Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applets: NAP applications inside Napkin #81

Open
wants to merge 246 commits into
base: 0.8
Choose a base branch
from
Open

Applets: NAP applications inside Napkin #81

wants to merge 246 commits into from

Conversation

cklosters
Copy link
Member

@cklosters cklosters commented Feb 3, 2025

This PR introduces Applets: Complete NAP applications that can run inside another host process, alongside each other, thread safe.

Applets enable developers or end-users to preview and inspect content before it is fully integrated into the main application, giving them a better understanding of what they are authoring (such as textures, meshes, materials, and more) and helps ensure the data is compatible with the application. The texture preview applet, included in this PR, demonstrates this functionality, running inside Napkin:

texture_mesh_preview_LQ.mp4

System

Background & Threading

Applets run alongside the main application, as demonstrated above. There can be many applets running at the same time: They're all bound to their own thread and all resources are local to that thread, including: core, the resource manager, spawned objects, services etc. Applets are currently intended and used for preview purposes (such as texture, material, etc) but could theoretically be spawned in any host process.

For this to work I had to re-work all the parts of the core system that are currently not thread safe, ie: not intended to be part of another process, which included services tied to imgui, sdl and the nap::ModuleManager. I also improved the caching and handling of modules - resulting in much faster load times on Linux and Windows.

While working on module resolution for applets (including shared modules), I added a dependency list for each module in the project. This helps identify and flag redundant modules that were loaded earlier, making it easier to clean up the project. The introduction of this nap::ModuleCache, alongside the dependency tracking, leads to faster startup times. Napkin now launches in less than 3 seconds in release mode, with 3 NAP instances loading concurrently.

Integration

It is relatively straight forward to add a new applet to Napkin: Every applet is derived from napkin::Applet and is managed (spawned, initialized and run) by a napkin::AppletRunner. API events are used to communicate with the applet without stalling the host application. Applets are behave for the most part like a regular NAP application: they are sourced from an app.json and load all required modules and data (sequentially) using the standard core de-serialization and init procedures. You can even author your applet inside Napkin, like a regular application!

The applet runs at 60fps but processes events immediately when detected, without waiting. When an applet is disabled or minimized (hidden), it becomes inactive—stopping all processing and entering sleep mode to save resources. This behavior can be customized to suit specific needs, including the option to only render a frame when input is received.

Window & Events

Each applet that is spawned (via the RenderPanel widget hosting it) is bound to a Vulkan-compatible QWindow, rather than a Vulkan-compatible window created by SDL. Upon initialization, the nap::RenderWindow is now set up using a window handle from Qt, instead of being created directly using SDL, which is achieved by registering a render window creation function prior to applet initialization.

The RenderPanel QWidget intercepts input events and converts those into NAP events using an AppletEventConverter. This is very similar to how the default SDLEventConverter works. All other remaining SDL functionality is confined to the applet thread, except for video subsystem initialization, which happens on the main thread before applet creation, as outlined in the official SDL documentation. I’ve disabled most SDL events and periodically pull to clear potential entries in the queue. Applets can be resized and undocked, like regular QDock widgets.

Module Descriptor

Every NAP object now knows which module it originates from. This is achieved by registering a static function local to the translation unit that has a handle to the module descriptor, which is registered and resolved automatically when you define your type. You can access the module for any given type by using nap::rtti::getModuleDescription(T).

Texture Preview Applet

The texture previewer supports both nap::2DTexture and nap::CubeMap, alongside custom meshes. This allows you to test your textures on your own mesh and inspect properties like UVs, reflection, and more.

  • 2D textures can be previewed in 2D (on a plane, orthographic, with aspect ratio correction) or in 3D (on a mesh, with a custom perspective).
  • Cube maps are applied to a skybox and reflected on a 3D (custom) mesh.
  • The applet also provides detailed information about the loaded mesh and texture, including available attributes, bounds, etc.

The last loaded object is tracked, and any property changes are detected and re-uploaded. The object is always framed correct, regardless of size, using its actual bounds to compute camera offsets and planes.

Zoom & Pan Controller

Allows for freely moving around and zooming into a scene and / or 2D texture using an orthographic camera. Use the 'frameTexture' function to adjust the scale and position of your texture, ensuring it fits perfectly in the viewport.

Build & Resources

The build system places a path_mapping.json file in the napkin/cache bin to handle applet loading when Napkin initializes. All paths point to the resources/applets directory, separate from other NAP applications. An applet is loaded from the applets directory just like a regular application by the AppletRunner. No significant changes were needed in the build system.

MISC

  • Group resources by module in Napkin instead of a flat list, making it easier to explore and visually more organized. This is possible due to the exposure of the module descriptor mentioned earlier.

  • Error messages with level of warning and higher are always made visible in the logger. The log panel will scroll and highlight it when detected, raising the widget if the dock is not visible. This makes it easier to highlight a detected problem for the user, rather than requiring them to scroll through it.

  • I developed a staging mechanism that allows resources to be made available to compatible Applets using staging options. Each staging widget that embeds a render panel exposes a list of accepted types. The resource panel uses this information to create a staging option for compatible types, which can then be loaded into an applet.

  • Added an option to calculate the camera distance required to fit a given plane or radius based on a specific field of view (FOV).

  • Added nap::UVTestTexture, nap::TestCubeMap and nap::SunsetCubeMap for quick demo, debug and setup purposes.

  • Fixed (re)size grip of main window.

- create render window from Qt handle in main thread, after initialization but before running the app
@cklosters cklosters added the napkin Napkin related Questions & Issues label Feb 3, 2025
@cklosters cklosters added enhancement New feature or request and removed build Build related Questions & Issues labels Feb 3, 2025
cklosters and others added 23 commits February 4, 2025 11:28
# Conflicts:
#	system_modules/naprender/src/imagefromfile.cpp
#	system_modules/naprender/src/irendertarget.h
#	system_modules/naprender/src/rendertexturecube.cpp
#	system_modules/naprender/src/rendertexturecube.h
#	system_modules/naprenderadvanced/src/cubemapfromfile.cpp
#	system_modules/naprenderadvanced/src/cubemapfromfile.h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core NAP Core related Questions & Issues enhancement New feature or request napkin Napkin related Questions & Issues rendering Render related Questions & Issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant