This integration now includes full support for VSTGUI's UIDescription system, which allows you to define your plugin UI layouts in XML files instead of hardcoding them in Rust code. This makes it much easier to iterate on UI designs without recompiling your plugin.
Create a file named ui.xml with your UI layout:
<?xml version="1.0" encoding="UTF-8"?>
<vstgui-description version="1">
<fonts>
<font id="title-font" name="Arial" size="16" bold="true"/>
<font id="label-font" name="Arial" size="12"/>
</fonts>
<colors>
<color id="dark-bg" red="40" green="40" blue="40" alpha="255"/>
<color id="text" red="230" green="230" blue="230" alpha="255"/>
</colors>
<templates>
<!-- Main editor view -->
<template name="Editor" size="400, 300" background-color="dark-bg">
<view class="CTextLabel" origin="20, 20" size="360, 30"
font-id="title-font" text="My Plugin" text-color="text"
text-alignment="center"/>
<!-- Your UI controls here -->
</template>
</templates>
</vstgui-description>use nih_plug_vstgui::{create_vstgui_editor, UIDescription, VSTGUIState};
use std::sync::Arc;
fn create_editor(editor_state: Arc<VSTGUIState>) -> Option<Box<dyn Editor>> {
create_vstgui_editor(editor_state, move |frame, _context| {
// Load the UI description
let ui_desc = UIDescription::new("path/to/ui.xml")?;
// Create the main view from the template
let root_view = ui_desc.create_view("Editor", None)?;
// Add it to the frame
frame.add_view(root_view.as_ptr())?;
})
}The UIDescription type wraps a loaded XML UI description and provides methods to interact with it.
pub fn new<P: AsRef<Path>>(xml_path: P) -> Result<Self, VSTGUIError>Creates a new UIDescription from an XML file. Returns an error if the file cannot be loaded or parsed.
pub fn create_view(
&self,
view_name: &str,
on_value_changed: Option<Box<dyn Fn(&str, f32)>>,
) -> Result<View, VSTGUIError>Creates a view from a UIDescription template. The view_name should match a <template> name in your XML file.
pub fn get_view(&self, view_name: &str) -> Result<View, VSTGUIError>Gets a previously created view by name. Useful if you've already created a view and need to reference it again.
pub fn find_control(&self, tag: &str) -> Result<Control, VSTGUIError>Finds a control by its tag. The tag must be defined in your XML UI description.
pub fn set_control_value(&self, tag: &str, value: f32) -> Result<(), VSTGUIError>Sets a control's value by its tag. Useful for updating UI elements from parameter changes.
pub fn get_control_value(&self, tag: &str) -> Result<f32, VSTGUIError>Gets a control's current value by its tag.
<vstgui-description>- Root element that wraps all UI definitions
Define reusable fonts:
<fonts>
<font id="title-font" name="Arial" size="16" bold="true" italic="false"/>
<font id="label-font" name="Arial" size="12"/>
</fonts>Define reusable colors:
<colors>
<color id="dark-bg" red="40" green="40" blue="40" alpha="255"/>
<color id="accent" red="255" green="140" blue="0" alpha="255"/>
</colors>Define UI templates (templates can be instantiated as views):
<templates>
<template name="Editor" size="400, 300" background-color="dark-bg">
<!-- View definitions -->
</template>
</templates>class- VSTGUI control class (e.g.,CTextLabel,CSlider,CCheckBox)origin- Position as "x, y"size- Size as "width, height"tag- Unique identifier for this control (string)text- Display textfont-id- Reference to a defined fonttext-color- Reference to a defined colorbackground-color- Reference to a defined colortext-alignment- "left", "center", or "right"min- Minimum value (for sliders)max- Maximum value (for sliders)default- Default value
CTextLabel- Static text displayCSlider- Horizontal slider controlCCheckBox- Checkbox controlCViewContainer- Container for grouping viewsCParamDisplay- Parameter value display- And all other standard VSTGUI control classes
See examples/src/editor_uidesc.rs and examples/src/ui.xml for a complete working example.
To run the example:
cargo build --example gain_gui_vstgui --features ui-description
cargo run --example gain_gui_vstgui --features ui-descriptionAll UIDescription operations return Result<T, VSTGUIError>. Common errors:
VSTGUIError::FailedToCreateUIDescription- XML file couldn't be loaded or parsedVSTGUIError::FailedToCreateView- Template name not found or view creation failedVSTGUIError::NotFound- Control with given tag not found
- UIDescription files are parsed once when loaded. Subsequent operations (creating views, finding controls) are relatively fast.
- Creating views from templates is a relatively expensive operation. Consider creating views once and reusing them.
- The memory footprint is minimal - parsed XML descriptions are kept in memory but typically occupy only a few KB.
Like all VSTGUI operations, UIDescription must be accessed only from the main/GUI thread. Attempts to use it from other threads will result in VSTGUIError::ThreadSafetyViolation errors in debug builds.
- Custom view classes (VSTGUI UIViewFactory) are not yet fully exposed through the Rust API
- Parameter binding (automatic synchronization with plugin parameters) is not yet implemented
- Scripting support (JavaScript in UIDescription) is not yet exposed
These can be added in future versions based on user demand.