Skip to content

Commit eebcb7b

Browse files
chelproctaka231Rn86222
committed
multi-bit simulation
Co-authored-by: taka231 <[email protected]> Co-authored-by: Rn86222 <[email protected]>
1 parent 7d4048b commit eebcb7b

File tree

11 files changed

+307
-175
lines changed

11 files changed

+307
-175
lines changed

src/common/theme.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const theme = {
88
textPrimary: "#444444",
99
primary: "#009966",
1010
error: "#ff0000",
11+
border: "#bbbbbb",
1112
editorBackground: "#fafafa",
1213
editorGrid: "#dddddd",
1314
},
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { ChevronLeft, ChevronRight } from "@mui/icons-material";
2+
import { IconButton, Paper } from "@mui/material";
3+
import { useComponentEditorStore } from "../store";
4+
5+
export default function CCComponentEditorFrameControl() {
6+
const componentEditorState = useComponentEditorStore()();
7+
8+
if (componentEditorState.editorMode === "edit") return null;
9+
10+
return (
11+
<Paper
12+
sx={{
13+
position: "absolute",
14+
bottom: "40px",
15+
left: "calc(50% - 80px)",
16+
width: "160px",
17+
display: "flex",
18+
backgroundColor: "background.paper",
19+
borderRadius: "40px",
20+
}}
21+
elevation={3}
22+
>
23+
<IconButton
24+
size="large"
25+
disabled={componentEditorState.timeStep <= 0}
26+
onClick={() => {
27+
componentEditorState.setTimeStep(componentEditorState.timeStep - 1);
28+
}}
29+
>
30+
<ChevronLeft />
31+
</IconButton>
32+
<input
33+
style={{
34+
flex: 1,
35+
minWidth: 0,
36+
textAlign: "center",
37+
border: "none",
38+
outline: "none",
39+
fontSize: "20px",
40+
}}
41+
value={componentEditorState.timeStep + 1}
42+
onChange={(e) => {
43+
const value = Number.parseInt(e.target.value, 10);
44+
if (!Number.isNaN(value) && value > 0) {
45+
componentEditorState.setTimeStep(value - 1);
46+
}
47+
}}
48+
/>
49+
<IconButton
50+
size="large"
51+
onClick={() => {
52+
componentEditorState.setTimeStep(componentEditorState.timeStep + 1);
53+
}}
54+
>
55+
<ChevronRight />
56+
</IconButton>
57+
</Paper>
58+
);
59+
}
Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
1-
import { Edit, PlayArrow, SkipNext } from "@mui/icons-material";
1+
import { Edit, PlayArrow } from "@mui/icons-material";
22
import { Fab } from "@mui/material";
33
import { useComponentEditorStore } from "../store";
44

55
export default function CCComponentEditorViewModeSwitcher() {
66
const componentEditorState = useComponentEditorStore()();
77

88
return (
9-
<>
10-
<Fab
11-
style={{ position: "absolute", bottom: "40px", right: "40px" }}
12-
color="primary"
13-
onClick={() => {
14-
componentEditorState.setEditorMode(
15-
componentEditorState.editorMode === "edit" ? "play" : "edit",
16-
);
17-
componentEditorState.resetTimeStep();
18-
}}
19-
>
20-
{componentEditorState.editorMode === "edit" ? <PlayArrow /> : <Edit />}
21-
</Fab>
22-
{componentEditorState.editorMode === "play" && (
23-
<Fab
24-
style={{ position: "absolute", bottom: "40px", right: "120px" }}
25-
color="primary"
26-
onClick={() => componentEditorState.incrementTimeStep()}
27-
>
28-
<SkipNext />
29-
</Fab>
30-
)}
31-
</>
9+
<Fab
10+
style={{ position: "absolute", bottom: "40px", right: "40px" }}
11+
color="primary"
12+
onClick={() => {
13+
componentEditorState.setEditorMode(
14+
componentEditorState.editorMode === "edit" ? "play" : "edit",
15+
);
16+
componentEditorState.setTimeStep(0);
17+
}}
18+
>
19+
{componentEditorState.editorMode === "edit" ? <PlayArrow /> : <Edit />}
20+
</Fab>
3221
);
3322
}

src/pages/edit/Editor/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ComponentPropertyDialog } from "../../../components/ComponentPropertyDi
66
import type { CCComponentId } from "../../../store/component";
77
import { useStore } from "../../../store/react";
88
import CCComponentEditorContextMenu from "./components/ContextMenu";
9+
import CCComponentEditorFrameControl from "./components/FrameControl";
910
import CCComponentEditorGrid from "./components/Grid";
1011
import { CCComponentEditorNodePinPropertyEditor } from "./components/NodePinPropertyEditor";
1112
import CCComponentEditorTitleBar from "./components/TitleBar";
@@ -46,6 +47,7 @@ function CCComponentEditorContent({
4647
onEditorClose={onClose}
4748
/>
4849
<CCComponentEditorViewModeSwitcher />
50+
<CCComponentEditorFrameControl />
4951
<CCComponentEditorContextMenu onEditComponent={onEditComponent} />
5052
<CCComponentEditorNodePinPropertyEditor />
5153
{isComponentPropertyDialogOpen && (
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import nullthrows from "nullthrows";
2+
import { theme } from "../../../../common/theme";
3+
import type { CCNodePinId } from "../../../../store/nodePin";
4+
import { useStore } from "../../../../store/react";
5+
import { useComponentEditorStore } from "../store";
6+
import {
7+
stringifySimulationValue,
8+
wrappingIncrementSimulationValue,
9+
} from "../store/slices/core";
10+
import getCCComponentEditorRendererNodeGeometry from "./Node.geometry";
11+
export type CCComponentEditorRendererInputValueProps = {
12+
nodePinId: CCNodePinId;
13+
};
14+
export default function CCComponentEditorRendererInputValue({
15+
nodePinId,
16+
}: CCComponentEditorRendererInputValueProps) {
17+
const { store } = useStore();
18+
const componentEditorState = useComponentEditorStore()();
19+
const nodePin = nullthrows(store.nodePins.get(nodePinId));
20+
const interfaceComponentPin = nullthrows(
21+
store.componentPins.getByImplementation(nodePinId),
22+
);
23+
const type = interfaceComponentPin.type;
24+
25+
const nodePinValue =
26+
type === "input"
27+
? nullthrows(componentEditorState.getInputValue(interfaceComponentPin.id))
28+
: nullthrows(componentEditorState.getNodePinValue(nodePinId));
29+
const updateInputValue = () => {
30+
componentEditorState.setInputValue(
31+
interfaceComponentPin.id,
32+
wrappingIncrementSimulationValue(nodePinValue),
33+
);
34+
};
35+
36+
const nodePinPosition = nullthrows(
37+
getCCComponentEditorRendererNodeGeometry(
38+
store,
39+
nodePin.nodeId,
40+
).nodePinPositionById.get(nodePinId),
41+
);
42+
const direction = type === "input" ? -1 : 1;
43+
44+
return (
45+
<>
46+
<rect
47+
x={nodePinPosition.x - 15 + direction * (15 + 10)}
48+
y={nodePinPosition.y - 6}
49+
width={30}
50+
height={12}
51+
rx={6}
52+
ry={6}
53+
stroke={theme.palette.textPrimary}
54+
fill={theme.palette.white}
55+
strokeWidth={1}
56+
{...(type === "input"
57+
? {
58+
onPointerDown: updateInputValue,
59+
style: { cursor: "pointer" },
60+
}
61+
: {})}
62+
/>
63+
<text
64+
x={nodePinPosition.x + direction * (15 + 10)}
65+
y={nodePinPosition.y}
66+
fill={theme.palette.textPrimary}
67+
textAnchor="middle"
68+
dominantBaseline="middle"
69+
fontSize={10}
70+
dy={1}
71+
style={{ pointerEvents: "none" }}
72+
>
73+
{stringifySimulationValue(nodePinValue)}
74+
</text>
75+
</>
76+
);
77+
}

src/pages/edit/Editor/renderer/Node.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,12 @@ const CCComponentEditorRendererNode = ensureStoreItem(
9393
rx={2}
9494
/>
9595
</g>
96-
{store.nodePins.getManyByNodeId(nodeId).map((nodePin) => {
97-
const position = nullthrows(
98-
geometry.nodePinPositionById.get(nodePin.id),
99-
);
100-
return (
101-
<CCComponentEditorRendererNodePin
102-
key={nodePin.id}
103-
nodePinId={nodePin.id}
104-
position={position}
105-
/>
106-
);
107-
})}
96+
{store.nodePins.getManyByNodeId(nodeId).map((nodePin) => (
97+
<CCComponentEditorRendererNodePin
98+
key={nodePin.id}
99+
nodePinId={nodePin.id}
100+
/>
101+
))}
108102
</>
109103
);
110104
},

src/pages/edit/Editor/renderer/NodePin.tsx

Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,36 @@ import { CCConnectionStore } from "../../../../store/connection";
88
import type { CCNodePinId } from "../../../../store/nodePin";
99
import { useStore } from "../../../../store/react";
1010
import { useComponentEditorStore } from "../store";
11-
import type { SimulationValue } from "../store/slices/core";
1211
import { CCComponentEditorRendererConnectionCore } from "./Connection";
12+
import CCComponentEditorRendererInputValue from "./InputValue";
1313
import getCCComponentEditorRendererNodeGeometry from "./Node.geometry";
1414

1515
const NODE_PIN_POSITION_SENSITIVITY = 10;
1616

1717
export type CCComponentEditorRendererNodePinProps = {
1818
nodePinId: CCNodePinId;
19-
position: Vector2;
2019
};
2120
export const CCComponentEditorRendererNodePinConstants = {
2221
SIZE: 10,
2322
};
2423
export default function CCComponentEditorRendererNodePin({
2524
nodePinId,
26-
position,
2725
}: CCComponentEditorRendererNodePinProps) {
2826
const { store } = useStore();
2927
const componentEditorState = useComponentEditorStore()();
3028
const nodePin = nullthrows(store.nodePins.get(nodePinId));
3129
const node = nullthrows(store.nodes.get(nodePin.nodeId));
32-
const nodePins = store.nodePins.getManyByNodeId(node.id);
3330
const componentPin = nullthrows(
3431
store.componentPins.get(nodePin.componentPinId),
3532
);
3633

34+
const position = nullthrows(
35+
getCCComponentEditorRendererNodeGeometry(
36+
store,
37+
nodePin.nodeId,
38+
).nodePinPositionById.get(nodePinId),
39+
);
40+
3741
const [draggingState, setDraggingState] = useState<{
3842
cursorPosition: Vector2;
3943
nodePinPositionKDTree: KDTree<CCNodePinId>;
@@ -133,63 +137,13 @@ export default function CCComponentEditorRendererNodePin({
133137
const isSimulationMode = useComponentEditorStore()(
134138
(s) => s.editorMode === "play",
135139
);
136-
const hasNoConnection =
137-
store.connections.getConnectionsByNodePinId(nodePinId).length === 0;
138-
139-
const pinType = componentPin.type;
140-
const simulationValueToString = (simulationValue: SimulationValue) => {
141-
return simulationValue.reduce(
142-
(acm, currentValue) => acm + (currentValue === true ? "1" : "0"),
143-
"",
144-
);
145-
};
146-
const implementationComponentPin =
140+
const interfaceComponentPin =
147141
store.componentPins.getByImplementation(nodePinId);
148-
let nodePinValue: SimulationValue;
149-
let nodePinValueAsString: string | null = null;
150-
if (isSimulationMode && hasNoConnection) {
151-
if (
152-
implementationComponentPin &&
153-
implementationComponentPin.type === "input"
154-
) {
155-
nodePinValue = nullthrows(
156-
componentEditorState.getInputValue(
157-
implementationComponentPin.id,
158-
nodePins,
159-
),
160-
);
161-
} else {
162-
nodePinValue = nullthrows(
163-
componentEditorState.getNodePinValue(nodePinId),
164-
);
165-
}
166-
nodePinValueAsString = simulationValueToString(nodePinValue);
167-
}
168-
const updateInputValue = () => {
169-
if (
170-
!implementationComponentPin ||
171-
implementationComponentPin.type !== "input"
172-
)
173-
return;
174-
const updatedPinValue = [...nodePinValue];
175-
updatedPinValue[0] = !updatedPinValue[0];
176-
componentEditorState.setInputValue(
177-
implementationComponentPin?.id,
178-
updatedPinValue,
179-
);
180-
};
181142

182143
return (
183144
<>
184-
{nodePinValueAsString && (
185-
<text
186-
x={position.x - (pinType === "input" ? 15 : -8)}
187-
y={position.y}
188-
onPointerDown={updateInputValue}
189-
fill={theme.palette.textPrimary}
190-
>
191-
{nodePinValueAsString}
192-
</text>
145+
{isSimulationMode && interfaceComponentPin && (
146+
<CCComponentEditorRendererInputValue nodePinId={nodePinId} />
193147
)}
194148
<g {...draggableProps} style={{ cursor: "pointer" }}>
195149
<rect
@@ -229,10 +183,10 @@ export default function CCComponentEditorRendererNodePin({
229183
{
230184
input: CCComponentEditorRendererNodePinConstants.SIZE,
231185
output: -CCComponentEditorRendererNodePinConstants.SIZE,
232-
}[pinType]
186+
}[componentPin.type]
233187
}
234188
y={position.y}
235-
textAnchor={{ input: "start", output: "end" }[pinType]}
189+
textAnchor={{ input: "start", output: "end" }[componentPin.type]}
236190
dominantBaseline="central"
237191
fontSize={12}
238192
fill={theme.palette.textPrimary}

0 commit comments

Comments
 (0)