#include "Framework.h"
using namespace fw;
template<> System* Singleton<System>::ms_instance = nullptr;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!InputManager::IsCreated() || !SYSTEM->IsReady())
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
{
INPUT_MANAGER->InjectKeyDown(wParam, HIWORD(lParam));
if (wParam == VK_SHIFT)
{
INPUT_MANAGER->InjectKeyModifierDown(InputManager::KeyModifier::SHIFT);
}
if (wParam == VK_CONTROL)
{
INPUT_MANAGER->InjectKeyModifierDown(InputManager::KeyModifier::CTRL);
}
if (wParam == VK_MENU)
{
INPUT_MANAGER->InjectKeyModifierDown(InputManager::KeyModifier::ALT);
}
break;
}
case WM_KEYUP:
{
INPUT_MANAGER->InjectKeyUp(wParam, HIWORD(lParam));
if (wParam == VK_SHIFT)
{
INPUT_MANAGER->InjectKeyModifierUp(InputManager::KeyModifier::SHIFT);
}
if (wParam == VK_CONTROL)
{
INPUT_MANAGER->InjectKeyModifierUp(InputManager::KeyModifier::CTRL);
}
if (wParam == VK_MENU)
{
INPUT_MANAGER->InjectKeyModifierUp(InputManager::KeyModifier::ALT);
}
break;
}
case WM_MOUSEMOVE:
{
int iMouseX = (int)LOWORD(lParam);
int iMouseY = (int)HIWORD(lParam);
INPUT_MANAGER->InjectMousePosition(iMouseX, iMouseY);
break;
}
case WM_LBUTTONDOWN:
{
INPUT_MANAGER->InjectMouseButtonDown(InputManager::MouseButton::MouseButtonLeft);
break;
}
case WM_RBUTTONDOWN:
{
INPUT_MANAGER->InjectMouseButtonDown(InputManager::MouseButton::MouseButtonRight);
break;
}
case WM_MBUTTONDOWN:
{
INPUT_MANAGER->InjectMouseButtonDown(InputManager::MouseButton::MouseButtonMiddle);
break;
}
case WM_MBUTTONUP:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
{
INPUT_MANAGER->InjectMouseButtonUp();
break;
}
case WM_MOUSEWHEEL:
{
uint32 zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
INPUT_MANAGER->InjectMouseWheel(zDelta);
break;
}
case WM_SETFOCUS:
{
INPUT_MANAGER->InjectWindowHasFocus(true);
INPUT_MANAGER->RestoreMousePosition();
break;
}
case WM_KILLFOCUS:
{
INPUT_MANAGER->InjectWindowHasFocus(false);
INPUT_MANAGER->ReleaseAllKeys();
INPUT_MANAGER->SaveMousePosition();
INPUT_MANAGER->CenterMouseCursor();
break;
}
case WM_WINDOWPOSCHANGED:
{
SYSTEM->GetCurrentRenderer()->SetFullScreenWindowChange(true);
break;
}
case WM_ERASEBKGND:
{
/*
if (SYSTEM->GetRenderer()->FullScreenWindowChanged())
{
SYSTEM->GetRenderer()->SetFullScreenPaint(true);
if (!SYSTEM->GetRenderer()->GetIgnoreTimeFrame())
{
SYSTEM->GetRenderer()->HandleFullScreenModeAltEnter();
}
}
*/
break;
}
case WM_DISPLAYCHANGE:
{
SYSTEM->GetCurrentRenderer()->RestoreFrameStopped();
break;
}
default:
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
return 0;
}
System::System(RenderMode mode) :
m_pRenderer(nullptr),
m_bFullScreen(mode == RenderMode::Fullscreen ? 1 : 0),
m_bRunning(true),
m_pFrameListener(nullptr),
m_bD3DInitSuccess(false),
m_bCenterMouse(false)
{
m_hInstance = GetModuleHandle(nullptr);
// Nom de l'application
m_sApplicationName = APPLICATION_NAME_WIDE;
m_pSingletonManager = new SingletonObjectsManager;
}
System::~System()
{
DestroyTheWindow();
SAFE_DELETE(m_pRenderer); // à déplacer
m_pSingletonManager->DestroyAllObjects();
SAFE_DELETE(m_pSingletonManager);
}
void System::Shutdown()
{
}
bool System::Run(FrameListener* pFrameListener)
{
MSG msg;
// Initialise la structure de message
ZeroMemory (&msg, sizeof(MSG));
// Boucler jusqu'à obtenir un message de sortie de la fenêtre ou de l'utilisateur
while (m_bRunning)
{
// Gérer les messages de la fenêtre
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Si la fenêtre demande à fermer l'application, alors on sort
if (msg.message == WM_QUIT)
{
m_bRunning = false;
}
else
{
// Autrement, effectuer le traitement de la trame
if (pFrameListener != nullptr)
{
pFrameListener->UpdateFrame();
}
}
}
return true;
}
bool System::Initialize(DXVersion version, const SplashScreen::SplashScreenInfo& splashInfo)
{
m_version = version;
m_pSingletonManager->CreateSystemPass();
if (splashInfo.GetInitialized() == OptionalParam::Initialized)
{
LaunchSplashScreen(splashInfo);
}
if (!SetupTheWindow())
{
MessageBoxA(nullptr, "Erreur d'initialisation de la fenêtre !", "Erreur", MB_ICONHAND | MB_OK);
return false;
}
if (m_version == DXVersion::D3D_10)
{
m_pSingletonManager->CreateAllObjects_D3D10Pass();
m_pRenderer = new D3D10Renderer(m_Hwnd);
}
else if(m_version == DXVersion::D3D_11)
{
m_pSingletonManager->CreateAllObjects_D3D11Pass();
m_pRenderer = new D3D11Renderer(m_Hwnd);
}
m_bD3DInitSuccess = m_pRenderer->Initialize(m_bFullScreen);
INPUT_MANAGER->CenterMouseCursor();
INPUT_MANAGER->SaveMousePosition();
if (!m_bD3DInitSuccess)
{
MessageBoxA(nullptr, "Erreur d'initialisation du D3DRenderer !", "Erreur", MB_ICONHAND | MB_OK);
return false;
}
PrintSystemInformations();
return true;
}
bool System::HasFocus()
{
return GetFocus() == m_Hwnd;
}
bool System::SetupTheWindow()
{
// Détermine la résolution de l'écran.
uint32 iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
uint32 iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
// Structure de la classe à configurer
WNDCLASSEX wcex;
// Taille de la structure WNDCLASSEX
wcex.cbSize = sizeof( WNDCLASSEX );
// Style de la classe
wcex.style = CS_HREDRAW | CS_VREDRAW;
// Pointeur de la fonction de boucle de fenêtre (Callback)
wcex.lpfnWndProc = WndProc;
// Inutile à comprendre
wcex.cbClsExtra = 0;
// Inutile à comprendre
wcex.cbWndExtra = 0;
// Obtention de l'instance de cette application
wcex.hInstance = m_hInstance;
// Icone de la fenêtre
wcex.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
// Icone du pointeur de la souris
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
// Inutile à comprendre
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
// Inutile à comprendre
wcex.lpszMenuName = nullptr;
// Nom de la classe enregistrée
wcex.lpszClassName = m_sApplicationName;
wcex.hIconSm = wcex.hIcon;
DEVMODE dmScreenSettings;
// Cas plein écran
if (m_bFullScreen)
{
ZeroMemory(&dmScreenSettings, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof (dmScreenSettings);
dmScreenSettings.dmPelsWidth = (uint64) iScreenWidth;
dmScreenSettings.dmPelsHeight = (uint64) iScreenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
}
if (!RegisterClassEx(&wcex))
{
return false;
}
// Créée la fenêtre
RECT rc = { 0, 0, 1200, 800 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
m_Hwnd = CreateWindow(m_sApplicationName, m_sApplicationName, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
nullptr, nullptr, m_hInstance, nullptr);
if (!m_Hwnd)
{
return false;
}
ShowWindow(m_Hwnd, SW_SHOW);
SetForegroundWindow(m_Hwnd);
SetFocus(m_Hwnd);
return true;
}
void System::DestroyTheWindow()
{
// Change les paramètres d'affichage si l'on quitte le mode plein écran
if (m_bFullScreen)
{
ChangeDisplaySettings(nullptr, 0);
}
// Détruit la fenêtre.
DestroyWindow(m_Hwnd);
m_Hwnd = nullptr;
// Détruit l'instance de l'application
UnregisterClass(m_sApplicationName, m_hInstance);
m_hInstance = nullptr;
}
bool System::IsQuitting()
{
return m_bRunning == false;
}
void System::Quit()
{
/*
if (Logger::IsCreated())
{
//SYSTEM_LOG->SetEndingState(Logger::FatalError);
Logger::Destroy();
}
*/
//PostQuitMessage(1);
m_bRunning = false;
}
std::string System::GetVersion()
{
return ENGINE_VERSION;
}
HWND System::GetHwnd()
{
return m_Hwnd;
}
void System::ChangeWindowTitle(const std::string& sWindowTitle)
{
SetWindowTextA(m_Hwnd, sWindowTitle.c_str());
}
D3DRenderer* System::GetCurrentRenderer()
{
return m_pRenderer;
}
D3DRenderer* System::GetRenderer(DXVersion version)
{
if (version == DXVersion::D3D_10)
{
return GetSpecificRenderer<D3D10>();
}
else if (version == DXVersion::D3D_11)
{
return GetSpecificRenderer<D3D11>();
}
return nullptr;
}
void System::UpdateWindowTitle()
{
static char buffer[256];
D3DXVECTOR3 camPos = SCENE_MANAGER->GetActiveCamera()->GetPosition();
sprintf_s(buffer, "Position de la caméra : X = %.2f Y = %.2f Z = %.2f", camPos.x, camPos.y, camPos.z);
// On met à jour le titre de la fenêtre
ChangeWindowTitle(buffer);
}
void System::PrintSystemInformations()
{
new ComputerInfo();
LogMessage(std::endl);
LogMessage("Voici le nom de votre processeur : " << COMPUTER_INFO->GetCpuName().c_str() << std::endl);
LogMessage("Voici la vitesse de votre processeur : " << COMPUTER_INFO->GetCpuSpeed().c_str() << std::endl);
LogMessage("Voici la capacité total de votre mémoire centrale : " << COMPUTER_INFO->GetTotalMemory().c_str() << std::endl);
LogMessage("Voici la capacité restante de votre mémoire centrale : " << COMPUTER_INFO->GetAvailableMemory().c_str() << std::endl);
LogMessage("Voici la capacité restante de votre volume de disque principal : " << COMPUTER_INFO->GetHDSpace().c_str() << std::endl);
LogMessage("Voici le nom de votre système d'exploitation : " << COMPUTER_INFO->GetOsName().c_str() << std::endl);
LogMessage(std::endl);
CPUInfo* pCPUInfo = new CPUInfo();
pCPUInfo->Initialize();
LogMessage("Voici le nombre de coeurs de votre processeur : "
<< pCPUInfo->GetSystemProcessorCount() << " coeurs" << std::endl);
LogMessage("Voici le nombre de coeurs physiques de votre processeur : "
<< pCPUInfo->GetPhysicalProcessorCount() << " coeurs" << std::endl);
uint32 L1CacheSize = pCPUInfo->GetL1CacheSize();
uint32 L2CacheSize = pCPUInfo->GetL2CacheSize();
uint32 L3CacheSize = pCPUInfo->GetL3CacheSize();
std::string sizeL1CacheFormat = " KB";
std::string sizeL2CacheFormat = " KB";
std::string sizeL3CacheFormat = " KB";
if (MATHS->GetDigitsCount(L1CacheSize) > 6)
{
L1CacheSize /= 1000000;
sizeL1CacheFormat = " MB";
}
if (MATHS->GetDigitsCount(L2CacheSize) > 6)
{
L2CacheSize /= 1000000;
sizeL2CacheFormat = " MB";
}
if (MATHS->GetDigitsCount(L3CacheSize) > 6)
{
L3CacheSize /= 1000000;
sizeL3CacheFormat = " MB";
}
LogMessage("Voici la taille du cache L1 de votre processeur : "
<< L1CacheSize << sizeL1CacheFormat.c_str() << std::endl);
LogMessage("Voici la taille du cache L2 de votre processeur : "
<< L2CacheSize << sizeL2CacheFormat.c_str() << std::endl);
LogMessage("Voici la taille du cache L3 de votre processeur : "
<< L3CacheSize << sizeL3CacheFormat.c_str() << std::endl);
LogMessage(std::endl);
const CPUInfo::CPUExtensionsSupport& extensions = pCPUInfo->GetExtensionsSupport();
LogMessage("Voici les extensions de CPU supportées : " << std::endl);
std::cout << std::endl;
if (extensions.HW_SSE)
{
LogMessage("\tSSE supporté" << std::endl);
}
if (extensions.HW_SSE2)
{
LogMessage("\tSSE2 supporté" << std::endl);
}
if (extensions.HW_SSE3)
{
LogMessage("\tSSE3 supporté" << std::endl);
}
if (extensions.HW_SSE41)
{
LogMessage("\tSSE41 supporté" << std::endl);
}
if (extensions.HW_SSE42)
{
LogMessage("\tSSE42 supporté" << std::endl);
}
if (extensions.HW_SSE4a)
{
LogMessage("\tSSE4a supporté" << std::endl);
}
if (extensions.HW_MMX)
{
LogMessage("\tMMX supporté" << std::endl);
}
if (extensions.HW_ABM)
{
LogMessage("\tABM supporté" << std::endl);
}
if (extensions.HW_AES)
{
LogMessage("\tAES supporté" << std::endl);
}
if (extensions.HW_AVX)
{
LogMessage("\tAVX supporté" << std::endl);
}
if (extensions.HW_AVX2)
{
LogMessage("\tAVX2 supporté" << std::endl);
}
if (extensions.HW_FMA3)
{
LogMessage("\tFMA3 supporté" << std::endl);
}
if (extensions.HW_FMA4)
{
LogMessage("\tFMA4 supporté" << std::endl);
}
if (extensions.HW_RDRAND)
{
LogMessage("\tRDRAND supporté" << std::endl);
}
if (extensions.HW_SHA)
{
LogMessage("\tSHA supporté" << std::endl);
}
if (extensions.HW_x64)
{
LogMessage("\tx64 supporté" << std::endl);
}
if (extensions.HW_XOP)
{
LogMessage("\tXOP supporté" << std::endl);
}
LogMessage(std::endl);
delete pCPUInfo;
COMPUTER_INFO->Destroy();
}
DXVersion System::GetDirectXVersion()
{
return m_version;
}
bool System::IsReady()
{
return m_bD3DInitSuccess;
}
void System::LaunchSplashScreen(const SplashScreen::SplashScreenInfo& splashInfo)
{
GAME_RESOURCES_MANAGER->LoadZipFile();
bool bImageExist = GAME_RESOURCES_MANAGER->FileExist(splashInfo.m_sImageFileName);
SKIP_IF_FAILED_AssertMsg(bImageExist,
"Problème chargement d'image de l'écran de démarrage")
{
ThreadsWrapper::Thread* pT = nullptr;
std::function<void(void)> function = [splashInfo]()
{
SplashScreen splash(splashInfo);
splash.Show(GetModuleHandle(NULL));
};
pT = THREADS_WRAPPER->CreateThreadLambda("SplashScreen", function);
if (pT)
{
std::thread::id id = THREADS_WRAPPER->LaunchThread(pT);
}
}
}
void System::LoadCustomCursor(const std::string& sCursorName)
{
PointerHolder<CursorFileBuffer> cursorBuffer =
GAME_RESOURCES_MANAGER->LoadWindowCursor_ZIP(sCursorName);
if (cursorBuffer->IsEmpty())
{
return;
}
HWND hwnd = GetHwnd();
HICON hIcon = nullptr;
size_t32 iWidth = cursorBuffer->GetCursorWidth();
size_t32 iHeight = cursorBuffer->GetCursorHeight();
char* pBuffer = cursorBuffer->GetBuffer();
uint16 offset = LookupIconIdFromDirectoryEx((PBYTE)pBuffer, TRUE, iWidth, iHeight, LR_DEFAULTCOLOR);
if (offset != 0)
{
hIcon = CreateIconFromResourceEx((PBYTE)pBuffer + offset, 0, TRUE, 0x30000, iWidth, iHeight, LR_DEFAULTCOLOR);
}
cursorBuffer->Done();
cursorBuffer.ToDelete();
GAME_RESOURCES_MANAGER->RemoveFileBuffer(cursorBuffer);
SetClassLong((HWND)hwnd, GCL_HCURSOR, (LONG)hIcon);
}
void System::ToggleCenteredMouseCursor()
{
m_bCenterMouse = !m_bCenterMouse;
ShowCursor(!m_bCenterMouse);
}
char* System::GetTime(const char* sFormat)
{
time_t CurrentTime = time(NULL);
static char sTime[24];
strftime(sTime, sizeof(sTime), sFormat, localtime(&CurrentTime));
return sTime;
}