+54
-13
src/App.tsx
+54
-13
src/App.tsx
···
13
14
import * as keybinds from './keybinds';
15
import { listen } from "@tauri-apps/api/event";
16
17
let App = () => {
18
-
let [ selectedNode, setSelectedNode ] = createSignal<Node | null>(null);
19
20
let canvas!: HTMLCanvasElement;
21
let ctx: CanvasRenderingContext2D;
···
57
}
58
59
onMount(async () => {
60
-
NodeManager.Instance.HookTabChange(() => setSelectedNode(null));
61
62
ctx = canvas.getContext('2d')!;
63
···
100
}
101
102
if(clickedNode){
103
-
contextMenu.items = NodeContextMenu(clickedNode, selectedNode, setSelectedNode);
104
} else{
105
contextMenu.items = CanvasContextMenu;
106
}
···
121
return;
122
}
123
124
-
if(e.shiftKey){
125
-
// TODO: Multi-select
126
-
return;
127
-
}
128
-
129
if(contextMenu.visible){
130
let submenus: ContextMenu[] = [];
131
contextMenu.items.map(x => x.menu ? submenus.push(x.menu): null);
···
160
161
if(nodes){
162
nodes.map(node => {
163
-
node.selected = false;
164
165
if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale },
166
e.clientX, e.clientY,
···
220
221
movingNode = clickedNode;
222
223
-
if(clickedNode){
224
clickedNode.selected = true;
225
-
setSelectedNode(clickedNode);
226
}
227
228
isMouseDown = true;
···
230
}
231
232
canvas.onmousemove = ( e ) => {
233
if(isMouseDown){
234
if(isDrawing){
235
drawingTo = screenToWorldSpace(canvas, { x: offset[0], y: offset[1], scale }, e.clientX - 10 * scale, e.clientY - 10 * scale) as [ number, number ];
···
321
isMouseDown = false;
322
}
323
324
-
keybinds.load(selectedNode, setSelectedNode);
325
requestAnimationFrame(update);
326
327
let unlisten_0 = await listen('hide-window', () => {
···
378
379
return (
380
<>
381
<TabMenu />
382
-
<ControlBar node={selectedNode} lockMovement={( lock ) => lockMovement = lock} />
383
<canvas ref={canvas}/>
384
</>
385
);
···
13
14
import * as keybinds from './keybinds';
15
import { listen } from "@tauri-apps/api/event";
16
+
import { ConfirmationPopup } from "./components/ConfirmationPopup";
17
18
let App = () => {
19
+
let [ selectedNodes, setSelectedNodes ] = createSignal<Node[]>([]);
20
21
let canvas!: HTMLCanvasElement;
22
let ctx: CanvasRenderingContext2D;
···
58
}
59
60
onMount(async () => {
61
+
NodeManager.Instance.HookTabChange(() => setSelectedNodes([]));
62
63
ctx = canvas.getContext('2d')!;
64
···
101
}
102
103
if(clickedNode){
104
+
contextMenu.items = NodeContextMenu(clickedNode, selectedNodes, setSelectedNodes);
105
} else{
106
contextMenu.items = CanvasContextMenu;
107
}
···
122
return;
123
}
124
125
if(contextMenu.visible){
126
let submenus: ContextMenu[] = [];
127
contextMenu.items.map(x => x.menu ? submenus.push(x.menu): null);
···
156
157
if(nodes){
158
nodes.map(node => {
159
+
if(!e.shiftKey)node.selected = false;
160
161
if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale },
162
e.clientX, e.clientY,
···
216
217
movingNode = clickedNode;
218
219
+
if(!e.shiftKey){
220
+
if(clickedNode){
221
+
clickedNode.selected = true;
222
+
setSelectedNodes([ clickedNode ]);
223
+
} else{
224
+
setSelectedNodes([]);
225
+
}
226
+
} else{
227
clickedNode.selected = true;
228
+
229
+
let snodes = selectedNodes();
230
+
if(!snodes.find(x => x.id === clickedNode!.id)){
231
+
snodes.push(clickedNode);
232
+
clickedNode.selected = true;
233
+
234
+
setSelectedNodes(snodes);
235
+
}
236
}
237
238
isMouseDown = true;
···
240
}
241
242
canvas.onmousemove = ( e ) => {
243
+
if(e.shiftKey && isMouseDown){
244
+
let nodes = NodeManager.Instance.GetNodes();
245
+
let hoveredNode: Node | null = null;
246
+
247
+
if(nodes){
248
+
nodes.map(node => {
249
+
if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale },
250
+
e.clientX, e.clientY,
251
+
node.x - 20, node.y, node.w + 40, node.h
252
+
)){
253
+
hoveredNode = node;
254
+
return;
255
+
}
256
+
})
257
+
}
258
+
259
+
if(hoveredNode !== null){
260
+
let snodes = selectedNodes();
261
+
if(!snodes.find(x => x.id === hoveredNode!.id)){
262
+
snodes.push(hoveredNode);
263
+
264
+
// @ts-ignore
265
+
hoveredNode.selected = true;
266
+
setSelectedNodes(snodes);
267
+
}
268
+
}
269
+
270
+
return;
271
+
}
272
+
273
if(isMouseDown){
274
if(isDrawing){
275
drawingTo = screenToWorldSpace(canvas, { x: offset[0], y: offset[1], scale }, e.clientX - 10 * scale, e.clientY - 10 * scale) as [ number, number ];
···
361
isMouseDown = false;
362
}
363
364
+
keybinds.load(selectedNodes, setSelectedNodes);
365
requestAnimationFrame(update);
366
367
let unlisten_0 = await listen('hide-window', () => {
···
418
419
return (
420
<>
421
+
<ConfirmationPopup />
422
<TabMenu />
423
+
<ControlBar node={selectedNodes} lockMovement={( lock ) => lockMovement = lock} />
424
<canvas ref={canvas}/>
425
</>
426
);
+11
-2
src/ContextMenu/Node.tsx
+11
-2
src/ContextMenu/Node.tsx
···
3
import { PositionInfo } from "../renderer";
4
import { Node } from "../structs/node";
5
6
-
export let NodeContextMenu = ( clickedNode: Node, selectedNode: Accessor<Node | null>, setSelectedNode: Setter<Node | null> ) => [
7
{
8
text: "Delete Node",
9
clicked: ( _e: MouseEvent, _canvas: HTMLCanvasElement, _position: PositionInfo ) => {
···
20
})
21
22
let selected = selectedNode();
23
-
if(selected && clickedNode.id === selected.id)setSelectedNode(null);
24
25
NodeManager.Instance.RemoveNode(clickedNode!)
26
},
···
3
import { PositionInfo } from "../renderer";
4
import { Node } from "../structs/node";
5
6
+
export let NodeContextMenu = ( clickedNode: Node, selectedNode: Accessor<Node[]>, setSelectedNode: Setter<Node[]> ) => [
7
{
8
text: "Delete Node",
9
clicked: ( _e: MouseEvent, _canvas: HTMLCanvasElement, _position: PositionInfo ) => {
···
20
})
21
22
let selected = selectedNode();
23
+
for (let i = 0; i < selected.length; i++) {
24
+
let node = selected[i];
25
+
26
+
if(node.id === clickedNode.id){
27
+
selected.splice(i, 1);
28
+
setSelectedNode(selected);
29
+
30
+
break;
31
+
}
32
+
}
33
34
NodeManager.Instance.RemoveNode(clickedNode!)
35
},
+1
-1
src/components/ConfirmationPopup.tsx
+1
-1
src/components/ConfirmationPopup.tsx
+7
-7
src/components/ControlBar.tsx
+7
-7
src/components/ControlBar.tsx
···
9
import { NodeManager } from '../Mangers/NodeManager';
10
11
export interface ControlBarProps{
12
-
node: Accessor<Node | null>,
13
lockMovement: ( lock: boolean ) => void
14
}
15
···
20
21
return (
22
<div class="control-bar">
23
-
<For each={props.node()?.statics}>
24
{ ( item ) => {
25
let [ popupOpen, setPopupOpen ] = createSignal(false);
26
···
36
value={item.value || ''}
37
onChange={( el ) => {
38
let value = el.target.value;
39
-
let node = props.node()!;
40
41
item.value = value;
42
node.onStaticsUpdate(node);
···
54
value={item.value !== undefined ? item.value : ''}
55
onChange={( el ) => {
56
let value = el.target.value;
57
-
let node = props.node()!;
58
59
item.value = parseInt(value);
60
node.onStaticsUpdate(node);
···
72
value={item.value !== undefined ? item.value : ''}
73
onChange={( el ) => {
74
let value = el.target.value;
75
-
let node = props.node()!;
76
77
item.value = parseFloat(value);
78
node.onStaticsUpdate(node);
···
92
return addresses.map(x => x.address).filter(x => x.toLowerCase().includes(text.toLowerCase()));
93
}}
94
change={( text ) => {
95
-
let node = props.node()!;
96
97
item.value = text;
98
node.onStaticsUpdate(node);
···
118
}}
119
value={item.value}
120
changed={( value ) => {
121
-
let node = props.node()!;
122
123
item.value = value;
124
node.onStaticsUpdate(node);
···
9
import { NodeManager } from '../Mangers/NodeManager';
10
11
export interface ControlBarProps{
12
+
node: Accessor<Node[]>,
13
lockMovement: ( lock: boolean ) => void
14
}
15
···
20
21
return (
22
<div class="control-bar">
23
+
<For each={props.node()[0]?.statics}>
24
{ ( item ) => {
25
let [ popupOpen, setPopupOpen ] = createSignal(false);
26
···
36
value={item.value || ''}
37
onChange={( el ) => {
38
let value = el.target.value;
39
+
let node = props.node()[0]!;
40
41
item.value = value;
42
node.onStaticsUpdate(node);
···
54
value={item.value !== undefined ? item.value : ''}
55
onChange={( el ) => {
56
let value = el.target.value;
57
+
let node = props.node()[0]!;
58
59
item.value = parseInt(value);
60
node.onStaticsUpdate(node);
···
72
value={item.value !== undefined ? item.value : ''}
73
onChange={( el ) => {
74
let value = el.target.value;
75
+
let node = props.node()[0]!;
76
77
item.value = parseFloat(value);
78
node.onStaticsUpdate(node);
···
92
return addresses.map(x => x.address).filter(x => x.toLowerCase().includes(text.toLowerCase()));
93
}}
94
change={( text ) => {
95
+
let node = props.node()[0]!;
96
97
item.value = text;
98
node.onStaticsUpdate(node);
···
118
}}
119
value={item.value}
120
changed={( value ) => {
121
+
let node = props.node()[0]!;
122
123
item.value = value;
124
node.onStaticsUpdate(node);
+15
-14
src/keybinds.ts
+15
-14
src/keybinds.ts
···
4
5
let isKeyDown: any = {};
6
7
-
export let load = ( selectedNode: Accessor<Node | null>, setSelectedNode: Setter<Node | null> ) => {
8
// TODO: Copy / paste
9
// TODO: Add undo / redo -ing
10
···
15
16
switch(e.key){
17
case 'Delete':
18
-
let node = selectedNode();
19
-
if(!node)return;
20
21
-
node.inputs.map(input => {
22
-
input.connections.map(partner => {
23
-
partner.connections = partner.connections.filter(x => x != input);
24
})
25
-
})
26
27
-
node.outputs.map(output => {
28
-
output.connections.map(partner => {
29
-
partner.connections = partner.connections.filter(x => x != output);
30
-
})
31
-
})
32
33
-
setSelectedNode(null);
34
-
NodeManager.Instance.RemoveNode(node);
35
break;
36
case 's':
37
if(e.ctrlKey){
···
4
5
let isKeyDown: any = {};
6
7
+
export let load = ( selectedNode: Accessor<Node[]>, setSelectedNode: Setter<Node[]> ) => {
8
// TODO: Copy / paste
9
// TODO: Add undo / redo -ing
10
···
15
16
switch(e.key){
17
case 'Delete':
18
+
let nodes = selectedNode();
19
+
for(let node of nodes){
20
+
node.inputs.map(input => {
21
+
input.connections.map(partner => {
22
+
partner.connections = partner.connections.filter(x => x != input);
23
+
})
24
+
})
25
26
+
node.outputs.map(output => {
27
+
output.connections.map(partner => {
28
+
partner.connections = partner.connections.filter(x => x != output);
29
+
})
30
})
31
32
+
NodeManager.Instance.RemoveNode(node);
33
+
}
34
35
+
setSelectedNode([]);
36
break;
37
case 's':
38
if(e.ctrlKey){