- Startup screen
- Visualize an abstract graph
- Conditional structure layout improved
- Simpler graph
- Whole file edition / isolation mode
- Handle integers
- Improve reflection system
You don’t know Nodable? check this out: Nodable website
I will discuss about those features in two distinct parts and I will end with a small conclusion including potential future improvements.
For the users
A startup menu has been added to offer a single-click experience to a Nodable file. The user can create a file, open a file, or an example easily.
As soon as a file is open, a side panel is available to access help, file information, settings, and virtual machine UI.
Visualize an abstract graph
Nodable can generate an abstract graph, even if it is incomplete (missing declarations). This feature is useful to edit a program even if can’t (or doesn’t need to) be executed.
If we try to compile the abstract graph, we get an error regarding to the lack of declaration for f and g variables. You can notice we also got warnings during parsing phase.
The conditional structure’s layout has been improved to better understand what’s going on, even with multiple else.
In the previous figure, we can notice the last instruction at the very bottom could be positioned a bit lower to avoid crossing the green line, or we could draw green lines differently by using floating adjustable connectors (cf. Unreal blueprints).
To see more or less detail, I introduced the functionality expand/fold (double click). As you can see below, conditional blocs can be folded to adjust the level of details.
Edges and Variable references
In order to reduce the edge (referred as wire in previous versions of Nodable) count visible on the screen, I decided to hide edges when their length is too long. In such case, to keep the information visible I display the variable name in each inputs where it is connected to. Although, when the user selects a node, we always show the related edges. With that technique, the user gets detailed information only for the focused node.
The next figure shows another example to illustrate the importance of changing edge visibility depending on the context. The node msg is connected to 4 operators (in orange), displaying them constantly would reduce readability. But of course, when the user selects msg, it is useful to get such information.
Whole file edition / isolation mode
In the version 0.9 and inferior, Nodable was always focused on current selection (if any), or by default on the current line. Now, when a file is opened, the whole code is parsed, and if possible the abstract graph is generated and displayed.
User can still isolate selection using isolation mode toggle (
CTRL + I) or tool button:
If isolation mode is turned ON, we get the following behavior:
User can selected any portion to visualize its graph (and may compile and run it).
Nodable now handles 32bits integers. It may seem simple, but introducing integers from a software handling only double was not easy. Introducing a new number type involved to provide implicit cast to have a less verbose code and also to reuse existing (double-based) functions. I had to define how implicit cast would work and how to resolve function signatures.
In the next figure, we assign an integer (42) to the variable a which is a double. You can see in the graph, the literal 42 has a type int while variable d is a double.
After compiling and running, the variable d has the value 42 as a double.
Nodable now passes more complex tests, in the next figure you can see a conditional structure nested in a for a loop.
End to end tests
End to end tests can be run locally (hardware rendering) and on the GitHub CI (macOS, software rendering), reducing the number of manual operations required to test a minimum amount of the features.
In order to check which version of Nodable runs, the CMake script adds build information during the build configuration. Nodable is now aware of its tag and its git commit hash.
The version is accessible on the startup menu, easy to get the right version of the source code to debug.
In order to facilitate operator’s implementation binding (link a C++ function to a nodable function), I added a minimalist concept of operator ( symbol, type, and precedence). For example, in Fig. 1 I define the binary operator « + ». An operator is abstract, and is only useful to generate a correct graph, once we want to compile and run our program, we have to give an implementation for any couple of parameters we want to handle. You can see these implementations in Fig. 2. Then we bind the implementations to the operator by using the reflection system (highly inspired by RTTR), by specifying the function, the operator symbol, and the signature as arguments (since functions are polymorphic and/or uses templates, we have to give the exact signature).
This version of Nodable does not contains major features from a user’s perspective, however the source code has been refactored to adapt to many situations (polymorphism, native function binding). I didn’t mentioned it, but the source code is now divided in 2 big sub-projects: a framework and nodable. This helped to setup end-to-end tests involving GUI and will allow me to make more reusable code.
Since there is now a small application framework in the repository, I am thinking in developing many small tools involving nodes based on it in the future.
From a technical perspective, I would like to get rid of any getters/setters, inheritance, and smart pointers unless it is the only choice. I also see the limits of implementing my own parser and virtual machine, but I found out fun to learn it by practice, as my goal is not to make a production tool, I might want to continue this way…