Lets you visually assemble one or more simple equations using Nodes and Connections.
Press a key to add a Node:
A for an Add Function,
S for a Subtract Function,
M for a Multiplication Function,
D for a Division Function,
I for an Integer Constant,
F for a Float Constant, and
O for an Output Function.
Click and drag from one Node's Input/Output to Another's Output/Input to build an equation. For example, click and drag from a Constant Node to either of the Operand Inputs on a Maths Function Node. Drag from a Constant or a Maths Function Node's Output to an Output Function Node's Input to connect them and show the result.
Move Nodes around by clicking on the body of a Node and dragging it around (for Constants click the border). While moving a Constant Node, press
A or
S to increment or decrement the value.
It's easiest just to run it and play with it.
set display mode desktop width(), desktop height(), 32, 1
sync on
sync rate 60
set text font "verdana"
set text to bold
set text size 20
// CONSTANTS
#constant cNode_AddFunc 0 ` A Node with this as it's Func property will perform an Addition.
#constant cNode_SubFunc 1 ` ... Subtraction.
#constant cNode_MulFunc 2 ` ... Multiplication.
#constant cNode_DivFunc 3 ` ... Division.
#constant cNode_IntCnst 4 ` This type of Node provides an Integer Constant.
#constant cNode_FloatCnst 5 ` ... Float Constant.
#constant cNode_OutFunc 6 ` This type of Node will output the value it has been passed to the Screen.
#constant cFlowState_Idle 0 ` Flowchart doing nothing.
#constant cFlowState_NewLink 1 ` Currently mouse is being used to draw a new link between nodes.
#constant cFlowState_Test 2 ` Flowchart currently running a test. (Unused)
#constant cFlowState_MoveNode 3 ` Moving a node with the mouse.
#constant cNodeConnector_None -1
#constant cNodeConnector_Parent 0
#constant cNodeConnector_Child 1
#constant cNodeConnector_Op1 2
#constant cNodeConnector_Op2 3
// TYPES
type tVec2D
X as integer
Y as integer
endtype
type tNodeExtPropMath
Op1Node as integer
Op2Node as integer
endtype
type tNode
Pos as tVec2D
Func as integer
Operator as tNodeExtPropMath
Parent as integer
iValue as integer
fValue as float
Exist as boolean
endtype
type tNodeStack
Node as integer
ParentValue as float
Op1Value as float
Op2Value as float
endtype
type tIn_Key
Value as integer
Old as integer
endtype
type tIn_KeyCode
Value as integer
Old as integer
Code as integer
endtype
// GLOBALS
global gIn_Mouse as tVec2D
global gIn_MouseMove as tVec2D
global gIn_MClick as tIn_Key
global gIn_NewNode_AddFunc as tIn_KeyCode : gIn_NewNode_AddFunc.Code = 30
global gIn_NewNode_SubFunc as tIn_KeyCode : gIn_NewNode_SubFunc.Code = 31
global gIn_NewNode_MulFunc as tIn_KeyCode : gIn_NewNode_MulFunc.Code = 50
global gIn_NewNode_DivFunc as tIn_KeyCode : gIn_NewNode_DivFunc.Code = 32
global gIn_NewNode_IntCnst as tIn_KeyCode : gIn_NewNode_IntCnst.Code = 23
global gIn_NewNode_FloatCnst as tIn_KeyCode : gIn_NewNode_FloatCnst.Code = 33
global gIn_NewNode_OutFunc as tIn_KeyCode : gIn_NewNode_OutFunc.Code = 24
global gFlowState as integer = cFlowState_Idle
global gNodeClicked as integer = -1
global gNodeConnectorClicked as integer = cNodeConnector_None
global gFlowClickedX as integer
global gFlowClickedY as integer
global gNode_Max as integer = 50
global gNode_Last as integer = -1
dim gNode(gNode_Max) as tNode
global gNodeChild_MaxChildren as integer = 10
dim gNodeChild(gNode_Max, gNodeChild_MaxChildren)
dim gNodeChild_LastChild(gNode_Max)
for n = 0 to gNode_Max : gNodeChild_LastChild(n) = -1 : next n
global gNodeStack_Error as boolean = 0
global gNodeStack_Max as integer = gNode_Max ` I think that's as much as it'll need >_>
global gNodeStack_Last as integer = -1
dim gNodeStack(gNodeStack_Max) as tNodeStack
// Add starting Nodes.
Node_NewIntCnst(5, screen width() * 0.2, screen height() * 0.4)
Node_NewIntCnst(2, screen width() * 0.2, screen height() * 0.6)
Node_NewAddFunc(screen width() * 0.4, screen height() * 0.4)
Node_NewMulFunc(screen width() * 0.5, screen height() * 0.4)
gIn_MouseMove.X = mousemovex()
gIn_MouseMove.Y = mousemovey()
// MAIN LOOP
do
// UPDATE INPUT.
gIn_MouseMove.X = mousex() - gIn_Mouse.X`mousemovex()
gIn_MouseMove.Y = mousey() - gIn_Mouse.Y`mousemovey()
gIn_Mouse.X = mousex()
gIn_Mouse.Y = mousey()
gIn_MClick.Old = gIn_MClick.Value
gIn_MClick.Value = mouseclick()
`gIn_NewNode_AddFunc = UpdateCodeKey(gIn_NewNode_AddFunc)
`gIn_NewNode_SubFunc = UpdateCodeKey(gIn_NewNode_SubFunc)
`gIn_NewNode_MulFunc = UpdateCodeKey(gIn_NewNode_MulFunc)
`gIn_NewNode_DivFunc = UpdateCodeKey(gIn_NewNode_DivFunc)
gIn_NewNode_AddFunc.Old = gIn_NewNode_AddFunc.Value : gIn_NewNode_AddFunc.Value = keystate(gIn_NewNode_AddFunc.Code)
gIn_NewNode_SubFunc.Old = gIn_NewNode_SubFunc.Value : gIn_NewNode_SubFunc.Value = keystate(gIn_NewNode_SubFunc.Code)
gIn_NewNode_MulFunc.Old = gIn_NewNode_MulFunc.Value : gIn_NewNode_MulFunc.Value = keystate(gIn_NewNode_MulFunc.Code)
gIn_NewNode_DivFunc.Old = gIn_NewNode_DivFunc.Value : gIn_NewNode_DivFunc.Value = keystate(gIn_NewNode_DivFunc.Code)
gIn_NewNode_IntCnst.Old = gIn_NewNode_IntCnst.Value : gIn_NewNode_IntCnst.Value = keystate(gIn_NewNode_IntCnst.Code)
gIn_NewNode_FloatCnst.Old = gIn_NewNode_FloatCnst.Value : gIn_NewNode_FloatCnst.Value = keystate(gIn_NewNode_FloatCnst.Code)
gIn_NewNode_OutFunc.Old = gIn_NewNode_OutFunc.Value : gIn_NewNode_OutFunc.Value = keystate(gIn_NewNode_OutFunc.Code)
// Draw Background.
box 0, 0, screen width(), screen height(), rgb(36, 36, 144), rgb(72, 64, 192), rgb(0, 192, 192), rgb(96, 192, 240)
// ADDING NODES.
if gFlowState = cFlowState_Idle
if gIn_NewNode_AddFunc.Value = 1 and gIn_NewNode_AddFunc.Old = 0 then Node_NewAddFunc(gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_SubFunc.Value = 1 and gIn_NewNode_SubFunc.Old = 0 then Node_NewSubFunc(gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_MulFunc.Value = 1 and gIn_NewNode_MulFunc.Old = 0 then Node_NewMulFunc(gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_DivFunc.Value = 1 and gIn_NewNode_DivFunc.Old = 0 then Node_NewDivFunc(gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_IntCnst.Value = 1 and gIn_NewNode_IntCnst.Old = 0 then Node_NewIntCnst(rnd(100), gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_FloatCnst.Value = 1 and gIn_NewNode_FloatCnst.Old = 0 then Node_NewFloatCnst(rnd(10000) * 0.01, gIn_Mouse.X, gIn_Mouse.Y)
if gIn_NewNode_OutFunc.Value = 1 and gIn_NewNode_OutFunc.Old = 0 then Node_NewOutFunc(gIn_Mouse.X, gIn_Mouse.Y)
endif
// HANDLE INPUT.
if gIn_MClick.Value = 1
if gIn_MClick.Old = 0
if gFlowState = cFlowState_Idle
Node_GetClicked(gIn_Mouse.X, gIn_Mouse.Y)
if gNodeClicked <> -1
if gNodeConnectorClicked <> cNodeConnector_None
gFlowClickedX = gIn_Mouse.X
gFlowClickedY = gIn_Mouse.Y
gFlowState = cFlowState_NewLink
else
gFlowState = cFlowState_MoveNode
endif
endif
endif
else
if gFlowState = cFlowState_MoveNode
gNode(gNodeClicked).Pos.X = gNode(gNodeClicked).Pos.X + gIn_MouseMove.X
gNode(gNodeClicked).Pos.Y = gNode(gNodeClicked).Pos.Y + gIn_MouseMove.Y
// while in move mode, constant values can be changed with Add/Sub keys
select gNode(gNodeClicked).Func
case cNode_IntCnst, cNode_FloatCnst
if gIn_NewNode_AddFunc.Value = 1 and gIn_NewNode_AddFunc.Old = 0
if gNode(gNodeClicked).Func = cNode_IntCnst : inc gNode(gNodeClicked).iValue : else : inc gNode(gNodeClicked).fValue : endif
endif
if gIn_NewNode_SubFunc.Value = 1 and gIn_NewNode_SubFunc.Old = 0
if gNode(gNodeClicked).Func = cNode_IntCnst : dec gNode(gNodeClicked).iValue : else : dec gNode(gNodeClicked).fValue : endif
endif
endcase
endselect
endif
endif
else
if gIn_Mclick.Old = 1
if gFlowState = cFlowState_NewLink
NodeClickedOld = gNodeClicked
NodeConnectorClickedOld = gNodeConnectorClicked
Node_GetClicked(gIn_Mouse.X, gIn_Mouse.Y)
if gNodeClicked <> -1 and gNodeConnectorClicked <> cNodeConnector_None
Node_Connect(NodeClickedOld, NodeConnectorClickedOld, gNodeClicked, gNodeConnectorClicked)
endif
gFlowState = cFlowState_Idle
else
if gFlowState = cFlowState_MoveNode then gFlowState = cFlowState_Idle
endif
endif
endif
// HANDLE NODES.
// easiest way is to iterate backwards from an Out Node.
gNodeStack_Last = -1
gNodeStack_Error = 0
for n = 0 to gNode_Last
if gNode(n).Func = cNode_OutFunc
if gNode(n).Parent <> -1
inc gNodeStack_Last
gNodeStack(gNodeStack_Last).Node = n
gNodeStack(gNodeStack_Last).ParentValue = HandleNodeChain(gNode(n).Parent)
// Perform Output Function
gNode(n).fValue = gNodeStack(gNodeStack_Last).ParentValue
// Remove Self from Stack
dec gNodeStack_Last
else
print "Error: Output Node " + str$(n) + " has no input!"
endif
endif
next n
// DRAW.
// Nodes.
if gNode_Last <> -1
for n = 0 to gNode_Last
select gNode(n).Func
case cNode_IntCnst, cNode_FloatCnst
if gNode(n).Func = cNode_IntCnst then Color = rgb(0, 160, 160) else Color = rgb(0, 170, 170)
fill circle gNode(n).Pos.X, gNode(n).Pos.Y, 36, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
fill circle gNode(n).Pos.X, gNode(n).Pos.Y, 32, Color
if gNode(n).Func = cNode_IntCnst then Label$ = str$(gNode(n).iValue) else Label$ = str$(gNode(n).fValue, 4)
center text gNode(n).Pos.X, gNode(n).Pos.Y - (text height(Label$) / 2), Label$
`text gNode(n).Pos.X, gNode(n).Pos.Y + 64, str$(gNodeChild(n, 0))
endcase
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc
Color = rgb(0, 160, 160)
// Title Bar
select gNode(n).Func
case cNode_AddFunc : Title$ = "Add" : endcase
case cNode_SubFunc : Title$ = "Sub" : endcase
case cNode_MulFunc : Title$ = "Mul" : endcase
case cNode_DivFunc : Title$ = "Div" : endcase
endselect
box gNode(n).Pos.X, gNode(n).Pos.Y, gNode(n).Pos.X + 80, gNode(n).Pos.Y + 20, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
text gNode(n).Pos.X, gNode(n).Pos.Y, Title$
// Body
box gNode(n).Pos.X, gNode(n).Pos.Y + 20, gNode(n).Pos.X + 80, gNode(n).Pos.Y + 80, Color
// Connectors: Op1, Op2, Out
box gNode(n).Pos.X, gNode(n).Pos.Y + 30, gNode(n).Pos.X + 10, gNode(n).Pos.Y + 40, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
box gNode(n).Pos.X, gNode(n).Pos.Y + 60, gNode(n).Pos.X + 10, gNode(n).Pos.Y + 70, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
box gNode(n).Pos.X + 70, gNode(n).Pos.Y + 45, gNode(n).Pos.X + 80, gNode(n).Pos.Y + 55, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
print gNode(n).Operator.Op1Node
print gNode(n).Operator.Op2Node
// Links.
if gNode(n).Operator.Op1Node <> -1
// Op1 Link.
select gNode(gNode(n).Operator.Op1Node).Func
case cNode_IntCnst, cNode_FloatCnst
line gNode(gNode(n).Operator.Op1Node).Pos.X, gNode(gNode(n).Operator.Op1Node).Pos.Y, gNode(n).Pos.X, gNode(n).Pos.Y + 35
endcase
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc
line gNode(gNode(n).Operator.Op1Node).Pos.X + 80, gNode(gNode(n).Operator.Op1Node).Pos.Y + 50, gNode(n).Pos.X, gNode(n).Pos.Y + 35
endcase
endselect
endif
if gNode(n).Operator.Op2Node <> -1
// Op2 Link.
select gNode(gNode(n).Operator.Op2Node).Func
case cNode_IntCnst, cNode_FloatCnst
line gNode(gNode(n).Operator.Op2Node).Pos.X, gNode(gNode(n).Operator.Op2Node).Pos.Y, gNode(n).Pos.X, gNode(n).Pos.Y + 65
endcase
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc
line gNode(gNode(n).Operator.Op2Node).Pos.X + 80, gNode(gNode(n).Operator.Op2Node).Pos.Y + 50, gNode(n).Pos.X, gNode(n).Pos.Y + 65
endcase
endselect
endif
endcase
case cNode_OutFunc
Color = rgb(160, 160, 0)
// Title Bar
box gNode(n).Pos.X, gNode(n).Pos.Y, gNode(n).Pos.X + 120, gNode(n).Pos.Y + 20, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
text gNode(n).Pos.X, gNode(n).Pos.Y, "Out"
// Body
box gNode(n).Pos.X, gNode(n).Pos.Y + 20, gNode(n).Pos.X + 120, gNode(n).Pos.Y + 80, Color
center text gNode(n).Pos.X + 60, gNode(n).Pos.Y + 50 - (text height("A") / 2), str$(gNode(n).fValue, 4)
// Connector: Parent
box gNode(n).Pos.X, gNode(n).Pos.Y + 45, gNode(n).Pos.X + 10, gNode(n).Pos.Y + 55, rgb(rgbr(Color)/2, rgbg(Color)/2, rgbb(Color)/2)
// Link.
if gNode(n).Parent <> -1
select gNode(gNode(n).Parent).Func
case cNode_IntCnst, cNode_FloatCnst
line gNode(gNode(n).Parent).Pos.X, gNode(gNode(n).Parent).Pos.Y, gNode(n).Pos.X, gNode(n).Pos.Y + 50
endcase
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc
line gNode(gNode(n).Parent).Pos.X + 80, gNode(gNode(n).Parent).Pos.Y + 50, gNode(n).Pos.X, gNode(n).Pos.Y + 50
endcase
endselect
endif
endcase
endselect
next n
endif
// Draw New Link Line.
if gFlowState = cFlowState_NewLink
line gFlowClickedX, gFlowClickedY, gIn_Mouse.X, gIn_Mouse.Y
endif
sync
cls 0
loop
// FUNCTIONS
function Node_NewIntCnst(lValue, lX, lY)
Node_NewMathCnst(lValue, lValue, lX, lY, cNode_IntCnst)
endfunction
function Node_NewFloatCnst(lValue as float, lX, lY)
Node_NewMathCnst(lValue, lValue, lX, lY, cNode_FloatCnst)
endfunction
function Node_NewMathCnst(liValue, lfValue as float, lX, lY, lFunc)
local lNode as integer = -1
// Find a free Node to use.
lNode = Node_FindFree()
// Init the Node.
if lNode <> -1
Node_SetupNew(lNode)
gNode(lNode).Pos.X = lX
gNode(lNode).Pos.Y = lY
gNode(lNode).Func = lFunc
gNode(lNode).Parent = -1
gNode(lNode).Exist = 1
gNode(lNode).iValue = liValue
gNode(lNode).fValue = lfValue
endif
endfunction
function Node_NewAddFunc(lX, lY)
Node_NewMathFunc(lX, lY, cNode_AddFunc)
endfunction
function Node_NewSubFunc(lX, lY)
Node_NewMathFunc(lX, lY, cNode_SubFunc)
endfunction
function Node_NewMulFunc(lX, lY)
Node_NewMathFunc(lX, lY, cNode_MulFunc)
endfunction
function Node_NewDivFunc(lX, lY)
Node_NewMathFunc(lX, lY, cNode_DivFunc)
endfunction
function Node_NewMathFunc(lX, lY, lFunc)
local lNode as integer = -1
// Find a free Node to use.
lNode = Node_FindFree()
// Init the Node.
if lNode <> -1
Node_SetupNew(lNode)
gNode(lNode).Pos.X = lX
gNode(lNode).Pos.Y = lY
gNode(lNode).Func = lFunc
gNode(lNode).Parent = -1
gNode(lNode).Exist = 1
gNode(lNode).Operator.Op1Node = -1
gNode(lNode).Operator.Op2Node = -1
endif
endfunction
function Node_NewOutFunc(lX, lY)
local lNode as integer = -1
// Find a free Node to use.
lNode = Node_FindFree()
// Init the Node.
if lNode <> -1
Node_SetupNew(lNode)
gNode(lNode).Pos.X = lX
gNode(lNode).Pos.Y = lY
gNode(lNode).Func = cNode_OutFunc
gNode(lNode).Parent = -1
gNode(lNode).Exist = 1
endif
endfunction
function Node_SetupNew(lNode)
if lNode > gNode_Last then gNode_Last = lNode
endfunction
function Node_FindFree()
if gNode_Last = -1
// No Nodes; use first slot.
exitfunction 0
else
if gNode_Last = gNode_Max
// All Nodes taken; go home, get shouted at.
exitfunction -1
else
// Find the first available Node.
for n = 0 to gNode_Last
if gNode(n).Exist = 0 then exitfunction n
next n
exitfunction gNode_Last + 1
endif
endif
endfunction -1
function NodeChild_FindFree(lNode)
if gNodeChild_LastChild(lNode) = -1
// No Node Children; use first slot.
exitfunction 0
else
if gNodeChild_LastChild(lNode) = gNodeChild_MaxChildren
// All Node children taken; go home, get shouted at.
exitfunction -1
else
// Find the first available Node Child.
for n = 0 to gNodeChild_LastChild(lNode)
if gNodeChild(lNode, n) = -1 then exitfunction n
next n
exitfunction gNodeChild_LastChild(lNode) + 1
endif
endif
endfunction -1
function Node_DeleteChild(lNode, lChild)
if gNodeChild_LastChild(lNode) = lChild then dec gNodeChild_LastChild(lNode)
gNodeChild(lNode, lChild) = -1
endfunction
function Node_GetClicked(lX, lY)
local lNode as integer = -1
local lConnector as integer = cNodeConnector_None
for n = 0 to gNode_Last
if gNode(n).Exist = 1
select gNode(n).Func
case cNode_IntCnst, cNode_FloatCnst
if ((lX - gNode(n).Pos.X)*(lX - gNode(n).Pos.X)) + ((lY - gNode(n).Pos.Y)*(lY - gNode(n).Pos.Y)) < (32*32)
lNode = n
lConnector = cNodeConnector_Child
else
if ((lX - gNode(n).Pos.X)*(lX - gNode(n).Pos.X)) + ((lY - gNode(n).Pos.Y)*(lY - gNode(n).Pos.Y)) < (36*36)
lNode = n
lConnector = cNodeConnector_None
endif
endif
endcase
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc
if lX >= gNode(n).Pos.X and lY >= gNode(n).Pos.Y and lX <= gNode(n).Pos.X + 80 and lY <= gNode(n).Pos.Y + 80
lNode = n
lConnector = cNodeConnector_None
// get connector clicked
if lX >= gNode(n).Pos.X and lY >= gNode(n).Pos.Y + 30 and lX <= gNode(n).Pos.X + 10 and lY <= gNode(n).Pos.Y + 40 then lConnector = cNodeConnector_Op1
if lX >= gNode(n).Pos.X and lY >= gNode(n).Pos.Y + 60 and lX <= gNode(n).Pos.X + 10 and lY <= gNode(n).Pos.Y + 70 then lConnector = cNodeConnector_Op2
if lX >= gNode(n).Pos.X + 70 and lY >= gNode(n).Pos.Y + 45 and lX <= gNode(n).Pos.X + 80 and lY <= gNode(n).Pos.Y + 55 then lConnector = cNodeConnector_Child
endif
endcase
case cNode_OutFunc
if lX >= gNode(n).Pos.X and lY >= gNode(n).Pos.Y and lX <= gNode(n).Pos.X + 80 and lY <= gNode(n).Pos.Y + 80
lNode = n
lConnector = cNodeConnector_None
// get connector clicked
if lX >= gNode(n).Pos.X and lY >= gNode(n).Pos.Y + 45 and lX <= gNode(n).Pos.X + 10 and lY <= gNode(n).Pos.Y + 55 then lConnector = cNodeConnector_Parent
endif
endcase
endselect
endif
next n
gNodeClicked = lNode
gNodeConnectorClicked = lConnector
endfunction
function Node_Connect(lNodeA, lConnectorA, lNodeB, lConnectorB)
if lNodeA = lNodeB then exitfunction
// Check for a valid connection
select gNode(lNodeA).Func
// First Node is a Constant
case cNode_IntCnst, cNode_FloatCnst
select gNode(lNodeB).Func
// Second Node is a Maths Function
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc, cNode_OutFunc
select lConnectorB
// CONSTANT -> OP1
case cNodeConnector_Op1
Node_Connect_Cnst_To_Op(lNodeA, lNodeB, 1)
endcase
// CONSTANT -> OP2
case cNodeConnector_Op2
Node_Connect_Cnst_To_Op(lNodeA, lNodeB, 2)
endcase
// CONSTANT -> INPUT
case cNodeConnector_Parent
Node_Connect_Cnst_To_In(lNodeA, lNodeB)
endcase
endselect
endcase
endselect
endcase
// First Node is a Maths Function
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc, cNode_OutFunc
select gNode(lNodeB).Func
// Second Node is a Constant
case cNode_IntCnst, cNode_FloatCnst
select lConnectorA
// OP1 -> CONSTANT
case cNodeConnector_Op1
Node_Connect_Cnst_To_Op(lNodeB, lNodeA, 1)
endcase
// OP2 -> CONSTANT
case cNodeConnector_Op2
Node_Connect_Cnst_To_Op(lNodeB, lNodeA, 2)
endcase
// INPUT -> CONSTANT
case cNodeConnector_Parent
Node_Connect_Cnst_To_In(lNodeB, lNodeA)
endcase
endselect
endcase
// Second Node is a Maths Function
case cNode_AddFunc, cNode_SubFunc, cNode_MulFunc, cNode_DivFunc, cNode_OutFunc
select lConnectorA
case cNodeConnector_Child
select lConnectorB
// OUTPUT -> OP1
case cNodeConnector_Op1
Node_Connect_Out_To_Op(lNodeA, lNodeB, 1)
endcase
// OUTPUT -> OP2
case cNodeConnector_Op2
Node_Connect_Out_To_Op(lNodeA, lNodeB, 2)
endcase
// OUTPUT -> INPUT
case cNodeConnector_Parent
Node_Connect_Out_To_In(lNodeA, lNodeB)
endcase
endselect
endcase
endselect
endcase
endselect
endcase
endselect
endfunction
function Node_Connect_Cnst_To_Op(lNodeA, lNodeB, lOp)
// Stop if connection already exists
if (lOp = 1 and gNode(lNodeB).Operator.Op1Node = lNodeA) or (lOp = 2 and gNode(lNodeB).Operator.Op2Node = lNodeA) then exitfunction
// Check if another connection was here before
if lOp = 1
if gNode(lNodeB).Operator.Op1Node <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Operator.Op1Node)
// Find the child slot in that node that references this node and delete it, so the old op1 node stops having this node as a child
if gNodeChild(gNode(lNodeB).Operator.Op1Node, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Operator.Op1Node, n)
next n
endif
else
if gNode(lNodeB).Operator.Op2Node <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Operator.Op2Node)
if gNodeChild(gNode(lNodeB).Operator.Op2Node, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Operator.Op2Node, n)
next n
endif
endif
// Make lNodeA Child be lNodeB.
lNodeAChild = NodeChild_FindFree(lNodeA)
gNodeChild(lNodeA, lNodeAChild) = lNodeB
// Make lNodeB Op be lNodeA.
if lOp = 1
gNode(lNodeB).Operator.Op1Node = lNodeA
else
gNode(lNodeB).Operator.Op2Node = lNodeA
endif
endfunction
function Node_Connect_Out_To_Op(lNodeA, lNodeB, lOp)
// Stop if connection already exists
if (lOp = 1 and gNode(lNodeB).Operator.Op1Node = lNodeA) or (lOp = 2 and gNode(lNodeB).Operator.Op2Node = lNodeA) then exitfunction
// Check if another connection was here before
if lOp = 1
if gNode(lNodeB).Operator.Op1Node <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Operator.Op1Node)
if gNodeChild(gNode(lNodeB).Operator.Op1Node, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Operator.Op1Node, n)
next n
endif
else
if gNode(lNodeB).Operator.Op2Node <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Operator.Op2Node)
if gNodeChild(gNode(lNodeB).Operator.Op2Node, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Operator.Op2Node, n)
next n
endif
endif
// Make lNodeA Child to be lNodeB.
lNodeAChild = NodeChild_FindFree(lNodeA)
gNodeChild(lNodeA, lNodeAChild) = lNodeB
// Make lNodeB Op be lNodeA.
if lOp = 1
gNode(lNodeB).Operator.Op1Node = lNodeA
else
gNode(lNodeB).Operator.Op2Node = lNodeA
endif
endfunction
function Node_Connect_Cnst_To_In(lNodeA, lNodeB)
// Stop if connection already exists
if gNode(lNodeB).Parent = lNodeA then exitfunction
// Check if another connection was here before
if gNode(lNodeB).Parent <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Parent)
if gNodeChild(gNode(lNodeB).Parent, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Parent, n)
next n
endif
// Make lNodeA Child be lNodeB.
lNodeAChild = NodeChild_FindFree(lNodeA)
gNodeChild(lNodeA, lNodeAChild) = lNodeB
// Make lNodeB Parent be lNodeA.
gNode(lNodeB).Parent = lNodeA
endfunction
function Node_Connect_Out_To_In(lNodeA, lNodeB)
// Stop if connection already exists
if gNode(lNodeB).Parent = lNodeA then exitfunction
// Check if another connection was here before
if gNode(lNodeB).Parent <> -1
for n = 0 to gNodeChild_LastChild(gNode(lNodeB).Parent)
if gNodeChild(gNode(lNodeB).Parent, n) = lNodeB then Node_DeleteChild(gNode(lNodeB).Parent, n)
next n
endif
// Make lNodeA Child be lNodeB.
lNodeAChild = NodeChild_FindFree(lNodeA)
gNodeChild(lNodeA, lNodeAChild) = lNodeB
// Make lNodeB Parent be lNodeA.
gNode(lNodeB).Parent = lNodeA
endfunction
`function HandleNodeChain(lNodeA)
` local lValue as float
` exitfunction lValue+0.0
`endfunction 0
`remstart
function HandleNodeChain(lNodeA)
local lNodeB
local lValue as float
select gNode(lNodeA).Func
case cNode_IntCnst : lValue = gNode(lNodeA).iValue : exitfunction lValue : endcase
case cNode_FloatCnst : lValue = gNode(lNodeA).fValue : exitfunction lValue : endcase
case cNode_AddFunc
if gNode(lNodeA).Operator.Op1Node <> -1 and gNode(lNodeA).Operator.Op2Node <> -1
// Add Self to Stack and Get Input Values
inc gNodeStack_Last
gNodeStack(gNodeStack_Last).Node = lNodeA
gNodeStack(gNodeStack_Last).Op1Value = HandleNodeChain(gNode(lNodeA).Operator.Op1Node)
gNodeStack(gNodeStack_Last).Op2Value = HandleNodeChain(gNode(lNodeA).Operator.Op2Node)
// Perform Addition
lValue = gNodeStack(gNodeStack_Last).Op1Value + gNodeStack(gNodeStack_Last).Op2Value
// Remove Self from Stack
dec gNodeStack_Last
exitfunction lValue
else
print "Error: Addition Function Node " + str$(n) + " is missing one or more Operands!"
gNodeStack_Error = 1
`dec gNodeStack_Last
exitfunction lValue
endif
endcase
case cNode_SubFunc
if gNode(lNodeA).Operator.Op1Node <> -1 and gNode(lNodeA).Operator.Op2Node <> -1
// Add Self to Stack and Get Input Values
inc gNodeStack_Last
gNodeStack(gNodeStack_Last).Node = lNodeA
gNodeStack(gNodeStack_Last).Op1Value = HandleNodeChain(gNode(lNodeA).Operator.Op1Node)
gNodeStack(gNodeStack_Last).Op2Value = HandleNodeChain(gNode(lNodeA).Operator.Op2Node)
// Perform Subtraction
lValue = gNodeStack(gNodeStack_Last).Op1Value - gNodeStack(gNodeStack_Last).Op2Value
// Remove Self from Stack
dec gNodeStack_Last
exitfunction lValue + 0.0
else
print "Error: Subtraction Function Node " + str$(n) + " is missing one or more Operands!"
gNodeStack_Error = 1
`dec gNodeStack_Last
exitfunction 0.0
endif
endcase
case cNode_MulFunc
if gNode(lNodeA).Operator.Op1Node <> -1 and gNode(lNodeA).Operator.Op2Node <> -1
// Add Self to Stack and Get Input Values
inc gNodeStack_Last
gNodeStack(gNodeStack_Last).Node = lNodeA
gNodeStack(gNodeStack_Last).Op1Value = HandleNodeChain(gNode(lNodeA).Operator.Op1Node)
gNodeStack(gNodeStack_Last).Op2Value = HandleNodeChain(gNode(lNodeA).Operator.Op2Node)
// Perform Addition
lValue = gNodeStack(gNodeStack_Last).Op1Value * gNodeStack(gNodeStack_Last).Op2Value
// Remove Self from Stack
dec gNodeStack_Last
exitfunction lValue + 0.0
else
print "Error: Multiplication Function Node " + str$(n) + " is missing one or more Operands!"
gNodeStack_Error = 1
`dec gNodeStack_Last
exitfunction 0.0
endif
endcase
case cNode_DivFunc
if gNode(lNodeA).Operator.Op1Node <> -1 and gNode(lNodeA).Operator.Op2Node <> -1
// Add Self to Stack and Get Input Values
inc gNodeStack_Last
gNodeStack(gNodeStack_Last).Node = lNodeA
gNodeStack(gNodeStack_Last).Op1Value = HandleNodeChain(gNode(lNodeA).Operator.Op1Node)
gNodeStack(gNodeStack_Last).Op2Value = HandleNodeChain(gNode(lNodeA).Operator.Op2Node)
// Perform Addition
if gNodeStack(gNodeStack_Last).Op2Value <> 0
lValue = gNodeStack(gNodeStack_Last).Op1Value / gNodeStack(gNodeStack_Last).Op2Value
// Remove Self from Stack
dec gNodeStack_Last
exitfunction lValue
else
print "Error: Division Function Node " + str$(n) + " attempting Divide by Zero!"
gNodeStack_Error = 1
dec gNodeStack_Last
exitfunction 0.0
endif
else
print "Error: Division Function Node " + str$(n) + " is missing one or more Operands!"
gNodeStack_Error = 1
`dec gNodeStack_Last
exitfunction 0.0
endif
endcase
endselect
endfunction lValue
`remend
`function UpdateCodeKey(lKey as tIn_KeyCode)
` lKey.Old = lKey.Value
` lKey.Value = keystate(lKey.Code)
`endfunction lKey