VR-Engage  2.2
Loading...
Searching...
No Matches
sampleComponent.h
Go to the documentation of this file.
1/*******************************************************************************
2** Copyright (c) 2025 MAK Technologies, Inc.
3** All rights reserved.
4*******************************************************************************/
5
6//! \file sampleComponent.h
7//! \brief Example component demonstrating attribute monitoring and callback patterns in VR-Engage
8//!
9//! This header defines the DtPlayerStateAttributeSampleComponent which shows how to monitor
10//! player attribute store changes using the callback system. It demonstrates event-driven
11//! component design and proper callback lifecycle management patterns.
12
13#pragma once
14
16
17#include "vreUtil/attribute.h"
18
19
20//! \brief Type identifier string for DtNotifyLogic component registration.
21//!
22//! This string is used when registering the component with the component factory
23//! and must match the componentType value used in role configuration files.
24constexpr auto DtPlayerStateAttributeSampleComponentType = "DtPlayerStateAttributeSampleComponent";
25
26//! \brief Example component demonstrating player attribute monitoring and callback patterns.
27//!
28//! This component shows how to use the VR-Engage player attribute store callback system
29//! to monitor state changes using event-driven patterns. It specifically monitors the
30//! "set-gear" attribute and logs changes when the player's gear selection changes,
31//! demonstrating both polling (in tick()) and event-driven (via callbacks) approaches.
32//!
33//! Key VR-Engage patterns demonstrated:
34//! - Subscribing to attribute changes via attribute callbacks
35//! - Accessing the player attribute store for centralized state management
36//! - Using DtAttributeConnectionList for automatic callback lifetime management
37//! - Component lifecycle (initialize, postInitialize, tick, shutdown)
38//! - Proper callback cleanup during shutdown to prevent dangling pointers
39//! - Comparing polling (tick) vs. event-driven (callback) approaches
40//!
41//! This class inherits from DtPlayerComponent and is registered with the player
42//! station's component factory for role-based instantiation.
44{
45public:
46 //! \brief Default constructor.
47 //!
48 //! Initializes the player state attribute sample component. The actual setup is performed
49 //! in initialize() following the VR-Engage component lifecycle pattern.
51
52 //! \brief Virtual destructor.
53 //!
54 //! Cleanup is performed in shutdown() rather than the destructor to ensure
55 //! proper framework ordering during component destruction.
56 virtual ~DtPlayerStateAttributeSampleComponent() override = default;
57
58 //! \brief Initializes the component with player station and configuration.
59 //!
60 //! This method demonstrates the VR-Engage pattern for component initialization:
61 //! 1. Call base class initialize() first to set up inherited members
62 //! 2. Access player attribute store to retrieve attribute handles
63 //!
64 //! The "set-gear" attribute is accessed from the player attribute store,
65 //! which is a centralized repository for player-specific state. The attribute
66 //! handle is stored for later use in postInitialize() when callbacks are registered.
67 //!
68 //! PATTERN: Attribute handles should be retrieved in initialize(), but callbacks
69 //! should be registered in postInitialize() to ensure all components and attributes
70 //! are fully initialized.
71 //!
72 //! \param player The player station instance this component belongs to
73 //! \param config Configuration table containing role parameters (not used in this example)
74 //! \return true if initialization succeeds, false otherwise
76
77 //! \brief Performs post-initialization after all components are initialized.
78 //!
79 //! This method demonstrates the VR-Engage pattern for registering attribute callbacks:
80 //! 1. Call base class postInitialize() first
81 //! 2. Register callbacks using the connection manager
82 //!
83 //! PATTERN: Register attribute callbacks in postInitialize() rather than initialize()
84 //! to ensure all components are fully initialized and all attributes exist. This
85 //! prevents race conditions where callbacks might be invoked before the component
86 //! is fully ready.
87 //!
88 //! The myAttributeCallbacks connection manager automatically tracks all registered
89 //! callbacks and provides disconnectAll() for cleanup during shutdown.
90 //!
91 //! \return true if post-initialization succeeded, false otherwise
92 virtual bool postInitialize() override;
93
94 //! \brief Per-frame update callback.
95 //!
96 //! Called every frame by the player station framework. This example demonstrates
97 //! the polling approach to attribute access by retrieving and logging the current
98 //! gear value every frame using get<T>().
99 //!
100 //! PATTERN COMPARISON:
101 //! - Polling (this method): Retrieves attribute value every frame, even if unchanged
102 //! - Event-driven (onGearChanged): Callback invoked only when value actually changes
103 //!
104 //! For attributes that change infrequently, callbacks are more efficient. For attributes
105 //! that need to be sampled every frame (like analog inputs), polling in tick() is appropriate.
106 //!
107 //! \param dt Delta time in seconds since last update
108 virtual void tick(double dt) override;
109
110 //! \brief Shutdown callback for cleanup.
111 //!
112 //! Performs cleanup before component destruction. This method demonstrates
113 //! the VR-Engage pattern for proper callback cleanup:
114 //! 1. Call base class shutdown() first
115 //! 2. Disconnect all attribute callbacks to prevent dangling pointers
116 //!
117 //! The myAttributeCallbacks.disconnectAll() call ensures all registered
118 //! callbacks are properly removed from the attribute store before the
119 //! component is destroyed.
120 virtual void shutdown() override;
121
122 //! \brief Returns the component type identifier.
123 //!
124 //! This string is used by the component factory for instantiation and
125 //! must match the registration in initPlayerStationModule().
126 //!
127 //! \return The component type string "DtPlayerStateAttributeSampleComponent"
128 virtual const char* type() const override;
129
130protected:
131 //! \brief Callback invoked when the "set-gear" attribute changes.
132 //!
133 //! This method demonstrates the event-driven approach to attribute monitoring.
134 //! It is automatically called by the attribute store whenever the gear attribute
135 //! changes, receiving the new value as a parameter.
136 //!
137 //! PATTERN: Attribute callbacks receive the new value as a parameter with a type
138 //! matching the attribute's type. The signature must match:
139 //! void methodName(const AttributeType& newValue)
140 //!
141 //! This is more efficient than polling in tick() for infrequent changes, as it
142 //! only executes when the value actually changes.
143 //!
144 //! \param newGear The new gear value (e.g., "Neutral", "1st", "2nd", "Reverse")
145 virtual void onGearChanged(const std::string& newGear);
146
147 //! \brief Handle to the "set-gear" player attribute.
148 //!
149 //! This handle provides typed access to the gear attribute value via get<T>()
150 //! and is used to register callbacks via the connection manager. Attribute handles
151 //! are lightweight value types that can be safely stored as member variables.
152 //!
153 //! PATTERN: Store attribute handles as members for repeated access rather than
154 //! looking up attributes by name each time they're needed.
156};
Provides attribute handling system for hierarchical data storage and manipulation.
virtual bool postInitialize() override
Performs post-initialization after all components are initialized.
virtual ~DtPlayerStateAttributeSampleComponent() override=default
Virtual destructor.
DtPlayerStateAttributeSampleComponent()
Default constructor.
virtual const char * type() const override
Returns the component type identifier.
virtual bool initialize(makVre::DtPlayerStation *player, makVre::DtInitTable &config) override
Initializes the component with player station and configuration.
virtual void shutdown() override
Shutdown callback for cleanup.
makVre::DtAttributeHandle myGearAttributeHandle
Handle to the "set-gear" player attribute.
Definition sampleComponent.h:155
virtual void tick(double dt) override
Per-frame update callback.
virtual void onGearChanged(const std::string &newGear)
Callback invoked when the "set-gear" attribute changes.
Handle class for safe access to attributes.
Definition attributeHandle.h:30
Table-based access to Lua state for configuration data.
Definition initializer.h:38
Base class for all role components in VR-Engage.
Definition playerComponent.h:78
virtual DtPlayerStation & player()
Gets the player station.
Class for managing the user interface for engaged roles.
Definition playerStation.h:51
Defines the DtPlayerComponent base class for VR-Engage role components.
constexpr auto DtPlayerStateAttributeSampleComponentType
Type identifier string for DtNotifyLogic component registration.
Definition sampleComponent.h:24