Actor components

An actor component encapsulates reusable functionality for actors. A component can only be attached to one actor at a time. Each component has a unique ID and a name (not necessarily unique) for identification in save files and the Met.3D UI.

For example, the MTransformComponent provides position, rotation, and scale properties to its associated actor, along with an optional drag-and-drop gizmo for easy manipulation. This component operates independently from the actor’s core functionality.

In summary, if an actor’s functionality can be modularized, it should be implemented as an actor component.

Implementation

The MActorComponent class defines the interface for all components, featuring virtual methods for resource initialization, rendering, intersection checking, and dragging. It also allows enabling or disabling the component and emits the actorComponentChanged signal to indicate when redrawing or changes are necessary.

The MActor class manages actors and their components, storing them in an ID map. When adding a component, it is initialized, and its properties are integrated into the actor’s property tree. Components are managed using std::shared_ptr, ensuring automatic cleanup when references are cleared. Removing a component disconnects signal connections and removes its properties from the property tree, allowing for reuse or cleanup.

Actors do not save their attached components during session or file saving, as this must be managed manually by the actors themselves, which may create default components in their constructor. Creating these default components while loading would duplicate them. This design choice allows actors to control component instantiation.

Usage of existing components

Each instance of an actor component is created by the actor it is added to via the MActor::addActorComponentOfType<T>(...) method. This method takes the component type as a type parameter and accepts constructor arguments for the component. It is important to note, that the first argument for all components constructors should be the actor that created it. This argument should not be passed to the MActor::addActorComponentOfType<T>(...) method. It is provided by the actor.

Implementing a new component

The new component must inherit from the MActorComponent class or its subclasses and implement a constructor with the first argument as a pointer to the MActor class. The component’s interface can be customized as needed. For more details on the methods that can be implemented, refer to the Reference.

When using properties, it is recommended to group all component properties under a single group property and set its configuration group to the component’s name.

Reference

This contains the class reference of the MActorComponent class.

  • MActorComponent(MActor*, QString&) — The constructor of the component. The first argument is mandatory for all child classes to also implement.

  • ~MActorComponent() — The destructor of the component. All resources the component uses should be cleaned up here.

  • getName() — Returns the current name of the component.

  • setName(const QString&) — Sets the current name of the component.

  • getParentActor() — Returns the actor the component is attached to or nullptr, if it is orphaned.

  • isEnabled() — Whether the component is currently enabled or disabled.

  • setEnabled(bool) — Either enables or disables the component. A disabled component will not be interactable or rendered.

  • virtual onEnabled() — Called when the component changes from disabled to enabled.

  • virtual onDisabled() — Called when the component changes from enabled to disabled.

  • virtual onNameChanged() — Called when the name of the component changes. Use this to update the configuration group of the component.

  • virtual initializeResources() — Initialize the component and its GPU resources.

  • virtual reloadShaderEffects(bool) — Reload all shaders used by the component and optionally force them to recompile.

  • virtual renderToCurrentContext(MSceneViewGLWidget*) — Used to render the component as a 3D object in the scene.

  • virtual renderToUiLayer(MSceneViewGLWidget*) — Used to render the component to the 2D UI layer.

  • virtual checkIntersectionWithHandle(MSceneViewGLWidget*, float, float) — Used to check for intersections with the mouse and the component for interaction.

  • virtual dragEvent(MSceneViewGLWidget*, int, float, float) — Called when the component is dragged after a successful intersection check.

  • virtual releaseEvent(MSceneViewGLWidget*, int) — Called when the drag event ends and the component is released.

  • virtual addProperties(MProperty*) — Used to add the component properties to the given property group.

  • virtual toggleProperties(bool) — Used to disable all properties of the component.

  • virtual removeProperties(MProperty*) — Used to remove the component properties from the given property group.

  • virtual saveConfiguration(QSettings*) — Saves all non-property configuration to the given QSettings* object.

  • virtual loadConfiguration(QSettings*) — Loads all non-property configuration from the given QSettings* object.

  • emitComponentChangedSignal() — Emits the signal, that the component changed and the actor needs to react to those changes.