Skip to content

Commit e6b7d26

Browse files
committed
context visibility setup... youc an click on some nodes to "enter them" and keep creating nodes "inside" of it...
1 parent 7e879d2 commit e6b7d26

File tree

5 files changed

+121
-5
lines changed

5 files changed

+121
-5
lines changed

src/Editor.ts

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,63 @@ export class Editor {
3131
private _ctx:CanvasRenderingContext2D;
3232
private mouseDrag = false;
3333
private focusedChild :Node|undefined;
34+
35+
/**
36+
* We are editing nodes inside of this node.
37+
* Undefined would be top-most nodes
38+
* It is an array to support recursive nesting, like folders in a computer
39+
*/
40+
private weAreInsideOf:Node[] = [];
41+
42+
/**
43+
* The node in which we are inside of...
44+
*/
45+
get contextNode() {
46+
return this.weAreInsideOf.length? this.weAreInsideOf[ this.weAreInsideOf.length-1 ] : undefined;
47+
}
48+
49+
enterNode( node:Node ) {
50+
if( node.canHanveChilds )
51+
{
52+
this.weAreInsideOf?.push( node );
53+
this.refilterNodes();
54+
}
55+
else
56+
{
57+
throw new Error(`Node ${node.nodeName} can't have childrens.`);
58+
}
59+
}
60+
61+
exitCurrentNode() {
62+
if( this.contextNode )
63+
{
64+
this.weAreInsideOf.pop();
65+
this.refilterNodes();
66+
}
67+
}
68+
69+
/**
70+
* Return `true` only if the node is in context.
71+
*/
72+
protected nodeIsInContext( node:Node )
73+
{
74+
return this.contextNode==node.childOf;
75+
}
76+
77+
protected get objsInContext() {
78+
return this.objs.filter( node=>this.nodeIsInContext(node) );
79+
}
80+
81+
protected refilterNodes() {
82+
83+
}
84+
85+
/**
86+
* Used to know what node is under the mouse on click events....
87+
* Will be used to tell if a user double clicked a node or not....
88+
*/
89+
private nodeUnderMouse:Node|undefined;
90+
3491
private mouse:Vector2Like = {x:0, y:0}
3592
private aspectCorrection = 1;
3693
private canvasAspect:number;
@@ -149,7 +206,7 @@ export class Editor {
149206
//
150207
// check if some prop wants to handle the wheel...
151208
//
152-
for (const obj of this.objs) {
209+
for (const obj of this.objsInContext) {
153210
if( mouseWheelCaptured(obj, cursor, ev.deltaY) )
154211
return;
155212
// if( obj.traverse( elem=>{
@@ -181,6 +238,7 @@ export class Editor {
181238
canvas.addEventListener('mousemove', (event) => {
182239

183240
this.mouseMoved = true;
241+
this.nodeUnderMouse = undefined;
184242

185243
let scale = this.ctx.getTransform().a; // Get the current scale (assuming uniform scaling)
186244
const mousePos = this.getMousePos( event);
@@ -276,7 +334,9 @@ export class Editor {
276334
//
277335
// let's see if some canvas element wants to capture the mouse....
278336
//
279-
for (const obj of this.zSortedObjs) {
337+
for (const obj of this.zSortedObjs) {
338+
339+
if(!this.nodeIsInContext(obj)) continue;
280340

281341
//#region OUTLET
282342
//
@@ -334,6 +394,7 @@ export class Editor {
334394
{
335395
// default... will make the object move...
336396
this.focusedChild = obj;
397+
this.nodeUnderMouse = obj;
337398
this.bingToTop(obj);
338399

339400
break; //<-- to avoid processing childrens under us....
@@ -542,6 +603,8 @@ export class Editor {
542603
}
543604

544605
node.editor = this;
606+
node.childOf = this.contextNode;
607+
545608
this.objs.push( node );
546609
this.zSortedObjs.unshift(node);
547610

@@ -723,7 +786,14 @@ export class Editor {
723786
let dotPos:Vector2Like|undefined;
724787

725788
//#region draw connections
726-
this.connections.forEach( connection=>{
789+
this.connections
790+
791+
//
792+
// this is enough since a connection can't point to a node in another context...
793+
//
794+
.filter( connection=>this.nodeIsInContext(connection.from.owner) )
795+
796+
.forEach( connection=>{
727797

728798
const from = this.global2canvas({x:connection.from.globalX, y:connection.from.globalY });
729799

@@ -978,7 +1048,7 @@ export class Editor {
9781048

9791049
const ctx = this._ctx;
9801050

981-
this.objs.forEach( node => {
1051+
this.objsInContext.forEach( node => {
9821052

9831053
const objLeft = node.x;
9841054
const objRight = node.x + node.width(ctx);
@@ -1011,6 +1081,11 @@ export class Editor {
10111081

10121082
this.zSortedObjs.forEach( obj=>{
10131083

1084+
//
1085+
// dont render if not enabled.
1086+
//
1087+
if( !this.nodeIsInContext(obj) ) return;
1088+
10141089
ctx.save();
10151090

10161091
obj.selected = this.selectedNodes.includes(obj)
@@ -1030,7 +1105,17 @@ export class Editor {
10301105
requestAnimationFrame(()=>this.start());
10311106
}
10321107

1033-
protected showNodeCreationMenu( ev:MouseEvent ) {
1108+
protected showNodeCreationMenu( ev:MouseEvent ) {
1109+
1110+
if( this.nodeUnderMouse ) {
1111+
1112+
if( this.nodeUnderMouse.canHanveChilds )
1113+
{
1114+
this.enterNode(this.nodeUnderMouse)
1115+
}
1116+
return;
1117+
};
1118+
10341119
const at = this.getCanvasMousePosition(this.mouse ); ;
10351120

10361121
createNewNode( ev.clientX, ev.clientY, newNode => {

src/EditorNodes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Theme } from "./colors/Theme";
22
import { UVNode } from "./nodes/attribute/UVNode";
33
import { tslInputNodes } from "./nodes/input/TslInputNode";
44
import { ValueNode } from "./nodes/input/ValueNode";
5+
import { FunctionNode } from "./nodes/logic/FunctionNode";
56
import { Node } from "./nodes/Node";
67
import { mathFunctions, mathOperations } from "./nodes/operators/list";
78
import { methodsDefinitions2NodeClassDefinitions } from "./nodes/operators/MethodCallNode";
@@ -36,6 +37,15 @@ export const NodeTypes : NodeGroupType[] = [
3637
...tslInputNodes
3738
]
3839
},
40+
{
41+
group:"Logic",
42+
color:Theme.config.groupLogic as string,
43+
nodes: [
44+
{
45+
TypeClass:FunctionNode, name:"Function", id:"fn"
46+
}
47+
]
48+
},
3949
{
4050
group:"Operators",
4151
color:Theme.config.groupMath as string,

src/colors/Theme.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class Theme {
3535
readonly groupOutput : FillStyle = "#3c1d26";
3636
readonly groupAttribute:FillStyle = "#83314a";
3737
readonly groupShader:FillStyle = "#2b652b";
38+
readonly groupLogic:FillStyle = "#203c3c";
3839

3940
readonly barBgColor : FillStyle = "#545454";
4041
readonly barFillColor : FillStyle = "#4772b3";

src/nodes/Node.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export class Node extends LayoutElement implements IScript {
1111

1212
editor!:Editor;
1313
canBeDeleted = true;
14+
15+
/**
16+
* A win node can have child windows...
17+
*/
18+
public childOf?:Node;
19+
20+
protected _canHaveChilds?:boolean;
21+
get canHanveChilds() { return this._canHaveChilds; }
1422

1523
/**
1624
* Mostly used to visually show a sign that this node is selected

src/nodes/logic/FunctionNode.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Theme } from "../../colors/Theme";
2+
import { Output } from "../../properties/Output";
3+
import { WinNode } from "../WinNode";
4+
5+
export class FunctionNode extends WinNode {
6+
constructor() {
7+
super("Function", Theme.config.groupLogic,[
8+
new Output( "return", 0)
9+
] );
10+
this._canHaveChilds = true;
11+
}
12+
}

0 commit comments

Comments
 (0)