As you can see in the previous articles, an other recent important point on the application is the creation, management and display of the connections between the nodes.
For a better understanding, here is a simplified diagram, limited to the connection mechanism :
You can see that a connection is defined by two “clips”, the name we gave to the input and output points of the nodes. Each clip is identified with :
- nodeName : the name (= identifier) of the node he belongs to
- port : it’s a string indicating if the clip is an “input” or an “output”
- clipNumber : the number of the clip, usefull for the nodes with several sources. For an output clip, this property is always equal to 1 because a node can have only one output.
In fact, there isn’t any direct link between the node object and the connection object, which just knows the identifier of the correspondind node, so the connection doesn’t have a direct access to the node’s coordinates for example. It’s why the clip object also supplies it’s coordinates, updated each time the node is moved. Then the connection is able to expose the right coordinates to the QML view.
Concerning the display of the connections, there isn’t any Line or Curve type in QML, so we had to create a custom line type. This is a QdeclarativeItem written in python and allowing to draw a line between two points by rewriting the method paint().
Here is the result :
Thanks to signals between the data core, the wrappers and the QML view, all connections are updated in real time when a node is moved.
In order to improve the connections’ appearance, we are planning to replace the line items by Bézier curves, maybe using the QML object Canvas. This is what we have now :
See you soon for an other article !
Now that we plugged Tuttle into Buttle, we can access to the TuttleOFX utilities.
First, we added a TuttleGraph to the ButtleGraph in order to respect the new structure.
Then, we created a TuttleNode in CmdCreateNode.py and added in the ButtleNode a link to the TuttleNode . The ButtleNode is then added to the ButtleGraph (which contains the TuttleGraph) and we update the ButtleGraph.
The main part was to link the ButtleParam to the TuttleParam. In order to do that, we modified node.py in which the parameters were manually created. We separated the ButtleProperties (Name, Color, Coords) from the TuttleProperties (with the ParamObject.qml).
The attribute params of the node is an empty list. We fill it according to the type of the node. We created a mapTuttleParamToButtleParam in order to get the ParamObject corresponding to the TuttleType. Then, for all the parameters in the TuttleNode, we created the ParamObject in ButtleNode.params. The tricky part was to pick up the argument we need to build the ParamObject from Tuttle. We finally used if conditions in order to get the right arguments and to build ParamObject.
Now we have a pretty clear idea of the hierarchy of our project. That’s important, because soon we need to make the link between our application (Buttle), and Tuttle. Just to reminder, Tuttle will enable us to truly calculate the effect of the different nodes of the graph.
We made a class diagram (UML), in order to have a quick access to a common vision of the structure. It is an important tool, especially in our case because we code in Python. And in a python code, it’s hard to understand who is who, and who contains who, because the mechanism of pointer is hidden to the programmer.
The following diagram uses 4 colors, in order to separate the different layers we manipulated. So, from the core level, to the UI :
- red : tuttle
- blue : buttle core
- pink : buttle wrapper
- green : buttle data
- (and the grey class represents tools we use from one of our submodule : quick mamba).