NoesisGUI
 

🛠️ Integrating Noesis Studio

Because Noesis Studio is built natively on the core NoesisGUI architecture, it offers extensive flexibility. You can easily extend the editor with custom components, such as new controls or converters. Additionally, you can override its default rendering device to match your application's exact renderer, or even register new texture formats. Furthermore, the entire Studio environment can be embedded directly into your custom engine or proprietary toolset, providing a seamless and unified visual authoring experience for your team.

Note

The NoesisGUI SDK includes a practical sample application named StudioTool. This project is located alongside all the SDK samples and serves as a reference implementation, demonstrating exactly how to embed Noesis Studio within your own architecture.

This sample is the exact same vanilla Noesis Studio application available for download from our website.

Studio API Functions

The API for Noesis Studio allows loading a Studio project located on disk and creating its visual tree. This is done using the Noesis::Studio::Create function, which returns a FrameworkElement root. This root can then be rendered by putting it inside a view as explained in the Rendering Architecture tutorial.

Among the options that can be passed to Noesis::Studio::Create, configuring the Resource Providers is mandatory. Studio relies on these providers each time it needs to read resources from your project; if they are not set, Studio will be unable to load your assets.

The following code shows how to configure the providers and load the project located in the given path. The rest of the parameters in the Options structure are initialized to their default values; however, it is highly recommended to review the StudioOptions.h header to discover all available configuration options and callbacks:

#include <NsGui/Studio.h>
#include <NsApp/LocalXamlProvider.h>
#include <NsApp/LocalTextureProvider.h>
#include <NsApp/LocalFontProvider.h>

Ptr<FrameworkElement> GetProjectRootElement(const char* projectPath)
{
    Studio::Options options;

    options.GetXamlProvider = [](const char*, const char* path) -> Ptr<XamlProvider>
    {
        return MakePtr<LocalXamlProvider>(path);
    };

    options.GetTextureProvider = [](const char*, const char* path) -> Ptr<TextureProvider>
    {
        return MakePtr<LocalTextureProvider>(path);
    };

    options.GetFontProvider = [](const char*, const char* path) -> Ptr<FontProvider>
    {
        return MakePtr<LocalFontProvider>(path);
    };

    return Studio::Create(projectPath, options);
}

Additional API & Callbacks

Beyond the initial project creation, the Noesis::Studio::Options structure contains several delegates that allow your application to react to editor lifecycle and file system events. These include:

  • File Management: FileCreated, FileWritten, and FileMoved trigger whenever the user modifies the project files inside Studio.
  • State & Lifecycle: SaveStateChanged notifies you of pending unsaved changes, RegisterAssembly hooks into custom assembly loading, and Exit is invoked when Studio requests to close.
  • Environment: You can assign a parentWindow handle to integrate Studio seamlessly into your toolset's windowing system, and toggle the initial darkTheme state.

Once the Studio instance is running, the Noesis::Studio namespace provides essential utility functions to manage its state dynamically:

  • State Management: SaveAllChanges() and DiscardAllChanges() allow programmatic control over pending modifications.
  • Navigation: OpenProjectFile() instructs Studio to open a specific file from the project directory.
  • Cache Control: ClearTypeCache() and PopulateTypeCache() refresh the internal type system, which is crucial if you hot-reload custom components.
  • Theming: SetTheme() allows you to switch between light and dark modes at runtime to match your host application's aesthetic.

Extending Studio

Any custom components registered within your NoesisGUI application are automatically exposed to Noesis Studio. For instance, newly registered User Controls will seamlessly populate within the editor's palette.

To refine how these extensions are presented, such as assigning descriptive tooltips, custom icons, or grouping them into specific palette categories, you can leverage the metadata attributes defined in the StudioMeta.h header. These attributes allow deep customization of the design-time experience for any custom extension.

The following example demonstrates how to apply this metadata to the custom Star shape, which is a class provided by the Application Framework. This configures its category, icon, and specific property bounds for the editor's property grid:

#include <NsGui/StudioMeta.h>

NS_IMPLEMENT_REFLECTION(NoesisApp::Star, "NoesisGUIExtensions.Star")
{
    NsMeta<StudioOrder>(2000, "Shape");
    NsMeta<StudioDesc>("Renders a star shape with variable number of points");
    NsMeta<StudioHelpUri>("https://www.noesisengine.com/docs/App.Toolkit._Star.html");
    NsMeta<StudioIcon>(Uri::Pack("Toolkit", "#ToolkitIcons"), 0xE906);

    NsProp("Count", &Star::GetCount, &Star::SetCount)
        .Meta<StudioOrder>(0);
    NsProp("Ratio", &Star::GetRatio, &Star::SetRatio)
        .Meta<StudioOrder>(1)
        .Meta<StudioRange>(0.0f, 1.0f);
    NsProp("Radius", &Star::GetRadius, &Star::SetRadius)
        .Meta<StudioOrder>(2)
        .Meta<StudioMin>(0.0f);
}

The Application Framework provides numerous examples with full source code, serving as a practical reference for utilizing metadata to effectively organize and document your extensions inside Studio.

Launching Studio

Because your application already initializes NoesisGUI and registers its own custom extensions, launching Noesis Studio in-process directly from your executable is the most efficient way to achieve a fully integrated, customized editor environment.

All samples built using the Application Framework support the '--project' command-line argument for loading a .noesis project file. When invoked with this switch, the sample executable embeds and launches the Studio interface in-process, rather than running the standard standalone application.

This approach is essential for projects that rely on specific native integrations. For example, the CustomRender sample must be launched with '--project C:\MyProjects\CustomRender.noesis' to ensure its custom rendering extensions are properly registered and actively running within the editor's visual tree.

Although there are other methods to launch a customized instance of Studio, this approach is the simplest. We highly recommend reviewing the implementation of our Application class to see exactly how this is achieved under the hood.

 
© 2017 Noesis Technologies