GameEditor的Platform的核心实现

1.platform.h

#pragma once

#include "CommonHeaders.h"

#include "Window.h"

namespace primal::platform

{

struct window_init_info;

window create_window(const window_init_info* const init_info = nullptr);

void remove_window(window_id id);

}

2.Platform.cpp

#include "Platform.h"

#include "PlatformTypes.h"

namespace primal::platform

{

#ifdef _WIN64

namespace {

struct window_info {

HWND hwnd{ nullptr };

RECT client_area{ 0,0,1920,1080 };

RECT fullscreen_area{};

POINT top_left{ 0,0 };

DWORD style{ WS_VISIBLE };

bool is_fullscreen{ false };

bool is_closed{ false };

//~window_info() { assert(!is_fullscreen); }

};

utl::free_list<window_info> windows;

/*

utl::vector<u32> available_slots;

u32

add_to_windows(window_info info)

{

u32 id{ u32_invalid_id };

if (available_slots.empty())

{

id = (id::id_type)windows.size();

windows.emplace_back(info);

}

else

{

id = available_slots.back();

available_slots.pop_back();

assert(id!=u32_invalid_id);

windows[id] = info;

}

return id;

}

void remove_from_windows(u32 id)

{

assert(id < windows.size());

available_slots.emplace_back(id);

}

*/

window_info&

get_from_id(window_id id)

{

assert(id < windows.size());

assert(windows[id].hwnd);

return windows[id];

}

window_info&

get_from_handle(window_handle handle)

{

const window_id id{ (id::id_type)GetWindowLongPtr(handle,GWLP_USERDATA) };

return get_from_id(id);

}

LRESULT CALLBACK internal_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)

{

window_info* info{ nullptr };

switch (msg)

{

case WM_DESTROY:

get_from_handle(hwnd).is_closed = true;

break;

case WM_EXITSIZEMOVE:

info = &get_from_handle(hwnd);

break;

case WM_SIZE:

if (wparam == SIZE_MAXIMIZED)

{

info = &get_from_handle(hwnd);

}

break;

case WM_SYSCOMMAND:

if (wparam == SC_RESTORE)

{

info = &get_from_handle(hwnd);

}

break;

default:

break;

}

if (info)

{

assert(info->hwnd);

GetClientRect(info->hwnd, info->is_fullscreen ? &info->fullscreen_area : &info->client_area);

}

LONG_PTR long_ptr{GetWindowLongPtr(hwnd,0)};

return long_ptr

? ((window_proc)long_ptr)(hwnd, msg, wparam, lparam)

: DefWindowProc(hwnd, msg, wparam, lparam);

}

void

resize_window(const window_info& info, const RECT& area)

{

//Adjust the window size for correct

RECT window_rect{ area };

AdjustWindowRect(&window_rect, info.style, FALSE);

const s32 width{ window_rect.right - window_rect.left };

const s32 height{ window_rect.bottom - window_rect.top };

MoveWindow(info.hwnd, info.top_left.x, info.top_left.y, width, height, true);

}

void resize_window(window_id id, u32 width, u32 height)

{

window_info& info{ get_from_id(id) };

if (info.style & WS_CHILD)

{

GetClientRect(info.hwnd, &info.client_area);

}

else {

RECT& area{ info.is_fullscreen ? info.fullscreen_area : info.client_area };

area.bottom = area.top + height;

area.right = area.left + width;

resize_window(info, area);

}

}

void set_window_fullscreen(window_id id, bool is_fullscreen)

{

window_info& info{ get_from_id(id) };

if(info.is_fullscreen != is_fullscreen)

{

info.is_fullscreen = is_fullscreen;

if (is_fullscreen)

{

//store the current window dimensions so they can be restored

//when sitching out of fullscreen state.

GetClientRect(info.hwnd, &info.client_area);

RECT rect;

GetWindowRect(info.hwnd, &rect);

info.top_left.x = rect.left;

info.top_left.y = rect.top;

SetWindowLongPtr(info.hwnd, GWL_STYLE, 0);

ShowWindow(info.hwnd, SW_MAXIMIZE);

}

else

{

//info.style = WS_VISIBLE | WS_OVERLAPPEDWINDOW;

SetWindowLongPtr(info.hwnd, GWL_STYLE, info.style);

resize_window(info, info.client_area);

ShowWindow(info.hwnd, SW_SHOWNORMAL);

}

}

}

}//anonymous namespace

bool is_window_fullscreen(window_id id)

{

return get_from_id(id).is_fullscreen;

}

window_handle

get_window_handle(window_id id)

{

return get_from_id(id).hwnd;

}

void

set_window_caption(window_id id, const wchar_t* caption)

{

window_info& info{ get_from_id(id) };

SetWindowText(info.hwnd, caption);

}

math::u32v4

get_window_size(window_id id)

{

window_info& info{ get_from_id(id) };

RECT& area{ info.is_fullscreen ? info.fullscreen_area : info.client_area };

return { (u32)area.left,(u32)area.top,(u32)area.right,(u32)area.bottom };

}

bool

is_window_closed(window_id id)

{

return get_from_id(id).is_closed;

}

window

create_window(const window_init_info* const init_info)

{

window_proc callback{ init_info ? init_info->callback : nullptr };

window_handle parent{ init_info ? init_info->parent : nullptr };

//Setup a window class

WNDCLASSEX wc;

ZeroMemory(&wc, sizeof(wc));

wc.cbSize = sizeof(WNDCLASSEX);

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.lpfnWndProc = internal_window_proc;

wc.cbClsExtra = 0;

wc.cbWndExtra = callback ? sizeof(callback) : 0;

wc.hInstance = 0;

wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL,IDC_ARROW);

wc.hbrBackground = CreateSolidBrush(RGB(26,48,76));

wc.lpszMenuName = NULL;

wc.lpszClassName = L"PrimalWindow";

wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);

//Register the window class

RegisterClassExW(&wc);

window_info info{};

info.client_area.right = (init_info && init_info->width) ? info.client_area.left + init_info->width : info.client_area.right;

info.client_area.bottom = (init_info && init_info->height) ? info.client_area.left + init_info->height : info.client_area.bottom;

info.style |= parent ? WS_CHILD : WS_OVERLAPPEDWINDOW;

RECT rect{ info.client_area };

AdjustWindowRect(&rect, info.style, FALSE);

const wchar_t* caption{ (init_info && init_info->caption) ? init_info->caption : L"Primal Game" };

const s32 left{ init_info ? init_info->left : info.top_left.x };

const s32 top{ init_info ? init_info->top : info.top_left.y };

const s32 width{ rect.right - rect.left };

const s32 height{ rect.bottom - rect.top};

//Create an instance of the window class

info.hwnd = CreateWindowEx(

0, //extended style

wc.lpszClassName, //window class name

caption, // instance title

info.style, //window style

left, top,

width,height,

parent,

NULL,

NULL,

NULL

);

if (info.hwnd)

{

DEBUG_OP(SetLastError(0));

const window_id id{ windows.add(info) };

SetWindowLongPtr(info.hwnd, GWLP_USERDATA, (LONG_PTR)id);

if (callback) SetWindowLongPtr(info.hwnd, 0, (LONG_PTR)callback);

assert(GetLastError() == 0);

ShowWindow(info.hwnd, SW_SHOWNORMAL);

UpdateWindow(info.hwnd);

return window{ id };

}

return {};

}

void remove_window(window_id id)

{

window_info& info{ get_from_id(id) };

DestroyWindow(info.hwnd);

windows.remove(id);

}

#else

#error "must implement at least one platform"

#endif

void window::set_fullscreen(bool is_fullscreen) const

{

assert(is_valid());

set_window_fullscreen(_id, is_fullscreen);

}

bool window::is_fullscreen() const {

assert(is_valid());

return is_window_fullscreen(_id);

}

void* window::handle() const {

assert(is_valid());

return get_window_handle(_id);

}

void window::set_caption(const wchar_t* caption) const

{

assert(is_valid());

set_window_caption(_id,caption);

}

math::u32v4 window::size() const

{

assert(is_valid());

return get_window_size(_id);

}

void window::resize(u32 width, u32 height) const

{

assert(is_valid());

resize_window(_id, width, height);

}

u32 window::width() const

{

math::u32v4 s{ size() };

return s.z - s.x;

}

u32 window::height() const

{

math::u32v4 s{ size() };

return s.w - s.y;

}

bool window::is_closed() const

{

assert(is_valid());

return is_window_closed(_id);

}

}

相关推荐
鱼跃鹰飞几秒前
Leetcode279:完全平方数
数据结构·算法·leetcode·面试
小龙报几秒前
【数据结构与算法】单链表核心精讲:从概念到实战,吃透指针与动态内存操作
c语言·开发语言·数据结构·c++·人工智能·算法·链表
long3162 分钟前
合并排序 merge sort
java·数据结构·spring boot·算法·排序算法
范纹杉想快点毕业4 分钟前
STM32单片机与ZYNQ PS端 中断+状态机+FIFO 综合应用实战文档(初学者版)
linux·数据结构·数据库·算法·mongodb
多米Domi0112 小时前
0x3f 第49天 面向实习的八股背诵第六天 过了一遍JVM的知识点,看了相关视频讲解JVM内存,垃圾清理,买了plus,稍微看了点确定一下方向
jvm·数据结构·python·算法·leetcode
L_090711 小时前
【C++】高阶数据结构 -- 红黑树
数据结构·c++
划破黑暗的第一缕曙光15 小时前
[数据结构]:5.二叉树链式结构的实现1
数据结构
青桔柠薯片15 小时前
数据结构:单向链表,顺序栈和链式栈
数据结构·链表
XiaoFan01215 小时前
将有向工作流图转为结构树的实现
java·数据结构·决策树
睡一觉就好了。16 小时前
快速排序——霍尔排序,前后指针排序,非递归排序
数据结构·算法·排序算法