New module: Platform - Split window management from Utility module (#128)

* New module: Platform - Split window management from Utility module

Final touch

* NDK/SDK: Bring back initialization of Utility
This commit is contained in:
Gawaboumga
2017-08-30 10:22:50 +02:00
committed by Jérôme Leclercq
parent 41a1b5d493
commit 5aa072cee3
125 changed files with 1049 additions and 782 deletions

View File

@@ -0,0 +1,106 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/CursorImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
bool CursorImpl::Create(const Image& cursor, int hotSpotX, int hotSpotY)
{
Image windowsCursor(cursor);
if (!windowsCursor.Convert(PixelFormatType_BGRA8))
{
NazaraError("Failed to convert cursor to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 32, windowsCursor.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = FALSE;
iconInfo.xHotspot = hotSpotX;
iconInfo.yHotspot = hotSpotY;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_icon = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
if (!m_icon)
{
NazaraError("Failed to create cursor: " + Error::GetLastSystemError());
return false;
}
m_cursor = m_icon;
return true;
}
bool CursorImpl::Create(SystemCursor cursor)
{
if (cursor != SystemCursor_Move)
m_cursor = static_cast<HCURSOR>(LoadImage(nullptr, s_systemCursorIds[cursor], IMAGE_CURSOR, 0, 0, LR_SHARED));
else
m_cursor = nullptr;
// No need to free the cursor if shared
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
m_icon = nullptr;
return true;
}
void CursorImpl::Destroy()
{
if (m_icon)
DestroyIcon(m_icon);
}
HCURSOR CursorImpl::GetCursor()
{
return m_cursor;
}
bool CursorImpl::Initialize()
{
return true;
}
void CursorImpl::Uninitialize()
{
}
std::array<LPTSTR, SystemCursor_Max + 1> CursorImpl::s_systemCursorIds =
{
IDC_CROSS, // SystemCursor_Crosshair
IDC_ARROW, // SystemCursor_Default
IDC_HAND, // SystemCursor_Hand
IDC_HELP, // SystemCursor_Help
IDC_SIZEALL, // SystemCursor_Move
nullptr, // SystemCursor_None
IDC_HAND, // SystemCursor_Pointer
IDC_APPSTARTING, // SystemCursor_Progress
IDC_SIZEWE, // SystemCursor_ResizeE
IDC_SIZENS, // SystemCursor_ResizeN
IDC_SIZENESW, // SystemCursor_ResizeNE
IDC_SIZENWSE, // SystemCursor_ResizeNW
IDC_SIZENS, // SystemCursor_ResizeS
IDC_SIZENWSE, // SystemCursor_ResizeSE
IDC_SIZENESW, // SystemCursor_ResizeSW
IDC_SIZEWE, // SystemCursor_ResizeW
IDC_IBEAM, // SystemCursor_Text
IDC_WAIT // SystemCursor_Wait
};
static_assert(SystemCursor_Max + 1 == 18, "System cursor array is incomplete");
}

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CURSORIMPL_HPP
#define NAZARA_CURSORIMPL_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <array>
#include <windows.h>
namespace Nz
{
class Image;
class CursorImpl
{
friend class Cursor;
public:
bool Create(const Image& image, int hotSpotX, int hotSpotY);
bool Create(SystemCursor cursor);
void Destroy();
HCURSOR GetCursor();
private:
static bool Initialize();
static void Uninitialize();
HCURSOR m_cursor = nullptr;
HICON m_icon = nullptr;
static std::array<LPTSTR, SystemCursor_Max + 1> s_systemCursorIds;
};
}
#endif // NAZARA_CURSORIMPL_HPP

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/IconImpl.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
bool IconImpl::Create(const Image& icon)
{
Image windowsIcon(icon); // Vive le COW
if (!windowsIcon.Convert(PixelFormatType_BGRA8))
{
NazaraError("Failed to convert icon to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 32, windowsIcon.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_icon = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
if (!m_icon)
{
NazaraError("Failed to create icon: " + Error::GetLastSystemError());
return false;
}
return true;
}
void IconImpl::Destroy()
{
DestroyIcon(m_icon);
}
HICON IconImpl::GetIcon()
{
return m_icon;
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ICONIMPL_HPP
#define NAZARA_ICONIMPL_HPP
#include <Nazara/Prerequesites.hpp>
#include <windows.h>
namespace Nz
{
class Image;
class IconImpl
{
public:
bool Create(const Image& image);
void Destroy();
HICON GetIcon();
private:
HICON m_icon = nullptr;
};
}
#endif // NAZARA_ICONIMPL_HPP

View File

@@ -0,0 +1,296 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/InputImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Platform/Window.hpp>
#include <windows.h>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
namespace
{
int vKeys[Keyboard::Count] = {
// Lettres
0x41, // Key::A
0x42, // Key::B
0x43, // Key::C
0x44, // Key::D
0x45, // Key::E
0x46, // Key::F
0x47, // Key::G
0x48, // Key::H
0x49, // Key::I
0x4A, // Key::J
0x4B, // Key::K
0x4C, // Key::L
0x4D, // Key::M
0x4E, // Key::N
0x4F, // Key::O
0x50, // Key::P
0x51, // Key::Q
0x52, // Key::R
0x53, // Key::S
0x54, // Key::T
0x55, // Key::U
0x56, // Key::V
0x57, // Key::W
0x58, // Key::X
0x59, // Key::Y
0x5A, // Key::Z
// Touches de fonction
VK_F1, // Key::F1
VK_F2, // Key::F2
VK_F3, // Key::F3
VK_F4, // Key::F4
VK_F5, // Key::F5
VK_F6, // Key::F6
VK_F7, // Key::F7
VK_F8, // Key::F8
VK_F9, // Key::F9
VK_F10, // Key::F10
VK_F11, // Key::F11
VK_F12, // Key::F12
VK_F13, // Key::F13
VK_F14, // Key::F14
VK_F15, // Key::F15
// Flèches directionnelles
VK_DOWN, // Key::Down
VK_LEFT, // Key::Left
VK_RIGHT, // Key::Right
VK_UP, // Key::Up
// Pavé numérique
VK_ADD, // Key::Add
VK_DECIMAL, // Key::Decimal
VK_DIVIDE, // Key::Divide
VK_MULTIPLY, // Key::Multiply
VK_NUMPAD0, // Key::Numpad0
VK_NUMPAD1, // Key::Numpad1
VK_NUMPAD2, // Key::Numpad2
VK_NUMPAD3, // Key::Numpad3
VK_NUMPAD4, // Key::Numpad4
VK_NUMPAD5, // Key::Numpad5
VK_NUMPAD6, // Key::Numpad6
VK_NUMPAD7, // Key::Numpad7
VK_NUMPAD8, // Key::Numpad8
VK_NUMPAD9, // Key::Numpad9
VK_SUBTRACT, // Key::Subtract
// Diverss
VK_OEM_5, // Key::Backslash
VK_BACK, // Key::Backspace
VK_CLEAR, // Key::Clear
VK_OEM_COMMA, // Key::Comma,
VK_OEM_MINUS, // Key::Dash
VK_DELETE, // Key::Delete
VK_END, // Key::End
VK_OEM_PLUS, // Key::Equal
VK_ESCAPE, // Key::Escape
VK_HOME, // Key::Home
VK_INSERT, // Key::Insert
VK_LMENU, // Key::LAlt
VK_OEM_4, // Key::LBracket
VK_LCONTROL, // Key::LControl
VK_LSHIFT, // Key::LShift
VK_LWIN, // Key::LSystem
0x30, // Key::Num0
0x31, // Key::Num1
0x32, // Key::Num2
0x33, // Key::Num3
0x34, // Key::Num4
0x35, // Key::Num5
0x36, // Key::Num6
0x37, // Key::Num7
0x38, // Key::Num8
0x39, // Key::Num9
VK_NEXT, // Key::PageDown
VK_PRIOR, // Key::PageUp
VK_PAUSE, // Key::Pause
VK_OEM_PERIOD, // Key::Period
VK_PRINT, // Key::Print
VK_SNAPSHOT, // Key::PrintScreen
VK_OEM_7, // Key::Quote
VK_RMENU, // Key::RAlt
VK_OEM_6, // Key::RBracket
VK_RCONTROL, // Key::RControl
VK_RETURN, // Key::Return
VK_RSHIFT, // Key::RShift
VK_RWIN, // Key::RSystem
VK_OEM_1, // Key::Semicolon
VK_OEM_2, // Key::Slash
VK_SPACE, // Key::Space
VK_TAB, // Key::Tab
VK_OEM_3, // Key::Tilde
// Touches navigateur
VK_BROWSER_BACK, // Key::Browser_Back
VK_BROWSER_FAVORITES, // Key::Browser_Favorites
VK_BROWSER_FORWARD, // Key::Browser_Forward
VK_BROWSER_HOME, // Key::Browser_Home
VK_BROWSER_REFRESH, // Key::Browser_Refresh
VK_BROWSER_SEARCH, // Key::Browser_Search
VK_BROWSER_STOP, // Key::Browser_Stop
// Touches de contrôle
VK_MEDIA_NEXT_TRACK, // Key::Media_Next,
VK_MEDIA_PLAY_PAUSE, // Key::Media_PlayPause,
VK_MEDIA_PREV_TRACK, // Key::Media_Previous,
VK_MEDIA_STOP, // Key::Media_Stop,
// Touches de contrôle du volume
VK_VOLUME_DOWN, // Key::Volume_Down
VK_VOLUME_MUTE, // Key::Volume_Mute
VK_VOLUME_UP, // Key::Volume_Up
// Touches à verrouillage
VK_CAPITAL, // Key::CapsLock
VK_NUMLOCK, // Key::NumLock
VK_SCROLL // Key::ScrollLock
};
}
String EventImpl::GetKeyName(Keyboard::Key key)
{
// http://www.ffuts.org/blog/mapvirtualkey-getkeynametext-and-a-story-of-how-to/
int vk = vKeys[key];
unsigned int code = MapVirtualKeyW(vk, 0) << 16;
///FIXME: Liste complète ?
switch (vk)
{
case VK_ATTN:
case VK_DOWN:
case VK_DECIMAL:
case VK_DELETE:
case VK_DIVIDE:
case VK_END:
case VK_HOME:
case VK_INSERT:
case VK_LEFT:
case VK_LWIN:
case VK_OEM_1:
case VK_OEM_2:
case VK_OEM_3:
case VK_OEM_4:
case VK_OEM_5:
case VK_OEM_6:
case VK_OEM_7:
case VK_OEM_CLEAR:
case VK_OEM_COMMA:
case VK_OEM_MINUS:
case VK_OEM_PERIOD:
case VK_OEM_PLUS:
case VK_PAUSE:
case VK_NEXT:
case VK_NUMLOCK:
case VK_PRIOR:
case VK_RIGHT:
case VK_RWIN:
case VK_UP:
code |= 0x1000000; // 24ème bit pour l'extension
break;
}
wchar_t keyName[20]; // Je ne pense pas que ça dépassera 20 caractères
if (!GetKeyNameTextW(code, &keyName[0], 20))
return "Unknown";
return String::Unicode(keyName);
}
Vector2i EventImpl::GetMousePosition()
{
POINT pos;
GetCursorPos(&pos);
return Vector2i(pos.x, pos.y);
}
Vector2i EventImpl::GetMousePosition(const Window& relativeTo)
{
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
if (handle)
{
POINT pos;
GetCursorPos(&pos);
ScreenToClient(handle, &pos);
return Vector2i(pos.x, pos.y);
}
else
{
NazaraError("Invalid window handle");
// Attention que (-1, -1) est une position tout à fait valide et ne doit pas servir de test
return Vector2i(-1, -1);
}
}
bool EventImpl::IsKeyPressed(Keyboard::Key key)
{
switch (key)
{
case Keyboard::CapsLock:
case Keyboard::NumLock:
case Keyboard::ScrollLock:
return GetKeyState(vKeys[key]) != 0;
default:
return (GetAsyncKeyState(vKeys[key]) & 0x8000) != 0;
}
}
bool EventImpl::IsMouseButtonPressed(Mouse::Button button)
{
static int vButtons[Mouse::Max+1] = {
VK_LBUTTON, // Button::Left
VK_MBUTTON, // Button::Middle
VK_RBUTTON, // Button::Right
VK_XBUTTON1, // Button::XButton1
VK_XBUTTON2 // Button::XButton2
};
// Gestion de l'inversement des boutons de la souris
if (GetSystemMetrics(SM_SWAPBUTTON))
{
switch (button)
{
case Mouse::Left:
button = Mouse::Right;
break;
case Mouse::Right:
button = Mouse::Left;
break;
default:
break;
}
}
return (GetAsyncKeyState(vButtons[button]) & 0x8000) != 0;
}
void EventImpl::SetMousePosition(int x, int y)
{
SetCursorPos(x, y);
}
void EventImpl::SetMousePosition(int x, int y, const Window& relativeTo)
{
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
if (handle)
{
POINT pos = {x, y};
ClientToScreen(handle, &pos);
SetCursorPos(pos.x, pos.y);
}
else
NazaraError("Invalid window handle");
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_INPUTIMPL_HPP
#define NAZARA_INPUTIMPL_HPP
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
namespace Nz
{
class EventImpl
{
public:
static String GetKeyName(Keyboard::Key key);
static Vector2i GetMousePosition();
static Vector2i GetMousePosition(const Window& relativeTo);
static bool IsKeyPressed(Keyboard::Key key);
static bool IsMouseButtonPressed(Mouse::Button button);
static void SetMousePosition(int x, int y);
static void SetMousePosition(int x, int y, const Window& relativeTo);
};
}
#endif // NAZARA_INPUTIMPL_HPP

View File

@@ -0,0 +1,35 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/Win32/VideoModeImpl.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <algorithm>
#include <windows.h>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
VideoMode VideoModeImpl::GetDesktopMode()
{
DEVMODE mode;
mode.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &mode);
return VideoMode(mode.dmPelsWidth, mode.dmPelsHeight, static_cast<UInt8>(mode.dmBitsPerPel));
}
void VideoModeImpl::GetFullscreenModes(std::vector<VideoMode>& modes)
{
DEVMODE win32Mode;
win32Mode.dmSize = sizeof(DEVMODE);
for (unsigned int i = 0; EnumDisplaySettings(nullptr, i, &win32Mode); ++i)
{
VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, static_cast<UInt8>(win32Mode.dmBitsPerPel));
// Il existe plusieurs modes avec ces trois caractéristques identiques
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode);
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VIDEOMODEIMPL_HPP
#define NAZARA_VIDEOMODEIMPL_HPP
#include <Nazara/Platform/VideoMode.hpp>
namespace Nz
{
class VideoModeImpl
{
public:
static VideoMode GetDesktopMode();
static void GetFullscreenModes(std::vector<VideoMode>& modes);
};
}
#endif // NNAZARA_VIDEOMODEIMPL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_WINDOWIMPL_HPP
#define NAZARA_WINDOWIMPL_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Platform/Config.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <Nazara/Platform/Window.hpp>
#include <windows.h>
namespace Nz
{
class ConditionVariable;
class Mutex;
class Window;
#undef IsMinimized // Conflits with windows.h redefinition
class WindowImpl
{
public:
WindowImpl(Window* parent);
WindowImpl(const WindowImpl&) = delete;
WindowImpl(WindowImpl&&) = delete; ///TODO?
~WindowImpl() = default;
bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style);
bool Create(WindowHandle handle);
void Destroy();
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
WindowHandle GetHandle() const;
unsigned int GetHeight() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
String GetTitle() const;
unsigned int GetWidth() const;
bool HasFocus() const;
void IgnoreNextMouseEvent(int mouseX, int mouseY);
bool IsMinimized() const;
bool IsVisible() const;
void ProcessEvents(bool block);
void SetCursor(const Cursor& cursor);
void SetEventListener(bool listener);
void SetFocus();
void SetIcon(const Icon& icon);
void SetMaximumSize(int width, int height);
void SetMinimumSize(int width, int height);
void SetPosition(int x, int y);
void SetSize(unsigned int width, unsigned int height);
void SetStayOnTop(bool stayOnTop);
void SetTitle(const String& title);
void SetVisible(bool visible);
WindowImpl& operator=(const WindowImpl&) = delete;
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
static bool Initialize();
static void Uninitialize();
private:
bool HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
void PrepareWindow(bool fullscreen);
static Keyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags);
static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
static UInt32 RetrieveStyle(HWND window);
static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
HCURSOR m_cursor;
HWND m_handle;
LONG_PTR m_callback;
WindowStyleFlags m_style;
Vector2i m_maxSize;
Vector2i m_minSize;
Vector2i m_mousePos;
Vector2i m_position;
Vector2ui m_size;
Thread m_thread;
Window* m_parent;
bool m_eventListener;
bool m_keyRepeat;
bool m_mouseInside;
bool m_ownsWindow;
bool m_sizemove;
bool m_smoothScrolling;
bool m_threadActive;
short m_scrolling;
};
}
#endif // NAZARA_WINDOWIMPL_HPP