Skip to content

Commit ffbf74d

Browse files
committed
fix bugs of simulation
Co-authored-by: Takashi Nagatomi <taka231@users.noreply.github.com> Co-authored-by: Tatsuhiko Nagaya <chelproc@users.noreply.github.com>
1 parent af2a1fb commit ffbf74d

18 files changed

Lines changed: 266 additions & 283 deletions

src/App.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import { Box } from "@mui/material";
22
import { useState } from "react";
33
import "@pixi/math-extras";
44
import GlobalHeader from "./components/GlobalHeader";
5-
import { useStore } from "./store/react";
65
import type { CCComponentId } from "./store/component";
76
import EditPage from "./pages/edit";
87
import HomePage from "./pages/home";
98

109
export default function App() {
11-
const store = useStore();
1210
const [editedComponentId, setEditedComponentId] =
13-
useState<CCComponentId | null>(store.components.rootComponentId);
11+
useState<CCComponentId | null>(null);
1412

1513
return (
1614
<Box

src/pages/edit/Editor/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function CCComponentEditorContent({
4545
const rendererRef = useRef<CCComponentEditorRenderer>();
4646
const containerRef = useRef<HTMLDivElement>(null);
4747
const overlayAreaRef = useRef<HTMLDivElement>(null);
48-
const store = useStore();
48+
const { store } = useStore();
4949
const componentEditorStore = useComponentEditorStore();
5050
const componentEditorState = componentEditorStore();
5151
const component = store.components.get(componentId);

src/pages/edit/Editor/renderer/componentPin.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ type CCComponentEditorRendererComponentPinProps = {
2020
nodeId: CCNodeId; // TODO: this might be unnecessary
2121
pinId: CCComponentPinId;
2222
position: PIXI.Point;
23-
getPinValue: () => boolean[] | undefined;
2423
};
2524

2625
/**
@@ -43,8 +42,6 @@ export default class CCComponentEditorRendererComponentPin extends CCComponentEd
4342

4443
readonly #unsubscribeComponentEditorStore: () => void;
4544

46-
readonly #getPinValue: () => boolean[] | undefined;
47-
4845
#valueBoxWidth: number;
4946

5047
private static readonly drawingConstants = {
@@ -115,7 +112,6 @@ export default class CCComponentEditorRendererComponentPin extends CCComponentEd
115112
this.context.store.componentPins.on("didUpdate", (pin) => {
116113
if (pin.id === this.#componentPinId) this.render();
117114
});
118-
this.#getPinValue = props.getPinValue;
119115
this.render();
120116
}
121117

@@ -189,7 +185,9 @@ export default class CCComponentEditorRendererComponentPin extends CCComponentEd
189185
}
190186
return valueText;
191187
};
192-
const outputValue = this.#getPinValue();
188+
const outputValue = editorState.getComponentPinValue(
189+
this.#componentPinId
190+
);
193191
if (outputValue) {
194192
this.#pixiValueText.text = createValueText(outputValue);
195193
this.#valueBoxWidth =

src/pages/edit/Editor/renderer/connection.ts

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import nullthrows from "nullthrows";
33
import type { CCConnectionId } from "../../../../store/connection";
44
import type CCStore from "../../../../store";
55
import CCComponentEditorRendererNode from "./node";
6-
import type {
7-
ComponentEditorStore,
8-
EditorMode,
9-
SimulationValue,
10-
} from "../store";
6+
import type { EditorMode } from "../store";
7+
import CCComponentEditorRendererBase, {
8+
type CCComponentEditorRendererContext,
9+
} from "./base";
1110

1211
export type CCConnectionEndpoint = {
1312
nodeId: string;
@@ -20,7 +19,7 @@ const lineColor = 0x000000;
2019
/**
2120
* Class for rendering connection
2221
*/
23-
export default class CCComponentEditorRendererConnection {
22+
export default class CCComponentEditorRendererConnection extends CCComponentEditorRendererBase {
2423
#store: CCStore;
2524

2625
#connectionId: CCConnectionId;
@@ -42,12 +41,8 @@ export default class CCComponentEditorRendererConnection {
4241

4342
#offset: number;
4443

45-
#componentEditorStore: ComponentEditorStore;
46-
4744
#onDragStart: (e: PIXI.FederatedMouseEvent) => void;
4845

49-
#getPinValue: () => SimulationValue | undefined;
50-
5146
/**
5247
* Constructor of CCComponentEditorRendererConnection
5348
* @param store store
@@ -62,14 +57,13 @@ export default class CCComponentEditorRendererConnection {
6257
store: CCStore,
6358
connectionId: CCConnectionId,
6459
pixiParentContainer: PIXI.Container,
65-
componentEditorStore: ComponentEditorStore,
66-
onDragStart: (e: PIXI.FederatedMouseEvent) => void,
67-
getPinValue: () => SimulationValue | undefined
60+
context: CCComponentEditorRendererContext,
61+
onDragStart: (e: PIXI.FederatedMouseEvent) => void
6862
) {
63+
super(context);
6964
this.#store = store;
7065
this.#connectionId = connectionId;
7166
this.#onDragStart = onDragStart;
72-
this.#getPinValue = getPinValue;
7367
this.#pixiGraphics = {
7468
from: CCComponentEditorRendererConnection.#createGraphics(),
7569
middle: CCComponentEditorRendererConnection.#createGraphics(),
@@ -103,23 +97,25 @@ export default class CCComponentEditorRendererConnection {
10397
});
10498
const editValueText = (mode: EditorMode) => {
10599
if (mode === "play") {
106-
const value = this.#getPinValue()
107-
?.map((v) => (v ? "1" : "0"))
108-
.join("");
100+
const connection = this.#store.connections.get(this.#connectionId)!;
101+
const inputValue = this.context.componentEditorStore
102+
.getState()
103+
.getNodePinValue(connection.from)!;
104+
const value = inputValue.map((v) => (v ? "1" : "0")).join("");
109105
this.#pixiGraphics.value.text = value || "";
110106
this.#pixiGraphics.value.visible = true;
111107
} else {
112108
this.#pixiGraphics.value.visible = false;
113109
}
114110
};
115111
this.#pixiGraphics.from.on("mouseover", () => {
116-
editValueText(this.#componentEditorStore.getState().editorMode);
112+
editValueText(this.context.componentEditorStore.getState().editorMode);
117113
});
118114
this.#pixiGraphics.to.on("mouseover", () => {
119-
editValueText(this.#componentEditorStore.getState().editorMode);
115+
editValueText(this.context.componentEditorStore.getState().editorMode);
120116
});
121117
this.#pixiGraphics.middle.on("mouseover", () => {
122-
editValueText(this.#componentEditorStore.getState().editorMode);
118+
editValueText(this.context.componentEditorStore.getState().editorMode);
123119
});
124120
this.#pixiGraphics.from.on("mouseout", () => {
125121
this.#pixiGraphics.value.visible = false;
@@ -135,7 +131,6 @@ export default class CCComponentEditorRendererConnection {
135131
)!.bentPortion;
136132
this.#temporaryBentPortion = this.#bentPortionCache;
137133
this.#offset = 0;
138-
this.#componentEditorStore = componentEditorStore;
139134
this.#render();
140135
this.#store.nodes.on("didUpdate", this.#render);
141136
}
@@ -146,11 +141,11 @@ export default class CCComponentEditorRendererConnection {
146141
*/
147142
onPointerDown(e: PIXI.FederatedEvent) {
148143
if (
149-
!this.#componentEditorStore
144+
!this.context.componentEditorStore
150145
.getState()
151146
.selectedConnectionIds.has(this.#connectionId)
152147
) {
153-
this.#componentEditorStore
148+
this.context.componentEditorStore
154149
.getState()
155150
.selectConnection([this.#connectionId], false);
156151
}
@@ -204,7 +199,7 @@ export default class CCComponentEditorRendererConnection {
204199
/**
205200
* Destroy the connection
206201
*/
207-
destroy() {
202+
override destroy() {
208203
this.#pixiParentContainer.removeChild(this.#pixiGraphics.from);
209204
this.#pixiParentContainer.removeChild(this.#pixiGraphics.middle);
210205
this.#pixiParentContainer.removeChild(this.#pixiGraphics.to);
@@ -249,19 +244,17 @@ export default class CCComponentEditorRendererConnection {
249244
* Render the connection
250245
*/
251246
#render = () => {
247+
const connection = this.#store.connections.get(this.#connectionId);
248+
if (!connection) return;
252249
this.#pixiGraphics.from.clear();
253250
this.#pixiGraphics.middle.clear();
254251
this.#pixiGraphics.to.clear();
255252
this.#pixiGraphics.from.lineStyle(lineWidth, lineColor);
256253
this.#pixiGraphics.middle.lineStyle(lineWidth, lineColor);
257254
this.#pixiGraphics.to.lineStyle(lineWidth, lineColor);
258255
const endPointGap = 9;
259-
const fromEndPoint = nullthrows(
260-
this.#store.connections.get(this.#connectionId)?.from
261-
);
262-
const toEndPoint = nullthrows(
263-
this.#store.connections.get(this.#connectionId)?.to
264-
);
256+
const fromEndPoint = nullthrows(connection.from);
257+
const toEndPoint = nullthrows(connection.to);
265258
const fromPosition = CCComponentEditorRendererNode.getNodePinAbsolute(
266259
this.#store,
267260
fromEndPoint

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -417,19 +417,12 @@ export default class CCComponentEditorRenderer extends CCComponentEditorRenderer
417417
},
418418
};
419419
};
420-
const getPinValue = () => {
421-
const nodePinId = this.context.store.connections.get(connectionId)!.from;
422-
return this.context.componentEditorStore
423-
.getState()
424-
.getNodePinValue(nodePinId);
425-
};
426420
const newConnectionRenderer = new CCComponentEditorRendererConnection(
427421
this.context.store,
428422
connectionId,
429423
this.#pixiWorld,
430-
this.context.componentEditorStore,
431-
onDragStart,
432-
getPinValue
424+
this.context,
425+
onDragStart
433426
);
434427
this.#connectionRenderers.set(connectionId, newConnectionRenderer);
435428
}

src/pages/edit/Editor/renderer/node.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ export default class CCComponentEditorRendererNode extends CCComponentEditorRend
257257
const node = this.context.store.nodes.get(this.#nodeId);
258258
if (!node) return;
259259

260+
const parentComponent = this.context.store.components.get(
261+
node.parentComponentId
262+
)!;
263+
const parentComponentPins =
264+
this.context.store.componentPins.getManyByComponentId(parentComponent.id);
260265
const nodePins = this.context.store.nodePins.getManyByNodeId(this.#nodeId);
261266

262267
const existingComponentPinRenderers = new Map(this.#componentPinRenderers);
@@ -266,37 +271,34 @@ export default class CCComponentEditorRendererNode extends CCComponentEditorRend
266271
>();
267272
for (const nodePin of nodePins) {
268273
if (this.context.store.connections.hasNoConnectionOf(nodePin.id)) {
269-
const componentPin = this.context.store.componentPins.get(
270-
nodePin.componentPinId
274+
const parentComponentPin = parentComponentPins.find(
275+
(pin) => pin.implementation === nodePin.id
271276
)!;
272277
const existingComponentPinRenderer = existingComponentPinRenderers.get(
273-
componentPin.id
278+
parentComponentPin.id
274279
);
275280
if (existingComponentPinRenderer) {
276281
newComponentPinRenderers.set(
277-
componentPin.id,
282+
parentComponentPin.id,
278283
existingComponentPinRenderer
279284
);
280-
existingComponentPinRenderers.delete(componentPin.id);
285+
existingComponentPinRenderers.delete(parentComponentPin.id);
281286
} else {
282-
const getPinValue = () => {
283-
return this.context.componentEditorStore
284-
.getState()
285-
.getNodePinValue(nodePin.id);
286-
};
287287
const componentPinRenderer =
288288
new CCComponentEditorRendererComponentPin({
289289
context: this.context,
290290
pixiParentContainer: this.#pixiWorld,
291291
nodeId: this.#nodeId,
292-
pinId: componentPin.id,
292+
pinId: parentComponentPin.id,
293293
position: CCComponentEditorRendererNode.getPinOffset(
294294
this.context.store,
295295
nodePin.id
296296
),
297-
getPinValue,
298297
});
299-
newComponentPinRenderers.set(componentPin.id, componentPinRenderer);
298+
newComponentPinRenderers.set(
299+
parentComponentPin.id,
300+
componentPinRenderer
301+
);
300302
}
301303
}
302304
}

src/pages/edit/Editor/store/index.tsx

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type State = {
3131
setRangeSelect(rangeSelect: RangeSelect): void;
3232
selectedConnectionIds: Set<CCConnectionId>;
3333
inputValues: Map<InputValueKey, SimulationValue>;
34-
getInputValue(componentPinId: CCComponentPinId): SimulationValue | undefined;
34+
getInputValue(componentPinId: CCComponentPinId): SimulationValue;
3535
setInputValue(componentPinId: CCComponentPinId, value: SimulationValue): void;
3636
setEditorMode(mode: EditorMode): void;
3737
resetTimeStep(): void;
@@ -69,10 +69,21 @@ function createEditorStore(componentId: CCComponentId, store: CCStore) {
6969
selectedNodeIds: new Set(),
7070
rangeSelect: null,
7171
selectedConnectionIds: new Set(),
72+
/** @private */
7273
inputValues: new Map(),
73-
/** @deprecated */
7474
getInputValue(componentPinId: CCComponentPinId) {
75-
return this.inputValues.get(componentPinId);
75+
const value = this.inputValues.get(componentPinId);
76+
if (!value) {
77+
const multiplexability =
78+
store.componentPins.getComponentPinMultiplexability(componentPinId);
79+
if (multiplexability.isMultiplexable) {
80+
const newValue = [false];
81+
return newValue;
82+
}
83+
const newValue = new Array(multiplexability.multiplicity).fill(false);
84+
return newValue;
85+
}
86+
return value;
7687
},
7788
setInputValue(componentPinId: CCComponentPinId, value: SimulationValue) {
7889
set((state) => {
@@ -139,7 +150,9 @@ function createEditorStore(componentId: CCComponentId, store: CCStore) {
139150
},
140151
}));
141152

142-
const simulationHandler = () => {
153+
const executeSimulation = () => {
154+
if (editorStore.getState().editorMode !== "play") return;
155+
143156
const newSimulationCacheKey =
144157
store.nodes
145158
.toArray()
@@ -148,35 +161,42 @@ function createEditorStore(componentId: CCComponentId, store: CCStore) {
148161
store.connections
149162
.toArray()
150163
.map((connection) => connection.id)
164+
.join() +
165+
[...editorStore.getState().inputValues.entries()]
166+
.map(([key, value]) => key + value.join())
151167
.join();
152-
const editorState = editorStore.getState();
153168
if (newSimulationCacheKey !== simulationCacheKey) {
154169
simulationCacheKey = newSimulationCacheKey;
155170
simulationCachedFrames = [];
156171
}
172+
173+
const editorState = editorStore.getState();
174+
let isUpdated = false;
157175
for (
158176
let timeStep = simulationCachedFrames.length;
159177
timeStep <= editorState.timeStep;
160178
timeStep += 1
161179
) {
180+
console.log(timeStep);
162181
const previousFrame = simulationCachedFrames[timeStep - 1] ?? null;
163-
182+
const inputValues = new Map();
183+
const pins = store.componentPins.getManyByComponentId(componentId);
184+
for (const pin of pins) {
185+
inputValues.set(pin.id, editorState.getInputValue(pin.id));
186+
}
164187
simulationCachedFrames.push(
165-
simulateComponent(
166-
store,
167-
componentId,
168-
editorState.inputValues,
169-
previousFrame
170-
)!
188+
simulateComponent(store, componentId, inputValues, previousFrame)!
171189
);
190+
isUpdated = true;
172191
}
192+
if (isUpdated) editorStore.setState((s) => ({ ...s }));
173193
};
174-
store.nodes.on("didRegister", simulationHandler);
175-
store.nodes.on("didUpdate", simulationHandler);
176-
store.nodes.on("didUnregister", simulationHandler);
177-
store.connections.on("didRegister", simulationHandler);
178-
store.connections.on("didUnregister", simulationHandler);
179-
editorStore.subscribe(simulationHandler);
194+
store.nodes.on("didRegister", executeSimulation);
195+
store.nodes.on("didUpdate", executeSimulation);
196+
store.nodes.on("didUnregister", executeSimulation);
197+
store.connections.on("didRegister", executeSimulation);
198+
store.connections.on("didUnregister", executeSimulation);
199+
editorStore.subscribe(executeSimulation);
180200

181201
return editorStore;
182202
}
@@ -192,7 +212,7 @@ export function ComponentEditorStoreProvider({
192212
componentId: CCComponentId;
193213
children: React.ReactNode;
194214
}) {
195-
const store = useStore();
215+
const { store } = useStore();
196216
const [editorStore] = useState(() => createEditorStore(componentId, store));
197217
return <context.Provider value={editorStore}>{children}</context.Provider>;
198218
}

0 commit comments

Comments
 (0)