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.