This guide demonstrates how to create sophisticated parameter layouts in VoidX. For real-world applications, structured organization is crucial, often requiring nested folders and subfolders for easy navigation. VoidX employs a hierarchical tree structure, allowing you to organize parameters and folders logically. This translates into a user-friendly interface, both directly on your device and within the VoidX-Control companion app. We’ll walk you through the process.
Folder types
VoidX organizes its structure using three distinct folder types: HFolder (Horizontal Folder), VFolder (Vertical Folder), and SFolder (System Folder). Each type plays a unique role in how your parameters are visually and logically arranged. To create these folders, you define a ParameterItem and set its ‘itemType’ to ‘hfolder’, ‘vfolder’, or ‘sfolder’, respectively. Let’s explore the specifics of each folder type.
HFolder: Horizontal Folders
HFolders organize content using a tab-based layout, ideal for dividing your application into distinct, top-level sections. Let’s demonstrate this by expanding our BasicDelay example to include a multi-effect chain, incorporating both the delay and a volume manager, each in its own tab.
The class constructor is where we establish the hierarchical structure. We start by creating the HFolder nodes, and then add the parameters as child elements within those HFolders.
All parameter declarations accessed using ‘this->’ are defined within the class header file, ‘BasicDelayEvents.hpp’. Please consult this file for complete information.
/* Create hfolders for high-level logical division. */
NodeItem * delayFolder = new NodeItem(parent, "delay", "Delay", "", "hfolder");
NodeItem * outputFolder = new NodeItem(parent, "output", "Output Mix", "", "hfolder");
/* Create parameter nodes inside the "Delay" folder. */
this->mix = new NodeFloat(delayFolder, "mix", "Mix", 0.0f, 100.0f, 50.0f, "%", 0.5f, false, 0);
this->feedback = new NodeFloat(delayFolder, "fdbk", "Feedback", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);
this->timeNode = new NodeFloat(delayFolder, "time", "Time", 20.0f, 1000.0f, 100.0f, "ms", 0.5f, false, 0);
/* Create the volume node inside the "Output Mix" folder. */
this->volume = new NodeFloat(outputFolder, "vol", "Volume", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);
To enhance our control, let’s add an on/off switch to the delay folder, allowing users to easily enable or disable the delay effect with a single click. We can accomplish this by creating a NodeEnum parameter named ‘on_off’, with ‘ON’ and ‘OFF’ as its only options, and placing it as the first child within the delay HFolder.
/* Create hfolders for high-level logical division. */
NodeItem * delayFolder = new NodeItem(parent, "delay", "Delay", "", "hfolder");
NodeItem * outputFolder = new NodeItem(parent, "output", "Output Mix", "", "hfolder");
/* Create parameter nodes inside the "Delay" folder. */
this->onOffDelay = new NodeEnum(delayFolder, "on_off", "Enable", {"ON", "OFF"}, "OFF");
this->mix = new NodeFloat(delayFolder, "mix", "Mix", 0.0f, 100.0f, 50.0f, "%", 0.5f, false, 0);
this->feedback = new NodeFloat(delayFolder, "fdbk", "Feedback", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);
this->timeNode = new NodeFloat(delayFolder, "time", "Time", 20.0f, 1000.0f, 100.0f, "ms", 0.5f, false, 0);
/* Create the volume node inside the "Output Mix" folder. */
this->volume = new NodeFloat(outputFolder, "vol", "Volume", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);
Let’s talk about styling. VoidX provides flexible color customization, allowing you to set styles for individual nodes or entire app sections. When applied to a folder, the style is automatically inherited by all its child elements. For example, we can assign a blue color to the ‘Delay’ folder and a green color to the ‘Time’ parameter, creating a clear visual distinction. This is purely for illustrative purposes.
/* Create hfolders for high-level logical division. */
NodeItem * delayFolder = new NodeItem(parent, "delay", "Delay", "", "hfolder");
NodeItem * outputFolder = new NodeItem(parent, "output", "Output Mix", "", "hfolder");
delayFolder->setStyle("color:#0000FF;"); //BLUE color assigned to the "Delay" folder.
/* Create parameter nodes inside the "Delay" folder. */
this->onOffDelay = new NodeEnum(delayFolder, "on_off", "Enable", {"ON", "OFF"}, "OFF");
this->mix = new NodeFloat(delayFolder, "mix", "Mix", 0.0f, 100.0f, 50.0f, "%", 0.5f, false, 0);
this->feedback = new NodeFloat(delayFolder, "fdbk", "Feedback", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);
this->timeNode = new NodeFloat(delayFolder, "time", "Time", 20.0f, 1000.0f, 100.0f, "ms", 0.5f, false, 0);
timeNode->setStyle("color:#00FF00;"); //GREEN color assigned to the "Time" parameter.
/* Create the volume node inside the "Output Mix" folder. */
this->volume = new NodeFloat(outputFolder, "vol", "Volume", 0.0f, 1.0f, 0.5, "", 0.5f, false, 2);


This is how our parameter structure looks in VoidX-Control. Notice the ‘Delay’ folder’s ON/OFF switch. When OFF, the entire section appears disabled; when ON, the parameters become active. As intended, the ‘Delay’ folder is blue, while the ‘Time’ parameter is green, overriding the folder’s style. The ‘Output Mix’ folder, containing only a ‘Volume’ parameter, remains unaffected by the blue styling. Let’s add more to this folder!
VFolder: Vertical Folders
VFolders are ideal for grouping content into secondary sections with a collapsible vertical layout. We’ll use them to create an ‘Advanced’ section within the ‘Output Mix’ folder. Inside this ‘Advanced’ section, we’ll add a placeholder parameter for demonstration purposes.
Just like HFolders and all other VoidX nodes, VFolders are also capable of being styled.
Similar to HFolders, we can also add an ON/OFF toggle that controls the entire VFolder content. Let’s implement that now!
Let’s add the following code snippet immediately after the declaration of the ‘Volume’ parameter. That’s all it takes!
/* Create a VFolder for logical sub-division into the "Output Mix" folder. */
NodeItem * advancedFolder = new NodeItem(outputFolder, "advanced", "Advanced", "", "vfolder");
this->onOffAdvanced = new NodeEnum(advancedFolder, "on_off", "Enable", {"ON", "OFF"}, "OFF");
this->dummyAdvanced = new NodeFloat(advancedFolder, "dummyadv", "Dummy Advanced", 0.0f, 100.0f, 50.0f, "%", 0.5f, false, 0);



And here’s how it appears in VoidX-Control! You’ll see a vertically organized section that can be both expanded/collapsed and enabled/disabled.
There are three default functional modes for VFolders:
- To create a VFolder that is expanded by default, simply set the ‘itemType’ to ‘vfolder_to‘ during declaration.
- To create a VFolder that is collapsed by default, simply set the ‘itemType’ to ‘vfolder_tc‘ during declaration.
- To create a VFolder that is always expanded (can’t be collapsed), simply set the ‘itemType’ to ‘vfolder_av‘ during declaration.
Example: NodeItem * advancedFolder = new NodeItem(outputFolder, “advanced”, “Advanced”, “”, “vfolder_av”);
SFolder: System Folders
SFolders are designed to showcase system-level settings. A common use is for a ‘Settings’ section, housing high-level parameters that are infrequently adjusted and outside the core application workflow. In VoidX-Control, SFolders are accessed through the rightmost panel. On PC and Mac, this panel is always visible. On mobile devices, it’s accessed by scrolling right or using the upper-right menu icon.
The VoidX framework recognizes any child of the root node with ‘itemType’ set to ‘sfolder’ as an SFolder. Additionally, the ‘app’ node, which houses your application’s nodes, is inherently treated as an SFolder.
We’ll now create a ‘Setup’ SFolder. Inside this section, we’ll place a placeholder parameter for demonstration purposes.
Add the following code snippet. You can place it either before or after the existing parameter declarations. The order doesn’t matter since these are separate logical sections.
/* Create sfolder for system-level logical division. */
NodeItem * setupFolder = new NodeItem(root, "setup", "Setup", "", "sfolder");
this->dummySettings = new NodeFloat(setupFolder, "dummyset", "Useless Setting", 0.0f, 100.0f, 50.0f, "%", 0.5f, false, 0);


And here’s the result in VoidX-Control! We’ve successfully created a ‘Setup’ section with a placeholder parameter inside.
Note: common SFolder names, like ‘settings’, trigger specialized icons, such as the gear icon. Standard names, like our ‘setup’ SFolder, display the default left-arrow icon. Additionally, the ‘app’ SFolder is represented by a ‘Home’ icon.
Note: if no SFolders are explicitly declared, and the ‘app’ node is the only application section, there’s no need for a “System Folders” area. In this case, the whole section will not be displayed.
Global ON/OFF Parameter
A global ON/OFF parameter is a common feature in many applications. In our ‘BasicDelay’ example, it can be used to toggle the effect between bypassed and active. You can see it in the application’s upper menu within the ‘Setup content’ image. How was this parameter declared?
It’s straightforward! Similar to HFolders and VFolders, create a NodeEnum parameter named ‘on_off’, with ‘ON’ and ‘OFF’ as only options, and place it as the first child of the ‘app’ node. Use the following code snippet, ensuring ‘onoff’ is declared before any other ‘app’ child.
//Main ON-OFF Node
this->onOff = new NodeEnum(parent, "on_off", "Enable", {"ON", "OFF"}, "ON");
Just as with HFolders and VFolders, when you turn off the global ON/OFF parameter, the ‘app’ section’s content appears disabled.
Throughout this tutorial, we’ve delved into the intricacies of organizing VoidX nodes, empowering you to craft sophisticated parameter structures. We explored the techniques for building complex hierarchies, including nested folders and subfolders, to achieve intuitive and user-friendly layouts. Furthermore, we examined the application of styling, enabling you to visually differentiate sections and enhance the user interface with customized colors and aesthetics. Finally, we mastered the implementation of convincing ON/OFF behaviors for each section, providing users with clear and responsive control over their application’s functionality. With these skills now firmly in your grasp, we’re ready to embark on the next phase of our VoidX journey. Let’s proceed to the next tutorial, where we’ll build upon this foundation and explore even more advanced capabilities.