Programming a path generator

 

In this tutorial, we are going to create an editor such that a user can create paths in the viewport.

First, use the SAMSON Element Generator to create a new SAMSON Element called Path containing:

  • An Editor class called Editor (full name: SEPathEditor). This class will make it possible for the user to add new nodes to the path.
  • A Visual Model class called VisualModel (full name: SEPathVisualModel). This will be the main class used to represent a path in the viewport and the document.
  • A Node class called NodeĀ (full name: SEPathNode). This class will be used to represent path nodes. The corresponding GUI class will be used to interact with the node.

Preliminaries

Let’s do a few things to set up our SAMSON Element.

First, since we want the user to create paths through the editor contained in our SAMSON Element, we are going to hide from SAMSON most other classes. Precisely, we need to remove from the descriptor of the SAMSON Element all the classes that we do not want to expose, and only keep the ones that will be directly useful to the user, i.e. the editor itself and the node GUI. Thus, remove lines from SEPathDescriptor.cpp such that you obtain:

Then, modify the getDescription function of SEPathEditor.cpp to provide a user-friendly name for the editor:

And don’t forget the tooltip:

Since we do not need a GUI for the editor itself, we remove it from the constructor and the destructor of the editor in SEPathEditor.cpp:

Path nodes

In this tutorial, a path will be composed of path nodes connected by straight lines.

We need each path node to store its position so, at the beginning of SEPathNode.hpp, we include SBVector3.hpp which contains the declarations of all physical vectors:

and in the end of the class declaration, we add this position and its accessors:

and we define these accessors in SEPathNode.cpp:

Finally, we modify the declaration of the path node constructor in SEPathNode.hpp to accept a position:

and we modify the constructor accordingly in SEPathNode.cpp:

Finally, we modify the constructor descriptor in SEPathNodeDescriptor.hpp:

Paths

We need paths to hold a list of path nodes, so we include SEPathNode.hpp at the beginning of SEPathVisualModel.hpp:

and we add such a list at the end of the class declaration, as well as functions to manage it:

and we define these functions in SEPathVisualModel.cpp:

Note that we use SAMSON pointers to manage this list, as we should whenever we want to hold references to persistent SAMSON objects.

Finally, we need to display the path based on the list of path nodes, so we modify the display function:

Editor

The editor needs to hold a pointer to the path that’s currently being created, so we include SEPathVisualModel.hpp at the beginning of SEPathEditor.hpp:

and we store a SAMSON pointer to the path at the end of the editor class declaration:

This path pointer will be non-zero whenever we are creating or editing a path, and will be zero otherwise. So we need to make sure that we reset this pointer to zero whenever we begin and end editing in SEPathEditor.cpp (i.e. when the user changes the active editor):

and we also make it possible for a user to stop the current path by pressing the Escape key:

We now want to create path nodes when we release the mouse button in the viewport. To achieve this, we modify the mouseReleaseEvent function in SEPathEditor.cpp:

Moving existing nodes

In order to make path nodes movable, we first need to make them selectable in the viewport. To achieve this, we modify the displayForSelection function in SEPathVisualModel.cpp to render node indices instead of colors:

Then, we declare a pointer to a selected node in SEPathEditor.hpp:

and we modify the editor to clean the pointer’s value when necessary:

and:

Then, we determine whether the user clicks on a path node during a mouse press event in SEPathEditor.cpp:

Note that we only get nodes which have the same class name and the same element UUID, so we’re sure that we can cast to SEPathNode*.

Finally, if a path node is selected, we move it when the user moves the mouse:

and we unselect the node when the user releases the mouse button by modifying the mouseReleaseEvent function:

Conclusion

We would need a few more things to make this SAMSON Element more user-friendly: make actions undoable, being able to erase nodes, provide feedback when we click in the viewport to show the user where a node is about to be created, etc. This will be seen in an upcoming part.

 
If you have any questions or feedback, please use the SAMSON forum.

Comments are closed.