-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNode.tsx
More file actions
112 lines (107 loc) · 3.25 KB
/
Node.tsx
File metadata and controls
112 lines (107 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import nullthrows from "nullthrows";
import { useState } from "react";
import { theme } from "../../../../common/theme";
import { vector2 } from "../../../../common/vector2";
import type { CCNodeId } from "../../../../store/node";
import { useStore } from "../../../../store/react";
import ensureStoreItem from "../../../../store/react/error";
import { useNode } from "../../../../store/react/selectors";
import { useComponentEditorStore } from "../store";
import getCCComponentEditorRendererNodeGeometry from "./Node.geometry";
import CCComponentEditorRendererNodePin from "./NodePin";
export type CCComponentEditorRendererNodeProps = {
nodeId: CCNodeId;
};
const CCComponentEditorRendererNode = ensureStoreItem(
(props, store) => store.nodes.get(props.nodeId),
({ nodeId }: CCComponentEditorRendererNodeProps) => {
const { store } = useStore();
const node = useNode(nodeId);
const component = nullthrows(store.components.get(node.componentId));
const geometry = getCCComponentEditorRendererNodeGeometry(store, nodeId);
const componentEditorState = useComponentEditorStore()();
const [dragging, setDragging] = useState(false);
const [dragStartPosition, setDragStartPosition] = useState(vector2.zero);
const [previousNodePosition, setPreviousNodePosition] = useState(
vector2.zero,
);
const handlePointerDown = (e: React.PointerEvent) => {
componentEditorState.selectNode([nodeId], true);
setDragStartPosition(vector2.fromDomEvent(e.nativeEvent));
setPreviousNodePosition(node.position);
setDragging(true);
e.currentTarget.setPointerCapture(e.pointerId);
};
const handlePointerMove = (e: React.PointerEvent) => {
if (dragging) {
store.nodes.update(nodeId, {
position: vector2.add(
previousNodePosition,
vector2.mul(
vector2.sub(
vector2.fromDomEvent(e.nativeEvent),
dragStartPosition,
),
componentEditorState.perspective.scale,
),
),
});
}
};
const handlePointerUp = (e: React.PointerEvent) => {
setDragging(false);
e.currentTarget.releasePointerCapture(e.pointerId);
};
return (
<>
<g
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
onContextMenu={(e) => {
e.preventDefault();
componentEditorState.selectNode([nodeId], true);
componentEditorState.openContextMenu(e);
}}
>
<text
fill={theme.palette.textPrimary}
x={geometry.x}
y={geometry.y - 5}
textAnchor="bottom"
fontSize={12}
>
{component.name}
</text>
<rect
x={geometry.x}
y={geometry.y}
width={geometry.width}
height={geometry.height}
fill={theme.palette.white}
stroke={
componentEditorState.selectedNodeIds.has(nodeId)
? theme.palette.primary
: theme.palette.textPrimary
}
strokeWidth={2}
rx={2}
/>
</g>
{store.nodePins.getManyByNodeId(nodeId).map((nodePin) => {
const position = nullthrows(
geometry.nodePinPositionById.get(nodePin.id),
);
return (
<CCComponentEditorRendererNodePin
key={nodePin.id}
nodePinId={nodePin.id}
position={position}
/>
);
})}
</>
);
},
);
export default CCComponentEditorRendererNode;