Align influence lamps 40cm above the tallest hall frame.
Compute the highest allocated frame top per hall and place every influence lamp on that shared rail so markers line up across different canvas sizes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
cfee69c9a6
commit
f20f811f21
@@ -191,8 +191,8 @@ function galleryWallColors(movementColor?: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/** Height above frame top edge — keeps fixture out of the viewer's line of sight. */
|
||||
const INFLUENCE_LAMP_ABOVE_FRAME = 0.46;
|
||||
/** Clearance above the tallest frame in the hall for influence lamps (metres). */
|
||||
const INFLUENCE_LAMP_ABOVE_HIGHEST_M = 0.4;
|
||||
|
||||
type WallSide = 'back' | 'left' | 'right';
|
||||
|
||||
@@ -304,6 +304,20 @@ function frameOuterH(canvasH: number, reviewed: boolean): number {
|
||||
return canvasH + matBorder * 2 + rail;
|
||||
}
|
||||
|
||||
/** World Y of the top edge of the tallest allocated frame in the hall. */
|
||||
function highestPaintingTopY(segments: WallSegment[]): number {
|
||||
let maxTop = EYE_HEIGHT;
|
||||
for (const seg of segments) {
|
||||
for (let i = 0; i < seg.paintings.length; i++) {
|
||||
const slot = seg.slots[i];
|
||||
if (!slot) continue;
|
||||
const top = slot.position[1] + frameOuterH(slot.maxH, paintingIsReviewed(seg.paintings[i])) / 2;
|
||||
if (top > maxTop) maxTop = top;
|
||||
}
|
||||
}
|
||||
return maxTop;
|
||||
}
|
||||
|
||||
function layoutRow(paintings: Painting[], span: number) {
|
||||
const count = paintings.length;
|
||||
if (count === 0) return { slots: [], spanNeeded: span };
|
||||
@@ -803,17 +817,19 @@ function usePaintingTexture(urls: string[] | string | null) {
|
||||
}
|
||||
|
||||
function InfluencePictureLamp({
|
||||
frameHeight,
|
||||
matBorder,
|
||||
frameWorldY,
|
||||
lampWorldY,
|
||||
frameDepth,
|
||||
highlighted,
|
||||
}: {
|
||||
frameHeight: number;
|
||||
matBorder: number;
|
||||
/** Painting group world Y — local lamp offset = lampWorldY − frameWorldY. */
|
||||
frameWorldY: number;
|
||||
/** Shared hall rail: 40 cm above the tallest frame. */
|
||||
lampWorldY: number;
|
||||
frameDepth: number;
|
||||
highlighted: boolean;
|
||||
}) {
|
||||
const mountY = frameHeight / 2 + matBorder + INFLUENCE_LAMP_ABOVE_FRAME;
|
||||
const mountY = lampWorldY - frameWorldY;
|
||||
const glow = highlighted ? 1.6 : 1.15;
|
||||
const scale = 1.35;
|
||||
|
||||
@@ -918,6 +934,7 @@ function PaintingFrame({
|
||||
wallSide,
|
||||
imageRevision,
|
||||
caption,
|
||||
influenceLampWorldY,
|
||||
onClick,
|
||||
}: {
|
||||
painting: Painting;
|
||||
@@ -928,6 +945,7 @@ function PaintingFrame({
|
||||
wallSide: WallSide;
|
||||
imageRevision?: number;
|
||||
caption?: string;
|
||||
influenceLampWorldY: number;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
@@ -1018,8 +1036,8 @@ function PaintingFrame({
|
||||
|
||||
{hasInfluenceLinks && (
|
||||
<InfluencePictureLamp
|
||||
frameHeight={height}
|
||||
matBorder={matBorder}
|
||||
frameWorldY={position[1]}
|
||||
lampWorldY={influenceLampWorldY}
|
||||
frameDepth={frameDepth}
|
||||
highlighted={hovered}
|
||||
/>
|
||||
@@ -1505,6 +1523,10 @@ function ArtistHall({
|
||||
const hallLightScale = interiorStyle?.lightScale ?? 1;
|
||||
const wallRoughness = interiorStyle ? 0.75 : 0.92;
|
||||
const wallMetalness = interiorStyle ? 0.08 : 0.06;
|
||||
const influenceLampWorldY = useMemo(
|
||||
() => highestPaintingTopY(segments) + INFLUENCE_LAMP_ABOVE_HIGHEST_M,
|
||||
[segments]
|
||||
);
|
||||
|
||||
const wallMaterial = (color: string) => (
|
||||
<meshStandardMaterial color={color} roughness={wallRoughness} metalness={wallMetalness} />
|
||||
@@ -1752,6 +1774,7 @@ function ArtistHall({
|
||||
wallSide={seg.slots[i].side}
|
||||
imageRevision={imageRevisions?.[painting.id]}
|
||||
caption={showCaptions ? paintingWallCaption(painting) : undefined}
|
||||
influenceLampWorldY={influenceLampWorldY}
|
||||
onClick={() => onPaintingClick(painting.id)}
|
||||
/>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user