Skip to content

Commit 0b141c1

Browse files
add hover / select / hightlight to frame title hud
1 parent 8184732 commit 0b141c1

7 files changed

Lines changed: 101 additions & 25 deletions

File tree

editor-packages/editor-canvas/canvas/canvas.tsx

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ const default_canvas_preferences: CanvsPreferences = {
4747
can_highlight_selected_layer: false,
4848
};
4949

50+
interface HovringNode {
51+
node: ReflectSceneNode;
52+
reason: "frame-title" | "raycast" | "external";
53+
}
54+
5055
export function Canvas({
5156
renderItem,
5257
onSelectNode,
@@ -68,12 +73,14 @@ export function Canvas({
6873
const [xy, setXY] = useState<[number, number]>(INITIAL_XY);
6974
const [isPanning, setIsPanning] = useState(false);
7075

76+
const node = (id) => designq.find_node_by_id_under_inpage_nodes(id, nodes);
77+
7178
const wshighlight = highlightedLayer
72-
? designq.find_node_by_id_under_inpage_nodes(highlightedLayer, nodes)
79+
? ({ node: node(highlightedLayer), reason: "external" } as HovringNode)
7380
: null;
7481

7582
const [hoveringLayer, setHoveringLayer] =
76-
useState<ReflectSceneNode | null>(wshighlight);
83+
useState<HovringNode | null>(wshighlight);
7784

7885
useEffect(() => {
7986
setHoveringLayer(wshighlight);
@@ -92,15 +99,33 @@ export function Canvas({
9299
offset: xy,
93100
margin: LAYER_HOVER_HIT_MARGIN,
94101
});
95-
setHoveringLayer(hovering);
102+
103+
if (!hovering) {
104+
if (
105+
hoveringLayer &&
106+
hoveringLayer.node &&
107+
hoveringLayer.reason === "frame-title"
108+
) {
109+
// skip
110+
} else {
111+
setHoveringLayer(null);
112+
}
113+
} else {
114+
setHoveringLayer({ node: hovering, reason: "raycast" });
115+
}
96116
};
97117

98118
const onPointerDown: OnPointerDownHandler = (state) => {
99119
if (isPanning || isZooming) {
100120
return;
101121
}
102122
if (hoveringLayer) {
103-
onSelectNode(hoveringLayer);
123+
switch (hoveringLayer.reason) {
124+
case "frame-title":
125+
case "raycast":
126+
onSelectNode(hoveringLayer.node);
127+
break;
128+
}
104129
} else {
105130
onClearSelection();
106131
}
@@ -176,23 +201,29 @@ export function Canvas({
176201
</DisableBackdropFilter>
177202
</CanvasTransformRoot>
178203
<HudSurface
179-
xy={xy}
204+
offset={xy}
180205
zoom={zoom}
181206
hide={is_canvas_transforming}
182207
readonly={readonly}
183208
labelDisplayNodes={nodes}
184209
selectedNodes={selected_nodes}
185210
highlights={
186-
hoveringLayer
211+
hoveringLayer?.node
187212
? (config.can_highlight_selected_layer
188-
? [hoveringLayer]
189-
: noduplicates([hoveringLayer], selected_nodes)
213+
? [hoveringLayer.node]
214+
: noduplicates([hoveringLayer.node], selected_nodes)
190215
).map((h) => ({
191216
id: h.id,
192217
xywh: [h.absoluteX, h.absoluteY, h.width, h.height],
193218
}))
194219
: []
195220
}
221+
onHoverNode={(id) => {
222+
setHoveringLayer({ node: node(id), reason: "frame-title" });
223+
}}
224+
onSelectNode={(id) => {
225+
onSelectNode(node(id));
226+
}}
196227
/>
197228
</>
198229
);

editor-packages/editor-canvas/canvas/hud-surface.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import { HoverOutlineHighlight, ReadonlySelectHightlight } from "../overlay";
22
import { FrameTitle } from "../frame-title";
33
import type { XY, XYWH } from "../types";
44

5+
interface HudControls {
6+
onSelectNode: (node: string) => void;
7+
onHoverNode: (node: string) => void;
8+
}
9+
510
/**
611
* minimum meta of displaying nodes for hud surface
712
*/
@@ -15,23 +20,25 @@ export interface DisplayNodeMeta {
1520
}
1621

1722
export function HudSurface({
18-
xy,
23+
offset,
1924
highlights,
2025
zoom,
2126
hide,
2227
labelDisplayNodes,
2328
selectedNodes,
2429
readonly,
30+
onSelectNode,
31+
onHoverNode,
2532
}: {
26-
xy: XY;
33+
offset: XY;
34+
zoom: number;
2735
highlights: { id: string; xywh: XYWH }[];
2836
labelDisplayNodes: DisplayNodeMeta[];
2937
selectedNodes: DisplayNodeMeta[];
30-
zoom: number;
3138
hide: boolean;
3239
readonly: boolean;
33-
}) {
34-
const [ox, oy] = xy;
40+
} & HudControls) {
41+
const [ox, oy] = offset;
3542
return (
3643
<div
3744
style={{
@@ -58,8 +65,19 @@ export function HudSurface({
5865
xy={absxy}
5966
wh={[node.width, node.height]}
6067
zoom={zoom}
61-
onHoverStart={() => {}}
62-
onHoverEnd={() => {}}
68+
onSelect={() => onSelectNode(node.id)}
69+
onHoverChange={(hv) => {
70+
if (hv) {
71+
onHoverNode(node.id);
72+
} else {
73+
onHoverNode(null);
74+
}
75+
}}
76+
highlight={
77+
!![...highlights, ...selectedNodes].find(
78+
(n) => n.id === node.id
79+
)
80+
}
6381
/>
6482
);
6583
})}

editor-packages/editor-canvas/frame-title/frame-title.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import React, { useState } from "react";
2+
import { useHover } from "@editor-ui/hooks";
13
import styled from "@emotion/styled";
24
import { color_frame_title } from "../theme";
35

@@ -7,8 +9,8 @@ export function FrameTitle({
79
wh,
810
zoom,
911
highlight = false,
10-
onHoverStart,
11-
onHoverEnd,
12+
onHoverChange,
13+
onSelect,
1214
}: {
1315
name: string;
1416
/**
@@ -21,18 +23,30 @@ export function FrameTitle({
2123
wh: [number, number];
2224
zoom: number;
2325
highlight?: boolean;
24-
onHoverStart?: () => void;
25-
onHoverEnd?: () => void;
26+
onHoverChange?: (hover: boolean) => void;
27+
onSelect?: () => void;
2628
}) {
2729
const [x, y] = xy;
2830
const [w, h] = wh;
2931
const view_height = 20;
3032

3133
const height_considered_y_transform = y - view_height;
3234

35+
const [hoverred, setHoverred] = useState(false);
36+
37+
const _onHoverChange = (hover) => {
38+
setHoverred(hover);
39+
onHoverChange?.(hover);
40+
};
41+
42+
const { hoverProps } = useHover({
43+
onHoverChange: _onHoverChange,
44+
});
45+
3346
return (
3447
<div
3548
id="frame-title"
49+
onClick={onSelect}
3650
style={{
3751
position: "fixed",
3852
width: w * zoom,
@@ -42,13 +56,16 @@ export function FrameTitle({
4256
cursor: "default",
4357
overflow: "hidden",
4458
transform: `translateX(${x}px) translateY(${height_considered_y_transform}px)`,
59+
display: "flex",
60+
flexDirection: "row",
4561
}}
46-
onMouseEnter={onHoverStart}
47-
onMouseLeave={onHoverEnd}
62+
{...hoverProps}
4863
>
4964
<TitleLabel
5065
color={
51-
highlight ? color_frame_title.highlight : color_frame_title.default
66+
highlight || hoverred
67+
? color_frame_title.highlight
68+
: color_frame_title.default
5269
}
5370
>
5471
{name}

editor-packages/editor-canvas/math/hovering-target.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// TODO:
2+
/**
3+
* if the array's order represents the reversed index (depth) set this to true.
4+
*/
5+
16
/**
27
* get the hovering target node from nested children tree.
38
* - ignore invisible nodes.

editor-packages/editor-canvas/overlay/outline-side.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export function OulineSide({
6262
width: d,
6363
height: d,
6464
opacity: 1,
65+
pointerEvents: "none",
6566
willChange: "transform",
6667
transformOrigin: "0px, 0px",
6768
transform: `translateX(${trans.x}px) translateY(${trans.y}px) translateZ(0px) scaleX(${l_scalex}) scaleY(${l_scaley})`,

editor-packages/editor-canvas/overlay/readonly-select-hightlight.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ export function ReadonlySelectHightlight({
1717
const dot_size = 4;
1818

1919
return (
20-
<>
20+
<div
21+
style={{
22+
pointerEvents: "none",
23+
}}
24+
>
2125
<>
2226
<ReadonlyHandle
2327
box={bbox}
@@ -112,7 +116,7 @@ export function ReadonlySelectHightlight({
112116
color={color_layer_readonly_highlight}
113117
/>
114118
</>
115-
</>
119+
</div>
116120
);
117121
}
118122

editor-packages/editor-canvas/theme/default-theme.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export const color_layer_highlight = "#0099ff";
2-
export const color_layer_readonly_highlight = "#FF12BD";
2+
export const color_layer_readonly_highlight = "#0099ff";
33
export const color_frame_title = {
44
default: "grey",
55
highlight: color_layer_highlight,

0 commit comments

Comments
 (0)