fireclawthefox / NodeEditor

A simple generic Node Editor written with python and Panda3D
BSD 2-Clause "Simplified" License
12 stars 2 forks source link

Handle cyclic nodes. #9

Open janEntikan opened 2 years ago

janEntikan commented 2 years ago

When you make a cycle of nodes (connecting two nodes to eachother into a cycle) the editor crashes:

Traceback (most recent call last):
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/main.py", line 52, in <module>
    base.run()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/ShowBase.py", line 3328, in run
    self.taskMgr.run()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/task/Task.py", line 553, in run
    self.step()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/task/Task.py", line 504, in step
    self.mgr.poll()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/EventManager.py", line 49, in eventLoopTask
    self.doEvents()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/EventManager.py", line 43, in doEvents
    processFunc(dequeueFunc())
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/EventManager.py", line 99, in processEvent
    messenger.send(eventName, paramList)
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/Messenger.py", line 337, in send
    self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/Messenger.py", line 422, in __dispatch
    result = method (*(extraArgs + sentArgs))
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/Sockets/SocketBase.py", line 70, in endPlug
    base.messenger.send("connectPlugs")
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/Messenger.py", line 337, in send
    self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/showbase/Messenger.py", line 422, in __dispatch
    result = method (*(extraArgs + sentArgs))
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 276, in connectPlugs
    self.updateConnectedNodes(outSocketNode)
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 326, in updateConnectedNodes
    self.__updateConnectedNodes(leaveNode)
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 337, in __updateConnectedNodes
    self.__updateConnectedNodes(connector.socketB.node)
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 337, in __updateConnectedNodes
    self.__updateConnectedNodes(connector.socketB.node)
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 337, in __updateConnectedNodes
    self.__updateConnectedNodes(connector.socketB.node)
  [Previous line repeated 972 more times]
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/NodeManager.py", line 336, in __updateConnectedNodes
    connector.socketB.node.logic()
  File "/home/tuvok/Panda3d/FRAME/NodeEditor/Panda3DNodeEditor/NodeCore/Nodes/TestOutNode.py", line 38, in logic
    self.inputList[0].text["text"] = str(self.inputList[0].getValue())
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/DirectGuiBase.py", line 446, in __setitem__
    self.configure(**{key: value})
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/DirectGuiBase.py", line 442, in configure
    func()
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/DirectFrame.py", line 99, in setText
    self[component + '_text'] = text
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/DirectGuiBase.py", line 446, in __setitem__
    self.configure(**{key: value})
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/DirectGuiBase.py", line 435, in configure
    func(**options)
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/OnscreenText.py", line 553, in configure
    setter(value)
  File "/home/tuvok/Blender/3.1/python/lib/python3.10/site-packages/direct/gui/OnscreenText.py", line 285, in setText
    if sys.version_info >= (3, 0):
RecursionError: maximum recursion depth exceeded in comparison

The easy way out is to disallow cyclic structures and stick to a tree structure (blender colors one connection line red). For things like a non-linear story editor, having cyclic nodes would be very interesting.

fireclawthefox commented 2 years ago

Just committed some changes so that creating cyclic connections won't result in a crash anymore and will highlight the problematic connection instead.

I still want to enable cyclic connections for some nodes that can actually make use of that, so I'm not closing the issue yet. Though, I'm not sure how to handle the logic part since that would mean it'd still end up in a too deep recursion exception. So there has to be a limit or alternatively the logic will not be handled by the actual logic processing in the node editor. That way it'd be more of a visual representation for cyclic connections.

It might help to see an actual example for a cyclic connection to implement more specific details but that'd also require having nodes that could actually be connected in a cycle in a meaningful way.