While implementing the UI functionality of Azura, I faced a little problem in segregating code for Different HUDs like Settings related UI Elements should be in a Settings related class and same goes for Main Menu Elements, Levels UI Elements etc.
But it was not possible with the Current strucutre. So I moved things around.
I coded an abstract class called Scene.
ref class Scene abstract { internal: Scene( ID2D1Factory3* d2dFactory, IDWriteFactory3* dwriteFactory, ID2D1DeviceContext2* d2dContext, CoreWindow^ window ); // Override Functions (Hooks) virtual void Init() = 0; virtual void Update() = 0; virtual void OnSceneEnter() = 0; virtual void OnSceneExit() = 0; // Internal Common Functions UIHUD^ CreateHUD(std::wstring id); // Direct 3D Render and Update Phase void UpdatePhase(); void RenderPhase(D2D1::Matrix3x2F orientationMatrix); std::map<std::wstring, UIHUD^> GetHUDMap() { return m_hudMap; } // Other Utilities CoreWindow^ GetWindow() { return m_window; } UIHUD^ GetHUD(std::wstring id); private: CoreWindow^ m_window; std::map<std::wstring, UIHUD^> m_hudMap; Microsoft::WRL::ComPtr<ID2D1Factory3> m_d2dFactory; Microsoft::WRL::ComPtr<IDWriteFactory3> m_dwriteFactory; Microsoft::WRL::ComPtr<ID2D1DeviceContext2> m_d2dContext; };
What’s so awesome is that I am now able to create Scenes seamlessly. Also, Each scene has now a collection of HUDs (earlier there was a UIManager, which has now been deprecated).
So who does the gluing of all the Scenes ? Answer: The SceneDirector.
ref class SceneDirector sealed { internal: SceneDirector(); void AddScene(std::wstring id, Scene^ scene); void ChangeScene(std::wstring id); Scene^ GetScene(std::wstring id); void DeleteScene(std::wstring id); void Update(); void Render(D2D1::Matrix3x2F oritentationMatrix); void Clear(); private: Scene^ m_currentScene; std::map<std::wstring, Scene^> m_sceneMap; };
The director stores the Scenes beautifully in std::map<std::wstring, Scene^> m_sceneMap. This enables me to define Scenes as:
ref class MainMenuScene sealed : public Scene { internal: MainMenuScene( ID2D1Factory3* d2dFactory, IDWriteFactory3* dwriteFactory, ID2D1DeviceContext2* d2dContext, CoreWindow^ window ); void Init() override; void Update() override; void OnSceneEnter() override; void OnSceneExit() override; };
Here I created a custom MainMenuScene which stores all the UI Elements only specific to the Main Menu. This way I can create multiple Scenes and store them in individual files and reusing a lot of code. Also I didn’t use the interface attribute for the Scene class because I wanted to create some common functions like createHUD() which is not possible when making an Interface like IScene as all the methods have to be pure virutal there.