Hey all,
For a while now I have been tinkering with my 3D engine, which is actually just a sandbox for me to try out some stuff in terms off well.. everything, not just graphics programming related, but pretty much everything. It's all for learning purposes!
When I started, I made everything (where needed) with raw pointers as I didn't have time to read up on smart pointers and I decided to dive into that now that I actually had the time to read up upon them, due to me being busy, I was kinda lost on where I was going with the engine and upon skimming through my code, I noticed I made a lot of use of singletons. Now whether they're good or bad is not really the point of this thread, but I decided I wanted to reduce them to a minimum and succeeded well enough to get the engine running like it did before and I only had one singleton left, which was my system class that is essentially the root of the engine where I initialize the window, renderer and scenemanager.
Now I got a bit curious if I could get rid of my system class being a singleton as well. I noticed I still had some dependencies that relied on system being a singleton, like my renderer class that needs a window handle to initialize DirectX11, but that was fixable by passing the right information.
Now I am facing a different kind of problem which has to do with event handling in windows. I have an abstract window class and a windows32 specific window class which both look like this:
Window.h
#ifndef _WINDOW_H_
#define _WINDOW_H_
namespace FX
{
enum WindowEvent
{
eWindowEvent_Close,
eWindowEvent_Minimize,
eWindowEvent_Maximize,
eWindowEvent_Resize,
eWindowEvent_Move,
eWindowEvent_Windowed,
eWindowEvent_FullScreen
};
class System;
class Window
{
public:
virtual ~Window();
Window();
void Create(FX::System* a_System, const std::string& a_Title, int a_Width, int a_Height, int a_PosX, int a_PosY);
const std::string& GetWindowTitle() const {return m_Title;}
const int GetWindowWidth() const {return m_WindowWidth;}
const int GetWindowHeight() const {return m_WindowHeight;}
const int GetWindowPositionX() const {return m_WindowPositionX;}
const int GetWindowPositionY() const {return m_WindowPositionY;}
const bool IsFullScreen() const {return m_FullScreen;}
virtual void SetWindowTitle(const std::string& a_Title) = 0;
virtual void SetWindowWidth(int a_Width) = 0;
virtual void SetWindowHeight(int a_Height) = 0;
virtual void SetWindowPositionX(int a_X) = 0;
virtual void SetWindowPositionY(int a_Y) = 0;
virtual void SetFullScreen(bool a_FullScreen) = 0;
virtual bool GetEvent() = 0;
virtual bool ProcessEvent() = 0;
static void WindowEventHandler(const WindowEvent a_WindowEvent, const int a_DataSize = 0, void* a_Data = NULL);
protected:
std::string m_Title;
int m_WindowWidth;
int m_WindowHeight;
int m_WindowPositionX;
int m_WindowPositionY;
bool m_FullScreen;
FX::System* m_System;
};
}
#endif
WindowWin32.h:
#ifndef _WINDOWWIN32_H_
#define _WINDOWWIN32_H_
#include "Window.h"
namespace FX
{
class WindowWin32 : public Window
{
friend class Window;
public:
WindowWin32();
virtual ~WindowWin32();
const HINSTANCE GetHInstance() const {return m_hInstance;}
const HWND GetHWnd() const {return m_hWnd;}
const WNDCLASSEX* GetWndClassEx() const {return &m_WndClass;}
void SetWindowTitle(const std::string& a_Title);
void SetWindowWidth(int a_Width);
void SetWindowHeight(int a_Height);
void SetWindowPositionX(int a_X);
void SetWindowPositionY(int a_Y);
void SetFullScreen(bool a_FullScreen);
bool GetEvent();
bool ProcessEvent();
protected:
void UpdatePosition();
HINSTANCE m_hInstance;
HWND m_hWnd;
WNDCLASSEX m_WndClass;
MSG m_Msg;
DWORD m_Style;
RECT m_Dimensions;
};
}
#endif
In Window.h I defined a static eventhandler function that gets called by the specific windows callback like this:
LRESULT CALLBACK WndProc(HWND a_HWND, UINT a_Message, WPARAM a_Param1, LPARAM a_Param2)
{
switch(a_Message)
{
case WM_CLOSE:
case WM_QUIT:
case WM_DESTROY:
{
FX::Window::WindowEventHandler(FX::eWindowEvent_Close);
break;
}
case WM_KEYDOWN:
{
//FX::Keyboard::Get()->InjectKeyDown(a_Param1);
break;
}
case WM_KEYUP:
{
//FX::Keyboard::Get()->InjectKeyUp(a_Param1);
break;
}
case WM_MOUSEMOVE:
{
//FX::Mouse::Get()->InjectPosition((float)LOWORD(a_Param2), (float)LOWORD(a_Param2));
//FX::Mouse::Get()->Clip();
break;
}
case WM_SIZE:
{
// FX::int2 newsize;
// newsize.x = LOWORD(a_Param2);
// newsize.y = HIWORD(a_Param2);
//
// if(a_Param1 == SIZE_MINIMIZED)
// {
// FX::Window::WindowEventHandler(FX::eWindowEvent_Minimize, 8, &newsize);
// break;
// }
// else if (a_Param1 == SIZE_MAXIMIZED)
// {
// FX::Window::WindowEventHandler(FX::eWindowEvent_Maximize, 8, &newsize);
// break;
// }
break;
}
case WM_ACTIVATE:
{
// bool active = ((LOWORD(a_Param1) != WA_INACTIVE) && !((BOOL)HIWORD(a_Param1)));
// if(!active)
// {
// Rld::Mouse::Get()->Clear();
// }
break;
}
}
return DefWindowProc(a_HWND, a_Message, a_Param1, a_Param2);
}
Now the initial problem lies with system being a non static member that needs to be called in the static function WindowEventHandler in the Window base class, but this is not allowed.
I could make it a non static function, but than I can't call it from windows32 specific callback anymore.
So how would (or should) I handle this situation? I could make the system class a singleton again, but I am curious how this would be implemented in a way like this. Any pointers, directions or different solutions would be much appreciated!