Add WindowImpl-Win32
This commit is contained in:
parent
831c6c83e9
commit
bcc92abbef
|
|
@ -20,6 +20,7 @@
|
||||||
<ClInclude Include="..\..\src\kiwano\core\event\MouseEvent.h" />
|
<ClInclude Include="..\..\src\kiwano\core\event\MouseEvent.h" />
|
||||||
<ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h" />
|
<ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h" />
|
||||||
<ClInclude Include="..\..\src\kiwano\core\Library.h" />
|
<ClInclude Include="..\..\src\kiwano\core\Library.h" />
|
||||||
|
<ClInclude Include="..\..\src\kiwano\core\Singleton.h" />
|
||||||
<ClInclude Include="..\..\src\kiwano\kiwano.h" />
|
<ClInclude Include="..\..\src\kiwano\kiwano.h" />
|
||||||
<ClInclude Include="..\..\src\kiwano\config.h" />
|
<ClInclude Include="..\..\src\kiwano\config.h" />
|
||||||
<ClInclude Include="..\..\src\kiwano\macros.h" />
|
<ClInclude Include="..\..\src\kiwano\macros.h" />
|
||||||
|
|
@ -131,6 +132,7 @@
|
||||||
<ClCompile Include="..\..\src\kiwano\platform\Input.cpp" />
|
<ClCompile Include="..\..\src\kiwano\platform\Input.cpp" />
|
||||||
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" />
|
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" />
|
||||||
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" />
|
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\kiwano\platform\win32\WindowImpl.cpp" />
|
||||||
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp" />
|
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp" />
|
||||||
<ClCompile Include="..\..\src\kiwano\renderer\Brush.cpp" />
|
<ClCompile Include="..\..\src\kiwano\renderer\Brush.cpp" />
|
||||||
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp" />
|
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp" />
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,9 @@
|
||||||
<ClInclude Include="..\..\src\kiwano\core\Director.h">
|
<ClInclude Include="..\..\src\kiwano\core\Director.h">
|
||||||
<Filter>core</Filter>
|
<Filter>core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\kiwano\core\Singleton.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
|
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
|
||||||
|
|
@ -479,5 +482,8 @@
|
||||||
<ClCompile Include="..\..\src\kiwano\core\Director.cpp">
|
<ClCompile Include="..\..\src\kiwano\core\Director.cpp">
|
||||||
<Filter>core</Filter>
|
<Filter>core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\kiwano\platform\win32\WindowImpl.cpp">
|
||||||
|
<Filter>platform\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -42,7 +42,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool Sound::Load(String const& file_path)
|
bool Sound::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_WARN(L"Media file '%s' not found", file_path.c_str());
|
KGE_WARN(L"Media file '%s' not found", file_path.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -53,7 +53,7 @@ namespace kiwano
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
|
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
|
|
||||||
HRESULT hr = transcoder_.LoadMediaFile(full_path);
|
HRESULT hr = transcoder_.LoadMediaFile(full_path);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
|
@ -62,7 +62,7 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
|
if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -86,7 +86,7 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
|
if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace kiwano
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
// Setup Platform/Renderer bindings
|
// Setup Platform/Renderer bindings
|
||||||
target_window_ = Renderer::instance().GetTargetWindow();
|
target_window_ = Renderer::Instance().GetTargetWindow();
|
||||||
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
@ -54,7 +54,7 @@ namespace kiwano
|
||||||
io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
|
io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
|
||||||
io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
|
io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
|
||||||
|
|
||||||
ImGui_Impl_Init(Renderer::instance());
|
ImGui_Impl_Init(Renderer::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiModule::DestroyComponent()
|
void ImGuiModule::DestroyComponent()
|
||||||
|
|
@ -71,10 +71,10 @@ namespace kiwano
|
||||||
io.DeltaTime = dt.Seconds();
|
io.DeltaTime = dt.Seconds();
|
||||||
|
|
||||||
// Read keyboard modifiers inputs
|
// Read keyboard modifiers inputs
|
||||||
io.KeyCtrl = Input::instance().IsDown(KeyCode::Ctrl);
|
io.KeyCtrl = Input::Instance().IsDown(KeyCode::Ctrl);
|
||||||
io.KeyShift = Input::instance().IsDown(KeyCode::Shift);
|
io.KeyShift = Input::Instance().IsDown(KeyCode::Shift);
|
||||||
io.KeyAlt = Input::instance().IsDown(KeyCode::Alt);
|
io.KeyAlt = Input::Instance().IsDown(KeyCode::Alt);
|
||||||
io.KeySuper = Input::instance().IsDown(KeyCode::Super);
|
io.KeySuper = Input::Instance().IsDown(KeyCode::Super);
|
||||||
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
|
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
|
||||||
|
|
||||||
// Update OS mouse position
|
// Update OS mouse position
|
||||||
|
|
@ -155,7 +155,7 @@ namespace kiwano
|
||||||
KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
|
KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
|
||||||
|
|
||||||
// Setup display size (every frame to accommodate for window resizing)
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
Size display_size = Renderer::instance().GetOutputSize();
|
Size display_size = Renderer::Instance().GetOutputSize();
|
||||||
io.DisplaySize = ImVec2(display_size.x, display_size.y);
|
io.DisplaySize = ImVec2(display_size.x, display_size.y);
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
@ -180,7 +180,7 @@ namespace kiwano
|
||||||
::SetCursorPos(pos.x, pos.y);
|
::SetCursorPos(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point pos = Input::instance().GetMousePos();
|
Point pos = Input::Instance().GetMousePos();
|
||||||
io.MousePos = ImVec2(pos.x, pos.y);
|
io.MousePos = ImVec2(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ namespace kiwano
|
||||||
case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break;
|
case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::instance().SetCursor(cursor);
|
Window::Instance().SetCursor(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,14 +95,14 @@ namespace kiwano
|
||||||
|
|
||||||
if (status == Status::Normal)
|
if (status == Status::Normal)
|
||||||
{
|
{
|
||||||
Window::instance().SetCursor(CursorType::Arrow);
|
Window::Instance().SetCursor(CursorType::Arrow);
|
||||||
|
|
||||||
if (mouse_out_callback_)
|
if (mouse_out_callback_)
|
||||||
mouse_out_callback_(this);
|
mouse_out_callback_(this);
|
||||||
}
|
}
|
||||||
else if (status == Status::Hover)
|
else if (status == Status::Hover)
|
||||||
{
|
{
|
||||||
Window::instance().SetCursor(CursorType::Hand);
|
Window::Instance().SetCursor(CursorType::Hand);
|
||||||
|
|
||||||
if (old_status == Status::Pressed)
|
if (old_status == Status::Pressed)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
if (!ctx_)
|
if (!ctx_)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTextureRenderTarget(ctx_);
|
Renderer::Instance().CreateTextureRenderTarget(ctx_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stroke_brush_)
|
if (!stroke_brush_)
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,9 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ss << "Render: " << Renderer::instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
|
ss << "Render: " << Renderer::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
|
||||||
|
|
||||||
ss << "Primitives / sec: " << std::fixed << Renderer::instance().GetStatus().primitives * frame_time_.size() << std::endl;
|
ss << "Primitives / sec: " << std::fixed << Renderer::Instance().GetStatus().primitives * frame_time_.size() << std::endl;
|
||||||
|
|
||||||
ss << "Memory: ";
|
ss << "Memory: ";
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool Frame::Load(String const& file_path)
|
bool Frame::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
TexturePtr texture = TextureCache::instance().AddOrGetTexture(file_path);
|
TexturePtr texture = TextureCache::Instance().AddOrGetTexture(file_path);
|
||||||
if (texture->IsValid())
|
if (texture->IsValid())
|
||||||
{
|
{
|
||||||
SetTexture(texture);
|
SetTexture(texture);
|
||||||
|
|
@ -40,7 +40,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool Frame::Load(Resource const& res)
|
bool Frame::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
TexturePtr texture = TextureCache::instance().AddOrGetTexture(res);
|
TexturePtr texture = TextureCache::Instance().AddOrGetTexture(res);
|
||||||
if (texture->IsValid())
|
if (texture->IsValid())
|
||||||
{
|
{
|
||||||
SetTexture(texture);
|
SetTexture(texture);
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,13 @@ namespace kiwano
|
||||||
|
|
||||||
bool GifSprite::Load(String const& file_path)
|
bool GifSprite::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
GifImagePtr image = TextureCache::instance().AddOrGetGifImage(file_path);
|
GifImagePtr image = TextureCache::Instance().AddOrGetGifImage(file_path);
|
||||||
return Load(image);
|
return Load(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifSprite::Load(Resource const& res)
|
bool GifSprite::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
GifImagePtr image = TextureCache::instance().AddOrGetGifImage(res);
|
GifImagePtr image = TextureCache::Instance().AddOrGetGifImage(res);
|
||||||
return Load(image);
|
return Load(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace kiwano
|
||||||
|
|
||||||
if (!frame_rt_)
|
if (!frame_rt_)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTextureRenderTarget(frame_rt_);
|
Renderer::Instance().CreateTextureRenderTarget(frame_rt_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gif_->GetFramesCount() > 0)
|
if (gif_->GetFramesCount() > 0)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace kiwano
|
||||||
SetStage(this);
|
SetStage(this);
|
||||||
|
|
||||||
SetAnchor(Vec2{ 0, 0 });
|
SetAnchor(Vec2{ 0, 0 });
|
||||||
SetSize(Renderer::instance().GetOutputSize());
|
SetSize(Renderer::Instance().GetOutputSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
Stage::~Stage()
|
Stage::~Stage()
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ namespace kiwano
|
||||||
|
|
||||||
out_stage_ = prev;
|
out_stage_ = prev;
|
||||||
in_stage_ = next;
|
in_stage_ = next;
|
||||||
window_size_ = Renderer::instance().GetOutputSize();
|
window_size_ = Renderer::Instance().GetOutputSize();
|
||||||
|
|
||||||
if (in_stage_)
|
if (in_stage_)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,52 +26,66 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::streambuf* cout_buffer, * cerr_buffer;
|
std::streambuf* cin_buffer, * cout_buffer, * cerr_buffer;
|
||||||
std::fstream console_output, console_error;
|
std::fstream console_input, console_output, console_error;
|
||||||
|
|
||||||
std::wstreambuf* wcout_buffer, * wcerr_buffer;
|
std::wstreambuf* wcin_buffer, * wcout_buffer, * wcerr_buffer;
|
||||||
std::wfstream wconsole_output, wconsole_error;
|
std::wfstream wconsole_input, wconsole_output, wconsole_error;
|
||||||
|
|
||||||
void RedirectStdIO()
|
void RedirectStdIO()
|
||||||
{
|
{
|
||||||
|
cin_buffer = std::cin.rdbuf();
|
||||||
cout_buffer = std::cout.rdbuf();
|
cout_buffer = std::cout.rdbuf();
|
||||||
cerr_buffer = std::cerr.rdbuf();
|
cerr_buffer = std::cerr.rdbuf();
|
||||||
|
wcin_buffer = std::wcin.rdbuf();
|
||||||
wcout_buffer = std::wcout.rdbuf();
|
wcout_buffer = std::wcout.rdbuf();
|
||||||
wcerr_buffer = std::wcerr.rdbuf();
|
wcerr_buffer = std::wcerr.rdbuf();
|
||||||
|
|
||||||
|
console_input.open("CONIN$", std::ios::in);
|
||||||
console_output.open("CONOUT$", std::ios::out);
|
console_output.open("CONOUT$", std::ios::out);
|
||||||
console_error.open("CONOUT$", std::ios::out);
|
console_error.open("CONOUT$", std::ios::out);
|
||||||
|
wconsole_input.open("CONIN$", std::ios::in);
|
||||||
wconsole_output.open("CONOUT$", std::ios::out);
|
wconsole_output.open("CONOUT$", std::ios::out);
|
||||||
wconsole_error.open("CONOUT$", std::ios::out);
|
wconsole_error.open("CONOUT$", std::ios::out);
|
||||||
|
|
||||||
FILE* dummy;
|
FILE* dummy;
|
||||||
freopen_s(&dummy, "CONOUT$", "w+t", stdout);
|
freopen_s(&dummy, "CONOUT$", "w+t", stdout);
|
||||||
|
freopen_s(&dummy, "CONIN$", "r+t", stdin);
|
||||||
freopen_s(&dummy, "CONOUT$", "w+t", stderr);
|
freopen_s(&dummy, "CONOUT$", "w+t", stderr);
|
||||||
(void)dummy;
|
(void)dummy;
|
||||||
|
|
||||||
|
std::cin.rdbuf(console_input.rdbuf());
|
||||||
std::cout.rdbuf(console_output.rdbuf());
|
std::cout.rdbuf(console_output.rdbuf());
|
||||||
std::cerr.rdbuf(console_error.rdbuf());
|
std::cerr.rdbuf(console_error.rdbuf());
|
||||||
|
std::wcin.rdbuf(wconsole_input.rdbuf());
|
||||||
std::wcout.rdbuf(wconsole_output.rdbuf());
|
std::wcout.rdbuf(wconsole_output.rdbuf());
|
||||||
std::wcerr.rdbuf(wconsole_error.rdbuf());
|
std::wcerr.rdbuf(wconsole_error.rdbuf());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetStdIO()
|
void ResetStdIO()
|
||||||
{
|
{
|
||||||
|
console_input.close();
|
||||||
console_output.close();
|
console_output.close();
|
||||||
console_error.close();
|
console_error.close();
|
||||||
|
wconsole_input.close();
|
||||||
wconsole_output.close();
|
wconsole_output.close();
|
||||||
wconsole_error.close();
|
wconsole_error.close();
|
||||||
|
|
||||||
|
std::cin.rdbuf(cin_buffer);
|
||||||
std::cout.rdbuf(cout_buffer);
|
std::cout.rdbuf(cout_buffer);
|
||||||
std::cerr.rdbuf(cerr_buffer);
|
std::cerr.rdbuf(cerr_buffer);
|
||||||
|
std::wcin.rdbuf(wcin_buffer);
|
||||||
std::wcout.rdbuf(wcout_buffer);
|
std::wcout.rdbuf(wcout_buffer);
|
||||||
std::wcerr.rdbuf(wcerr_buffer);
|
std::wcerr.rdbuf(wcerr_buffer);
|
||||||
|
|
||||||
fclose(stdout);
|
fclose(stdout);
|
||||||
|
fclose(stdin);
|
||||||
fclose(stderr);
|
fclose(stderr);
|
||||||
|
|
||||||
|
cin_buffer = nullptr;
|
||||||
cout_buffer = nullptr;
|
cout_buffer = nullptr;
|
||||||
cerr_buffer = nullptr;
|
cerr_buffer = nullptr;
|
||||||
|
wcin_buffer = nullptr;
|
||||||
wcout_buffer = nullptr;
|
wcout_buffer = nullptr;
|
||||||
wcerr_buffer = nullptr;
|
wcerr_buffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,26 +26,26 @@
|
||||||
|
|
||||||
#ifndef KGE_SYS_LOG
|
#ifndef KGE_SYS_LOG
|
||||||
# ifdef KGE_DEBUG
|
# ifdef KGE_DEBUG
|
||||||
# define KGE_SYS_LOG(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::System, FORMAT, __VA_ARGS__)
|
# define KGE_SYS_LOG(FORMAT, ...) ::kiwano::Logger::Instance().Printf(::kiwano::Logger::Level::System, FORMAT, __VA_ARGS__)
|
||||||
# else
|
# else
|
||||||
# define KGE_SYS_LOG __noop
|
# define KGE_SYS_LOG __noop
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KGE_WARN
|
#ifndef KGE_WARN
|
||||||
# define KGE_WARN(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Warning, FORMAT, __VA_ARGS__)
|
# define KGE_WARN(FORMAT, ...) ::kiwano::Logger::Instance().Printf(::kiwano::Logger::Level::Warning, FORMAT, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KGE_ERROR
|
#ifndef KGE_ERROR
|
||||||
# define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Error, FORMAT, __VA_ARGS__)
|
# define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::Instance().Printf(::kiwano::Logger::Level::Error, FORMAT, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KGE_LOG
|
#ifndef KGE_LOG
|
||||||
# define KGE_LOG(...) ::kiwano::Logger::instance().Println(::kiwano::Logger::Level::Info, __VA_ARGS__)
|
# define KGE_LOG(...) ::kiwano::Logger::Instance().Println(::kiwano::Logger::Level::Info, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KGE_LOGF
|
#ifndef KGE_LOGF
|
||||||
# define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Info, FORMAT, __VA_ARGS__)
|
# define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::Instance().Printf(::kiwano::Logger::Level::Info, FORMAT, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) 2016-2020 Kiwano - Nomango
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
struct Singleton
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Singleton() = default;
|
||||||
|
Singleton(const Singleton&) = delete;
|
||||||
|
Singleton& operator=(const Singleton&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ObjectCreator
|
||||||
|
{
|
||||||
|
ObjectCreator()
|
||||||
|
{
|
||||||
|
(void)Singleton<_Ty>::Instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Dummy() const {}
|
||||||
|
};
|
||||||
|
static ObjectCreator creator_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using object_type = _Ty;
|
||||||
|
|
||||||
|
static inline object_type& Instance()
|
||||||
|
{
|
||||||
|
static object_type instance;
|
||||||
|
creator_.Dummy();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
typename Singleton<_Ty>::ObjectCreator Singleton<_Ty>::creator_;
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace kiwano
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <3rd-party/OuterC/oc/oc.h>
|
#include <3rd-party/OuterC/oc/oc.h>
|
||||||
#include <kiwano/macros.h>
|
#include <kiwano/macros.h>
|
||||||
|
#include <kiwano/core/Singleton.h>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -113,11 +114,6 @@ namespace kiwano
|
||||||
/// @brief JSON对象容器
|
/// @brief JSON对象容器
|
||||||
using Json = oc::basic_json<Map, Vector, String, int, double, bool, std::allocator>;
|
using Json = oc::basic_json<Map, Vector, String, int, double, bool, std::allocator>;
|
||||||
|
|
||||||
/// \~chinese
|
|
||||||
/// @brief 데절친겼
|
|
||||||
template <typename _Ty>
|
|
||||||
using Singleton = oc::singleton<_Ty>;
|
|
||||||
|
|
||||||
/// \~chinese
|
/// \~chinese
|
||||||
/// @brief 侵入式链表容器
|
/// @brief 侵入式链表容器
|
||||||
template <typename _Ty>
|
template <typename _Ty>
|
||||||
|
|
|
||||||
|
|
@ -36,31 +36,12 @@ namespace kiwano
|
||||||
Queue<FunctionToPerform> functions_to_perform_;
|
Queue<FunctionToPerform> functions_to_perform_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Config(String const& title, uint32_t width, uint32_t height, uint32_t icon)
|
|
||||||
: debug(false)
|
|
||||||
{
|
|
||||||
window.title = title;
|
|
||||||
window.width = width;
|
|
||||||
window.height = height;
|
|
||||||
window.icon = icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
|
|
||||||
: debug(false)
|
|
||||||
{
|
|
||||||
window = wnd_config;
|
|
||||||
render = render_config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace kiwano
|
|
||||||
{
|
|
||||||
Application::Application()
|
Application::Application()
|
||||||
: time_scale_(1.f)
|
: time_scale_(1.f)
|
||||||
{
|
{
|
||||||
Use(&Renderer::instance());
|
Use(&Renderer::Instance());
|
||||||
Use(&Input::instance());
|
Use(&Input::Instance());
|
||||||
Use(&Director::instance());
|
Use(&Director::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
|
|
@ -68,21 +49,18 @@ namespace kiwano
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Run(const Config& config)
|
void Application::Run(bool debug)
|
||||||
{
|
{
|
||||||
Window::instance().Init(config.window);
|
|
||||||
Renderer::instance().Init(config.render);
|
|
||||||
|
|
||||||
// Setup all components
|
// Setup all components
|
||||||
for (auto c : comps_)
|
for (auto c : comps_)
|
||||||
{
|
{
|
||||||
c->SetupComponent();
|
c->SetupComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Director::instance().ShowDebugInfo(true);
|
Director::Instance().ShowDebugInfo(true);
|
||||||
Renderer::instance().SetCollectingStatus(true);
|
Renderer::Instance().SetCollectingStatus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything is ready
|
// Everything is ready
|
||||||
|
|
@ -90,7 +68,7 @@ namespace kiwano
|
||||||
|
|
||||||
last_update_time_ = Time::Now();
|
last_update_time_ = Time::Now();
|
||||||
|
|
||||||
Window& window = Window::instance();
|
Window& window = Window::Instance();
|
||||||
while (!window.ShouldClose())
|
while (!window.ShouldClose())
|
||||||
{
|
{
|
||||||
while (EventPtr evt = window.PollEvent())
|
while (EventPtr evt = window.PollEvent())
|
||||||
|
|
@ -105,20 +83,23 @@ namespace kiwano
|
||||||
|
|
||||||
void Application::Quit()
|
void Application::Quit()
|
||||||
{
|
{
|
||||||
Window::instance().Destroy();
|
Window::Instance().Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Destroy()
|
void Application::Destroy()
|
||||||
{
|
{
|
||||||
// Clear all resources
|
// Clear all resources
|
||||||
Director::instance().ClearStages();
|
Director::Instance().ClearStages();
|
||||||
ResourceCache::instance().Clear();
|
ResourceCache::Instance().Clear();
|
||||||
TextureCache::instance().Clear();
|
TextureCache::Instance().Clear();
|
||||||
|
|
||||||
for (auto iter = comps_.rbegin(); iter != comps_.rend(); ++iter)
|
for (auto iter = comps_.rbegin(); iter != comps_.rend(); ++iter)
|
||||||
{
|
{
|
||||||
(*iter)->DestroyComponent();
|
(*iter)->DestroyComponent();
|
||||||
}
|
}
|
||||||
|
render_comps_.clear();
|
||||||
|
update_comps_.clear();
|
||||||
|
event_comps_.clear();
|
||||||
comps_.clear();
|
comps_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +190,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
Renderer& renderer = Renderer::instance();
|
Renderer& renderer = Renderer::Instance();
|
||||||
for (auto c : render_comps_)
|
for (auto c : render_comps_)
|
||||||
{
|
{
|
||||||
c->OnRender(renderer);
|
c->OnRender(renderer);
|
||||||
|
|
|
||||||
|
|
@ -31,43 +31,6 @@
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* \~chinese
|
|
||||||
* @brief 应用程序配置
|
|
||||||
* @details 启动 Kiwano 应用程序前的初始化选项
|
|
||||||
*/
|
|
||||||
struct Config
|
|
||||||
{
|
|
||||||
WindowConfig window; ///< 窗口配置
|
|
||||||
RenderConfig render; ///< 渲染配置
|
|
||||||
bool debug; ///< 启用调试模式
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \~chinese
|
|
||||||
* @param title 窗口标题
|
|
||||||
* @param width 窗口宽度
|
|
||||||
* @param height 窗口高度
|
|
||||||
* @param icon 窗口图标的资源ID
|
|
||||||
*/
|
|
||||||
Config(
|
|
||||||
String const& title = L"Kiwano Game",
|
|
||||||
uint32_t width = 640,
|
|
||||||
uint32_t height = 480,
|
|
||||||
uint32_t icon = 0
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \~chinese
|
|
||||||
* @param wnd_config 窗口配置
|
|
||||||
* @param render_config 渲染配置
|
|
||||||
*/
|
|
||||||
Config(
|
|
||||||
WindowConfig const& wnd_config,
|
|
||||||
RenderConfig const& render_config = RenderConfig()
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 应用程序,控制游戏的整个生命周期,包括初始化、启动、结束以及事件分发等
|
* @brief 应用程序,控制游戏的整个生命周期,包括初始化、启动、结束以及事件分发等
|
||||||
|
|
@ -85,23 +48,23 @@ namespace kiwano
|
||||||
* @brief 初始化完成处理
|
* @brief 初始化完成处理
|
||||||
* @details 重载该函数以在应用程序初始化完成后自动执行
|
* @details 重载该函数以在应用程序初始化完成后自动执行
|
||||||
*/
|
*/
|
||||||
virtual void OnReady() {}
|
virtual void OnReady();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 应用程序销毁处理
|
* @brief 应用程序销毁处理
|
||||||
* @details 重载该函数以处理应用程序销毁时的行为,如完成资源回收等
|
* @details 重载该函数以处理应用程序销毁时的行为,如完成资源回收等
|
||||||
*/
|
*/
|
||||||
virtual void OnDestroy() {}
|
virtual void OnDestroy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 启动应用程序
|
* @brief 启动应用程序
|
||||||
* @details 初始化所有功能组件后执行 OnReady 函数
|
* @details 初始化所有功能组件后执行 OnReady 函数
|
||||||
* @param config 初始化配置
|
* @param debug 是否启用调试模式
|
||||||
* @note 该函数是阻塞的,应用程序结束时函数返回
|
* @note 该函数是阻塞的,应用程序结束时函数返回
|
||||||
*/
|
*/
|
||||||
void Run(Config const& config = Config());
|
void Run(bool debug = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -148,10 +111,18 @@ namespace kiwano
|
||||||
static void PreformInMainThread(Function<void()> func);
|
static void PreformInMainThread(Function<void()> func);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Render();
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 更新所有组件
|
||||||
|
*/
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 渲染所有组件
|
||||||
|
*/
|
||||||
|
void Render();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float time_scale_;
|
float time_scale_;
|
||||||
Time last_update_time_;
|
Time last_update_time_;
|
||||||
|
|
@ -160,4 +131,12 @@ namespace kiwano
|
||||||
Vector<UpdateComponent*> update_comps_;
|
Vector<UpdateComponent*> update_comps_;
|
||||||
Vector<EventComponent*> event_comps_;
|
Vector<EventComponent*> event_comps_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void Application::OnReady()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Application::OnDestroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,32 +19,9 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include <kiwano/platform/Window.h>
|
#include <kiwano/platform/Window.h>
|
||||||
#include <kiwano/platform/Application.h>
|
|
||||||
#include <kiwano/core/event/MouseEvent.h>
|
|
||||||
#include <kiwano/core/event/KeyEvent.h>
|
|
||||||
#include <kiwano/core/event/WindowEvent.h>
|
|
||||||
#include <kiwano/core/Logger.h>
|
|
||||||
|
|
||||||
#include <imm.h> // ImmAssociateContext
|
|
||||||
#pragma comment(lib, "imm32.lib")
|
|
||||||
|
|
||||||
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
|
||||||
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
|
|
||||||
#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
|
|
||||||
#define KGE_WND_CLASS_NAME L"KiwanoAppWnd"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
{
|
|
||||||
MONITORINFOEX GetMoniterInfoEx(HWND hwnd);
|
|
||||||
|
|
||||||
void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_width, uint32_t* win_height);
|
|
||||||
|
|
||||||
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name);
|
|
||||||
|
|
||||||
void RestoreResolution(WCHAR* device_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowConfig::WindowConfig(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen)
|
WindowConfig::WindowConfig(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen)
|
||||||
: title(title)
|
: title(title)
|
||||||
|
|
@ -57,13 +34,9 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window()
|
Window::Window()
|
||||||
: handle_(nullptr)
|
: should_close_(false)
|
||||||
, width_(0)
|
, width_(0)
|
||||||
, height_(0)
|
, height_(0)
|
||||||
, device_name_(nullptr)
|
|
||||||
, is_fullscreen_(false)
|
|
||||||
, resizable_(false)
|
|
||||||
, mouse_cursor_(CursorType::Arrow)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,125 +44,9 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Init(WindowConfig const& config)
|
|
||||||
{
|
|
||||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
|
||||||
WNDCLASSEX wcex = { 0 };
|
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
wcex.lpszClassName = KGE_WND_CLASS_NAME;
|
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
|
|
||||||
wcex.lpfnWndProc = Window::WndProc;
|
|
||||||
wcex.hIcon = nullptr;
|
|
||||||
wcex.cbClsExtra = 0;
|
|
||||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
|
||||||
wcex.hInstance = hinst;
|
|
||||||
wcex.hbrBackground = (HBRUSH)(::GetStockObject(BLACK_BRUSH));
|
|
||||||
wcex.lpszMenuName = nullptr;
|
|
||||||
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
|
|
||||||
|
|
||||||
if (config.icon)
|
|
||||||
{
|
|
||||||
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0,
|
|
||||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
::RegisterClassExW(&wcex);
|
|
||||||
|
|
||||||
// Get the nearest monitor to this window
|
|
||||||
HMONITOR monitor = ::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
|
||||||
|
|
||||||
// Get the target monitor info
|
|
||||||
MONITORINFOEX monitor_info_ex;
|
|
||||||
memset(&monitor_info_ex, 0, sizeof(MONITORINFOEX));
|
|
||||||
monitor_info_ex.cbSize = sizeof(MONITORINFOEX);
|
|
||||||
::GetMonitorInfoW(monitor, &monitor_info_ex);
|
|
||||||
|
|
||||||
// Save the device name
|
|
||||||
int len = lstrlenW(monitor_info_ex.szDevice);
|
|
||||||
device_name_ = new wchar_t[len + 1];
|
|
||||||
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
|
||||||
|
|
||||||
uint32_t width = config.width;
|
|
||||||
uint32_t height = config.height;
|
|
||||||
int left = -1;
|
|
||||||
int top = -1;
|
|
||||||
|
|
||||||
resizable_ = config.resizable;
|
|
||||||
is_fullscreen_ = config.fullscreen;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
top = monitor_info_ex.rcMonitor.top;
|
|
||||||
left = monitor_info_ex.rcMonitor.left;
|
|
||||||
|
|
||||||
if (width > static_cast<uint32_t>(monitor_info_ex.rcWork.right - left))
|
|
||||||
width = static_cast<uint32_t>(monitor_info_ex.rcWork.right - left);
|
|
||||||
|
|
||||||
if (height > static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top))
|
|
||||||
height = static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left;
|
|
||||||
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
|
|
||||||
|
|
||||||
uint32_t win_width, win_height;
|
|
||||||
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
|
|
||||||
|
|
||||||
left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
|
|
||||||
top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;
|
|
||||||
width = win_width;
|
|
||||||
height = win_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_ = ::CreateWindowExW(
|
|
||||||
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
|
||||||
KGE_WND_CLASS_NAME,
|
|
||||||
config.title.c_str(),
|
|
||||||
GetWindowStyle(),
|
|
||||||
left,
|
|
||||||
top,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
hinst,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (handle_ == nullptr)
|
|
||||||
{
|
|
||||||
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
|
|
||||||
win32::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
|
|
||||||
// disable imm
|
|
||||||
::ImmAssociateContext(handle_, nullptr);
|
|
||||||
|
|
||||||
// use Application instance in message loop
|
|
||||||
::SetWindowLongPtr(handle_, GWLP_USERDATA, LONG_PTR(this));
|
|
||||||
|
|
||||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
|
||||||
::UpdateWindow(handle_);
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
ChangeFullScreenResolution(width_, height_, device_name_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EventPtr Window::PollEvent()
|
EventPtr Window::PollEvent()
|
||||||
{
|
{
|
||||||
MSG msg;
|
PumpEvents();
|
||||||
while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
::TranslateMessage(&msg);
|
|
||||||
::DispatchMessageW(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventPtr evt;
|
EventPtr evt;
|
||||||
if (!event_queue_.empty())
|
if (!event_queue_.empty())
|
||||||
|
|
@ -202,135 +59,27 @@ namespace kiwano
|
||||||
|
|
||||||
String Window::GetTitle() const
|
String Window::GetTitle() const
|
||||||
{
|
{
|
||||||
if (handle_)
|
return title_;
|
||||||
{
|
|
||||||
wchar_t title[256];
|
|
||||||
::GetWindowTextW(handle_, title, 256);
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetTitle(String const& title)
|
|
||||||
{
|
|
||||||
if (handle_)
|
|
||||||
::SetWindowTextW(handle_, title.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Size Window::GetSize() const
|
Size Window::GetSize() const
|
||||||
{
|
{
|
||||||
return Size{
|
return Size(float(width_), float(height_));
|
||||||
static_cast<float>(width_),
|
|
||||||
static_cast<float>(height_)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetWidth() const
|
uint32_t Window::GetWidth() const
|
||||||
{
|
{
|
||||||
return static_cast<float>(width_);
|
return width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetHeight() const
|
uint32_t Window::GetHeight() const
|
||||||
{
|
{
|
||||||
return static_cast<float>(height_);
|
return height_;
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetIcon(uint32_t icon_resource)
|
|
||||||
{
|
|
||||||
if (handle_)
|
|
||||||
{
|
|
||||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
|
||||||
HICON icon = (HICON)::LoadImageW(
|
|
||||||
hinstance,
|
|
||||||
MAKEINTRESOURCE(icon_resource),
|
|
||||||
IMAGE_ICON,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
|
||||||
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::Resize(int width, int height)
|
|
||||||
{
|
|
||||||
if (handle_ && !is_fullscreen_)
|
|
||||||
{
|
|
||||||
RECT rc = { 0, 0, int(width), int(height) };
|
|
||||||
::AdjustWindowRect(&rc, GetWindowStyle(), false);
|
|
||||||
|
|
||||||
width = rc.right - rc.left;
|
|
||||||
height = rc.bottom - rc.top;
|
|
||||||
::SetWindowPos(handle_, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetFullscreen(bool fullscreen, int width, int height)
|
|
||||||
{
|
|
||||||
if (is_fullscreen_ != fullscreen || width != width_ || height != height_)
|
|
||||||
{
|
|
||||||
is_fullscreen_ = fullscreen;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
// move window to (0, 0) before display switch
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width_, height_, SWP_NOACTIVATE);
|
|
||||||
|
|
||||||
ChangeFullScreenResolution(width, height, device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
|
|
||||||
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, SWP_NOACTIVATE);
|
|
||||||
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
|
|
||||||
uint32_t screenw = info.rcWork.right - info.rcWork.left;
|
|
||||||
uint32_t screenh = info.rcWork.bottom - info.rcWork.top;
|
|
||||||
|
|
||||||
uint32_t win_width, win_height;
|
|
||||||
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
|
|
||||||
|
|
||||||
int left = screenw > win_width ? ((screenw - win_width) / 2) : 0;
|
|
||||||
int top = screenh > win_height ? ((screenh - win_height) / 2) : 0;
|
|
||||||
|
|
||||||
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
|
||||||
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, win_width, win_height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
|
|
||||||
|
|
||||||
// Update window rect
|
|
||||||
RECT rc;
|
|
||||||
::GetClientRect(handle_, &rc);
|
|
||||||
|
|
||||||
width_ = static_cast<uint32_t>(rc.right - rc.left);
|
|
||||||
height_ = static_cast<uint32_t>(rc.bottom - rc.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetCursor(CursorType cursor)
|
|
||||||
{
|
|
||||||
mouse_cursor_ = cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowHandle Window::GetHandle() const
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::ShouldClose()
|
bool Window::ShouldClose()
|
||||||
{
|
{
|
||||||
return handle_ == nullptr;
|
return should_close_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::PushEvent(EventPtr evt)
|
void Window::PushEvent(EventPtr evt)
|
||||||
|
|
@ -340,306 +89,12 @@ namespace kiwano
|
||||||
|
|
||||||
void Window::Destroy()
|
void Window::Destroy()
|
||||||
{
|
{
|
||||||
if (is_fullscreen_)
|
while (!event_queue_.empty())
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
if (device_name_)
|
|
||||||
{
|
{
|
||||||
delete[] device_name_;
|
event_queue_.pop();
|
||||||
device_name_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle_)
|
should_close_ = true;
|
||||||
{
|
|
||||||
::DestroyWindow(handle_);
|
|
||||||
handle_ = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(KGE_WIN32)
|
|
||||||
|
|
||||||
DWORD Window::GetWindowStyle() const
|
|
||||||
{
|
|
||||||
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::UpdateCursor()
|
|
||||||
{
|
|
||||||
LPTSTR win32_cursor = IDC_ARROW;
|
|
||||||
switch (mouse_cursor_)
|
|
||||||
{
|
|
||||||
case CursorType::Arrow: win32_cursor = IDC_ARROW; break;
|
|
||||||
case CursorType::TextInput: win32_cursor = IDC_IBEAM; break;
|
|
||||||
case CursorType::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
|
||||||
case CursorType::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
|
||||||
case CursorType::SizeNS: win32_cursor = IDC_SIZENS; break;
|
|
||||||
case CursorType::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
|
||||||
case CursorType::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
|
||||||
case CursorType::Hand: win32_cursor = IDC_HAND; break;
|
|
||||||
}
|
|
||||||
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetActive(bool actived)
|
|
||||||
{
|
|
||||||
if (!handle_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
if (actived)
|
|
||||||
{
|
|
||||||
ChangeFullScreenResolution(width_, height_, device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width_, height_, SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
||||||
::ShowWindow(handle_, SW_MINIMIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
|
|
||||||
{
|
|
||||||
Window* window = reinterpret_cast<Window*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
|
|
||||||
if (window == nullptr)
|
|
||||||
{
|
|
||||||
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_KEYDOWN:
|
|
||||||
case WM_SYSKEYDOWN:
|
|
||||||
{
|
|
||||||
KeyDownEventPtr evt = new KeyDownEvent;
|
|
||||||
evt->code = static_cast<int>(wparam);
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_KEYUP:
|
|
||||||
case WM_SYSKEYUP:
|
|
||||||
{
|
|
||||||
KeyUpEventPtr evt = new KeyUpEvent;
|
|
||||||
evt->code = static_cast<int>(wparam);
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_CHAR:
|
|
||||||
{
|
|
||||||
KeyCharEventPtr evt = new KeyCharEvent;
|
|
||||||
evt->value = static_cast<char>(wparam);
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
|
||||||
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
|
||||||
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
|
||||||
{
|
|
||||||
MouseDownEventPtr evt = new MouseDownEvent;
|
|
||||||
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
|
||||||
|
|
||||||
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { evt->button = MouseButton::Left; }
|
|
||||||
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { evt->button = MouseButton::Right; }
|
|
||||||
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { evt->button = MouseButton::Middle; }
|
|
||||||
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
case WM_MBUTTONUP:
|
|
||||||
case WM_RBUTTONUP:
|
|
||||||
{
|
|
||||||
MouseUpEventPtr evt = new MouseUpEvent;
|
|
||||||
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
|
||||||
|
|
||||||
if (msg == WM_LBUTTONUP) { evt->button = MouseButton::Left; }
|
|
||||||
else if (msg == WM_RBUTTONUP) { evt->button = MouseButton::Right; }
|
|
||||||
else if (msg == WM_MBUTTONUP) { evt->button = MouseButton::Middle; }
|
|
||||||
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
{
|
|
||||||
MouseMoveEventPtr evt = new MouseMoveEvent;
|
|
||||||
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_MOUSEWHEEL:
|
|
||||||
{
|
|
||||||
MouseWheelEventPtr evt = new MouseWheelEvent;
|
|
||||||
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
|
||||||
evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_SIZE:
|
|
||||||
{
|
|
||||||
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"Window minimized");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// KGE_SYS_LOG(L"Window resized");
|
|
||||||
|
|
||||||
window->width_ = ((uint32_t)(short)LOWORD(lparam));
|
|
||||||
window->height_ = ((uint32_t)(short)HIWORD(lparam));
|
|
||||||
|
|
||||||
WindowResizedEventPtr evt = new WindowResizedEvent;
|
|
||||||
evt->width = window->width_;
|
|
||||||
evt->height = window->height_;
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_MOVE:
|
|
||||||
{
|
|
||||||
int x = ((int)(short)LOWORD(lparam));
|
|
||||||
int y = ((int)(short)HIWORD(lparam));
|
|
||||||
|
|
||||||
WindowMovedEventPtr evt = new WindowMovedEvent;
|
|
||||||
evt->x = x;
|
|
||||||
evt->y = y;
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_ACTIVATE:
|
|
||||||
{
|
|
||||||
bool active = (LOWORD(wparam) != WA_INACTIVE);
|
|
||||||
|
|
||||||
window->SetActive(active);
|
|
||||||
|
|
||||||
WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent;
|
|
||||||
evt->focus = active;
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_SETTEXT:
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"Window title changed");
|
|
||||||
|
|
||||||
WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent;
|
|
||||||
evt->title.assign(reinterpret_cast<const wchar_t*>(lparam));
|
|
||||||
window->PushEvent(evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_SETICON:
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"Window icon changed");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_DISPLAYCHANGE:
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"The display resolution has changed");
|
|
||||||
|
|
||||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_SETCURSOR:
|
|
||||||
{
|
|
||||||
window->UpdateCursor();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"Window is closing");
|
|
||||||
|
|
||||||
WindowClosedEventPtr evt = new WindowClosedEvent;
|
|
||||||
window->PushEvent(evt);
|
|
||||||
window->Destroy();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
|
||||||
{
|
|
||||||
KGE_SYS_LOG(L"Window was destroyed");
|
|
||||||
|
|
||||||
::PostQuitMessage(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
MONITORINFOEX GetMoniterInfoEx(HWND hwnd)
|
|
||||||
{
|
|
||||||
HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
||||||
MONITORINFOEX monitor_info;
|
|
||||||
|
|
||||||
memset(&monitor_info, 0, sizeof(MONITORINFOEX));
|
|
||||||
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
|
||||||
::GetMonitorInfoW(monitor, &monitor_info);
|
|
||||||
|
|
||||||
return monitor_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_width, uint32_t* win_height)
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
::SetRect(&rc, 0, 0, (int)width, (int)height);
|
|
||||||
::AdjustWindowRect(&rc, style, false);
|
|
||||||
|
|
||||||
*win_width = rc.right - rc.left;
|
|
||||||
*win_height = rc.bottom - rc.top;
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(NULL);
|
|
||||||
|
|
||||||
uint32_t screenw = info.rcWork.right - info.rcWork.left;
|
|
||||||
uint32_t screenh = info.rcWork.bottom - info.rcWork.top;
|
|
||||||
|
|
||||||
if (*win_width > screenw)
|
|
||||||
*win_width = screenw;
|
|
||||||
if (*win_height > screenh)
|
|
||||||
*win_height = screenh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name)
|
|
||||||
{
|
|
||||||
DEVMODE mode;
|
|
||||||
|
|
||||||
memset(&mode, 0, sizeof(mode));
|
|
||||||
mode.dmSize = sizeof(DEVMODE);
|
|
||||||
mode.dmBitsPerPel = ::GetDeviceCaps(::GetDC(0), BITSPIXEL);;
|
|
||||||
mode.dmPelsWidth = width;
|
|
||||||
mode.dmPelsHeight = height;
|
|
||||||
mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
||||||
|
|
||||||
if (::ChangeDisplaySettingsExW(device_name, &mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
|
|
||||||
KGE_ERROR(L"ChangeDisplaySettings failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreResolution(WCHAR* device_name)
|
|
||||||
{
|
|
||||||
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,23 +79,26 @@ namespace kiwano
|
||||||
typedef HWND WindowHandle;
|
typedef HWND WindowHandle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 窗口类,控制窗口标题、大小、图标等
|
* @brief 窗口类,控制窗口标题、大小、图标等
|
||||||
*/
|
*/
|
||||||
class KGE_API Window
|
class KGE_API Window
|
||||||
: public Singleton<Window>
|
: protected Noncopyable
|
||||||
{
|
{
|
||||||
friend Singleton<Window>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 获取窗口实例
|
||||||
|
*/
|
||||||
|
static Window& Instance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 初始化窗口
|
* @brief 初始化窗口
|
||||||
* @param config 窗口设置
|
* @param config 窗口设置
|
||||||
*/
|
*/
|
||||||
void Init(WindowConfig const& config);
|
virtual bool Create(WindowConfig const& config) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -116,28 +119,34 @@ namespace kiwano
|
||||||
* @brief 获取窗口宽度
|
* @brief 获取窗口宽度
|
||||||
* @return 窗口宽度
|
* @return 窗口宽度
|
||||||
*/
|
*/
|
||||||
float GetWidth() const;
|
uint32_t GetWidth() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 获取窗口高度
|
* @brief 获取窗口高度
|
||||||
* @return 窗口高度
|
* @return 窗口高度
|
||||||
*/
|
*/
|
||||||
float GetHeight() const;
|
uint32_t GetHeight() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 获取窗口句柄
|
||||||
|
*/
|
||||||
|
virtual WindowHandle GetHandle() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 设置标题
|
* @brief 设置标题
|
||||||
* @param title 标题
|
* @param title 标题
|
||||||
*/
|
*/
|
||||||
void SetTitle(String const& title);
|
virtual void SetTitle(String const& title) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 设置窗口图标
|
* @brief 设置窗口图标
|
||||||
* @param icon_resource 图标资源ID
|
* @param icon_resource 图标资源ID
|
||||||
*/
|
*/
|
||||||
void SetIcon(uint32_t icon_resource);
|
virtual void SetIcon(uint32_t icon_resource) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -145,7 +154,7 @@ namespace kiwano
|
||||||
* @param width 窗口宽度
|
* @param width 窗口宽度
|
||||||
* @param height 窗口高度
|
* @param height 窗口高度
|
||||||
*/
|
*/
|
||||||
void Resize(int width, int height);
|
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -154,14 +163,14 @@ namespace kiwano
|
||||||
* @param width 窗口宽度
|
* @param width 窗口宽度
|
||||||
* @param height 窗口高度
|
* @param height 窗口高度
|
||||||
*/
|
*/
|
||||||
void SetFullscreen(bool fullscreen, int width, int height);
|
virtual void SetFullscreen(bool fullscreen) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 设置鼠标指针类型
|
* @brief 设置鼠标指针类型
|
||||||
* @param cursor 鼠标指针类型
|
* @param cursor 鼠标指针类型
|
||||||
*/
|
*/
|
||||||
void SetCursor(CursorType cursor);
|
virtual void SetCursor(CursorType cursor) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -170,49 +179,48 @@ namespace kiwano
|
||||||
*/
|
*/
|
||||||
EventPtr PollEvent();
|
EventPtr PollEvent();
|
||||||
|
|
||||||
/**
|
|
||||||
* \~chinese
|
|
||||||
* @brief »ñÈ¡´°¿Ú¾ä±ú
|
|
||||||
*/
|
|
||||||
WindowHandle GetHandle() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 是否需要关闭
|
* @brief 是否需要关闭
|
||||||
*/
|
*/
|
||||||
bool ShouldClose();
|
virtual bool ShouldClose() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
* @brief 销毁窗口
|
* @brief 销毁窗口
|
||||||
*/
|
*/
|
||||||
void Destroy();
|
virtual void Destroy();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Window();
|
Window();
|
||||||
|
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
void PushEvent(EventPtr evt);
|
void PushEvent(EventPtr evt);
|
||||||
|
|
||||||
#if defined(KGE_WIN32)
|
void SetInternalSize(uint32_t width, uint32_t height);
|
||||||
DWORD GetWindowStyle() const;
|
|
||||||
|
|
||||||
void UpdateCursor();
|
void SetInternalTitle(String const& title);
|
||||||
|
|
||||||
void SetActive(bool actived);
|
virtual void PumpEvents() = 0;
|
||||||
|
|
||||||
static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool resizable_;
|
bool should_close_;
|
||||||
bool is_fullscreen_;
|
|
||||||
WindowHandle handle_;
|
|
||||||
uint32_t width_;
|
uint32_t width_;
|
||||||
uint32_t height_;
|
uint32_t height_;
|
||||||
wchar_t* device_name_;
|
String title_;
|
||||||
CursorType mouse_cursor_;
|
|
||||||
std::queue<EventPtr> event_queue_;
|
std::queue<EventPtr> event_queue_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void Window::SetInternalSize(uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Window::SetInternalTitle(String const& title)
|
||||||
|
{
|
||||||
|
title_ = title;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,632 @@
|
||||||
|
// Copyright (c) 2016-2020 Kiwano - Nomango
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
#include <kiwano/platform/Window.h>
|
||||||
|
|
||||||
|
#if defined(KGE_WIN32)
|
||||||
|
|
||||||
|
#include <kiwano/platform/Application.h>
|
||||||
|
#include <kiwano/core/event/MouseEvent.h>
|
||||||
|
#include <kiwano/core/event/KeyEvent.h>
|
||||||
|
#include <kiwano/core/event/WindowEvent.h>
|
||||||
|
#include <kiwano/core/Logger.h>
|
||||||
|
|
||||||
|
#include <imm.h> // ImmAssociateContext
|
||||||
|
#pragma comment(lib, "imm32.lib")
|
||||||
|
|
||||||
|
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
||||||
|
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
|
||||||
|
#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
|
||||||
|
#define KGE_WND_CLASS_NAME L"KiwanoAppWnd"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
namespace win32
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
MONITORINFOEX GetMoniterInfoEx(HWND hwnd)
|
||||||
|
{
|
||||||
|
HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
MONITORINFOEX monitor_info;
|
||||||
|
|
||||||
|
memset(&monitor_info, 0, sizeof(MONITORINFOEX));
|
||||||
|
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
||||||
|
::GetMonitorInfoW(monitor, &monitor_info);
|
||||||
|
|
||||||
|
return monitor_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_width, uint32_t* win_height)
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
::SetRect(&rc, 0, 0, (int)width, (int)height);
|
||||||
|
::AdjustWindowRect(&rc, style, false);
|
||||||
|
|
||||||
|
*win_width = rc.right - rc.left;
|
||||||
|
*win_height = rc.bottom - rc.top;
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(NULL);
|
||||||
|
|
||||||
|
uint32_t screenw = info.rcWork.right - info.rcWork.left;
|
||||||
|
uint32_t screenh = info.rcWork.bottom - info.rcWork.top;
|
||||||
|
|
||||||
|
if (*win_width > screenw)
|
||||||
|
*win_width = screenw;
|
||||||
|
if (*win_height > screenh)
|
||||||
|
*win_height = screenh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeFullScreenResolution(uint32_t width, uint32_t height, WCHAR* device_name)
|
||||||
|
{
|
||||||
|
DEVMODE mode;
|
||||||
|
|
||||||
|
memset(&mode, 0, sizeof(mode));
|
||||||
|
mode.dmSize = sizeof(DEVMODE);
|
||||||
|
mode.dmBitsPerPel = ::GetDeviceCaps(::GetDC(0), BITSPIXEL);;
|
||||||
|
mode.dmPelsWidth = width;
|
||||||
|
mode.dmPelsHeight = height;
|
||||||
|
mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||||
|
|
||||||
|
if (::ChangeDisplaySettingsExW(device_name, &mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||||
|
KGE_ERROR(L"ChangeDisplaySettings failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreResolution(WCHAR* device_name)
|
||||||
|
{
|
||||||
|
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KGE_API WindowImpl
|
||||||
|
: public kiwano::Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowImpl();
|
||||||
|
|
||||||
|
~WindowImpl();
|
||||||
|
|
||||||
|
bool Create(WindowConfig const& config) override;
|
||||||
|
|
||||||
|
WindowHandle GetHandle() const override;
|
||||||
|
|
||||||
|
void SetTitle(String const& title) override;
|
||||||
|
|
||||||
|
void SetIcon(uint32_t icon_resource) override;
|
||||||
|
|
||||||
|
void Resize(uint32_t width, uint32_t height) override;
|
||||||
|
|
||||||
|
void SetFullscreen(bool fullscreen) override;
|
||||||
|
|
||||||
|
void SetCursor(CursorType cursor) override;
|
||||||
|
|
||||||
|
bool ShouldClose() override;
|
||||||
|
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PumpEvents() override;
|
||||||
|
|
||||||
|
DWORD GetWindowStyle() const;
|
||||||
|
|
||||||
|
void UpdateCursor();
|
||||||
|
|
||||||
|
void SetActive(bool actived);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool resizable_;
|
||||||
|
bool is_fullscreen_;
|
||||||
|
wchar_t* device_name_;
|
||||||
|
WindowHandle handle_;
|
||||||
|
CursorType mouse_cursor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowImpl::WindowImpl()
|
||||||
|
: handle_(nullptr)
|
||||||
|
, device_name_(nullptr)
|
||||||
|
, is_fullscreen_(false)
|
||||||
|
, resizable_(false)
|
||||||
|
, mouse_cursor_(CursorType::Arrow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowImpl::~WindowImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowImpl::Create(WindowConfig const& config)
|
||||||
|
{
|
||||||
|
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
||||||
|
WNDCLASSEX wcex = { 0 };
|
||||||
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wcex.lpszClassName = KGE_WND_CLASS_NAME;
|
||||||
|
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
|
||||||
|
wcex.lpfnWndProc = WindowImpl::WndProc;
|
||||||
|
wcex.hIcon = nullptr;
|
||||||
|
wcex.cbClsExtra = 0;
|
||||||
|
wcex.cbWndExtra = sizeof(LONG_PTR);
|
||||||
|
wcex.hInstance = hinst;
|
||||||
|
wcex.hbrBackground = (HBRUSH)(::GetStockObject(BLACK_BRUSH));
|
||||||
|
wcex.lpszMenuName = nullptr;
|
||||||
|
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
|
||||||
|
|
||||||
|
if (config.icon)
|
||||||
|
{
|
||||||
|
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0,
|
||||||
|
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
::RegisterClassExW(&wcex);
|
||||||
|
|
||||||
|
// Get the nearest monitor to this window
|
||||||
|
HMONITOR monitor = ::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
|
||||||
|
// Get the target monitor info
|
||||||
|
MONITORINFOEX monitor_info_ex;
|
||||||
|
memset(&monitor_info_ex, 0, sizeof(MONITORINFOEX));
|
||||||
|
monitor_info_ex.cbSize = sizeof(MONITORINFOEX);
|
||||||
|
::GetMonitorInfoW(monitor, &monitor_info_ex);
|
||||||
|
|
||||||
|
// Save the device name
|
||||||
|
int len = lstrlenW(monitor_info_ex.szDevice);
|
||||||
|
device_name_ = new wchar_t[len + 1];
|
||||||
|
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
||||||
|
|
||||||
|
uint32_t width = config.width;
|
||||||
|
uint32_t height = config.height;
|
||||||
|
int left = -1;
|
||||||
|
int top = -1;
|
||||||
|
|
||||||
|
resizable_ = config.resizable;
|
||||||
|
is_fullscreen_ = config.fullscreen;
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
top = monitor_info_ex.rcMonitor.top;
|
||||||
|
left = monitor_info_ex.rcMonitor.left;
|
||||||
|
|
||||||
|
if (width > static_cast<uint32_t>(monitor_info_ex.rcWork.right - left))
|
||||||
|
width = static_cast<uint32_t>(monitor_info_ex.rcWork.right - left);
|
||||||
|
|
||||||
|
if (height > static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top))
|
||||||
|
height = static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left;
|
||||||
|
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
|
||||||
|
|
||||||
|
uint32_t win_width, win_height;
|
||||||
|
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
|
||||||
|
|
||||||
|
left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
|
||||||
|
top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;
|
||||||
|
width = win_width;
|
||||||
|
height = win_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_ = ::CreateWindowExW(
|
||||||
|
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
||||||
|
KGE_WND_CLASS_NAME,
|
||||||
|
config.title.c_str(),
|
||||||
|
GetWindowStyle(),
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
hinst,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
if (handle_ == nullptr)
|
||||||
|
{
|
||||||
|
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
|
||||||
|
KGE_ERROR(L"Failed with HRESULT of %08X", HRESULT_FROM_WIN32(GetLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetInternalSize(width, height);
|
||||||
|
|
||||||
|
// disable imm
|
||||||
|
::ImmAssociateContext(handle_, nullptr);
|
||||||
|
|
||||||
|
// use Application instance in message loop
|
||||||
|
::SetWindowLongPtr(handle_, GWLP_USERDATA, LONG_PTR(this));
|
||||||
|
|
||||||
|
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||||
|
::UpdateWindow(handle_);
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
ChangeFullScreenResolution(width, height, device_name_);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowHandle WindowImpl::GetHandle() const
|
||||||
|
{
|
||||||
|
return handle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::PumpEvents()
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessageW(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::SetTitle(String const& title)
|
||||||
|
{
|
||||||
|
if (handle_)
|
||||||
|
::SetWindowTextW(handle_, title.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::SetIcon(uint32_t icon_resource)
|
||||||
|
{
|
||||||
|
if (handle_)
|
||||||
|
{
|
||||||
|
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||||
|
HICON icon = (HICON)::LoadImageW(
|
||||||
|
hinstance,
|
||||||
|
MAKEINTRESOURCE(icon_resource),
|
||||||
|
IMAGE_ICON,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||||
|
);
|
||||||
|
|
||||||
|
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
||||||
|
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::Resize(uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
if (handle_ && !is_fullscreen_)
|
||||||
|
{
|
||||||
|
RECT rc = { 0, 0, LONG(width), LONG(height) };
|
||||||
|
::AdjustWindowRect(&rc, GetWindowStyle(), false);
|
||||||
|
|
||||||
|
width = rc.right - rc.left;
|
||||||
|
height = rc.bottom - rc.top;
|
||||||
|
::SetWindowPos(handle_, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::SetFullscreen(bool fullscreen)
|
||||||
|
{
|
||||||
|
if (is_fullscreen_ != fullscreen)
|
||||||
|
{
|
||||||
|
is_fullscreen_ = fullscreen;
|
||||||
|
|
||||||
|
uint32_t width = GetWidth();
|
||||||
|
uint32_t height = GetHeight();
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
// move window to (0, 0) before display switch
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
ChangeFullScreenResolution(width, height, device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
|
||||||
|
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
|
||||||
|
uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left);
|
||||||
|
uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top);
|
||||||
|
|
||||||
|
int left = screenw > width ? ((screenw - width) / 2) : 0;
|
||||||
|
int top = screenh > height ? ((screenh - height) / 2) : 0;
|
||||||
|
|
||||||
|
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
||||||
|
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, width, height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::SetCursor(CursorType cursor)
|
||||||
|
{
|
||||||
|
mouse_cursor_ = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowImpl::ShouldClose()
|
||||||
|
{
|
||||||
|
return handle_ == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::Destroy()
|
||||||
|
{
|
||||||
|
if (is_fullscreen_)
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
if (device_name_)
|
||||||
|
{
|
||||||
|
delete[] device_name_;
|
||||||
|
device_name_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle_)
|
||||||
|
{
|
||||||
|
::DestroyWindow(handle_);
|
||||||
|
handle_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WindowImpl::GetWindowStyle() const
|
||||||
|
{
|
||||||
|
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::UpdateCursor()
|
||||||
|
{
|
||||||
|
LPTSTR win32_cursor = IDC_ARROW;
|
||||||
|
switch (mouse_cursor_)
|
||||||
|
{
|
||||||
|
case CursorType::Arrow: win32_cursor = IDC_ARROW; break;
|
||||||
|
case CursorType::TextInput: win32_cursor = IDC_IBEAM; break;
|
||||||
|
case CursorType::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||||
|
case CursorType::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
||||||
|
case CursorType::SizeNS: win32_cursor = IDC_SIZENS; break;
|
||||||
|
case CursorType::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||||
|
case CursorType::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||||
|
case CursorType::Hand: win32_cursor = IDC_HAND; break;
|
||||||
|
}
|
||||||
|
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowImpl::SetActive(bool actived)
|
||||||
|
{
|
||||||
|
if (!handle_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
if (actived)
|
||||||
|
{
|
||||||
|
ChangeFullScreenResolution(GetWidth(), GetHeight(), device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, GetWidth(), GetHeight(), SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
|
::ShowWindow(handle_, SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
WindowImpl* window = reinterpret_cast<WindowImpl*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
|
||||||
|
if (window == nullptr)
|
||||||
|
{
|
||||||
|
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
{
|
||||||
|
KeyDownEventPtr evt = new KeyDownEvent;
|
||||||
|
evt->code = static_cast<int>(wparam);
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
{
|
||||||
|
KeyUpEventPtr evt = new KeyUpEvent;
|
||||||
|
evt->code = static_cast<int>(wparam);
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CHAR:
|
||||||
|
{
|
||||||
|
KeyCharEventPtr evt = new KeyCharEvent;
|
||||||
|
evt->value = static_cast<char>(wparam);
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
||||||
|
{
|
||||||
|
MouseDownEventPtr evt = new MouseDownEvent;
|
||||||
|
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
||||||
|
|
||||||
|
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { evt->button = MouseButton::Left; }
|
||||||
|
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { evt->button = MouseButton::Right; }
|
||||||
|
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { evt->button = MouseButton::Middle; }
|
||||||
|
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
{
|
||||||
|
MouseUpEventPtr evt = new MouseUpEvent;
|
||||||
|
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
||||||
|
|
||||||
|
if (msg == WM_LBUTTONUP) { evt->button = MouseButton::Left; }
|
||||||
|
else if (msg == WM_RBUTTONUP) { evt->button = MouseButton::Right; }
|
||||||
|
else if (msg == WM_MBUTTONUP) { evt->button = MouseButton::Middle; }
|
||||||
|
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
{
|
||||||
|
MouseMoveEventPtr evt = new MouseMoveEvent;
|
||||||
|
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
MouseWheelEventPtr evt = new MouseWheelEvent;
|
||||||
|
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
|
||||||
|
evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"Window minimized");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// KGE_SYS_LOG(L"WindowImpl resized");
|
||||||
|
|
||||||
|
window->SetInternalSize(((uint32_t)(short)LOWORD(lparam)), ((uint32_t)(short)HIWORD(lparam)));
|
||||||
|
|
||||||
|
WindowResizedEventPtr evt = new WindowResizedEvent;
|
||||||
|
evt->width = window->GetWidth();
|
||||||
|
evt->height = window->GetHeight();
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOVE:
|
||||||
|
{
|
||||||
|
int x = ((int)(short)LOWORD(lparam));
|
||||||
|
int y = ((int)(short)HIWORD(lparam));
|
||||||
|
|
||||||
|
WindowMovedEventPtr evt = new WindowMovedEvent;
|
||||||
|
evt->x = x;
|
||||||
|
evt->y = y;
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_ACTIVATE:
|
||||||
|
{
|
||||||
|
bool active = (LOWORD(wparam) != WA_INACTIVE);
|
||||||
|
|
||||||
|
window->SetActive(active);
|
||||||
|
|
||||||
|
WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent;
|
||||||
|
evt->focus = active;
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SETTEXT:
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"Window title changed");
|
||||||
|
|
||||||
|
String title = String::cstr(reinterpret_cast<LPCWSTR>(lparam));
|
||||||
|
window->SetInternalTitle(title);
|
||||||
|
|
||||||
|
WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent;
|
||||||
|
evt->title = title;
|
||||||
|
window->PushEvent(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SETICON:
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"Window icon changed");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"The display resolution has changed");
|
||||||
|
|
||||||
|
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
{
|
||||||
|
window->UpdateCursor();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"Window is closing");
|
||||||
|
|
||||||
|
WindowClosedEventPtr evt = new WindowClosedEvent;
|
||||||
|
window->PushEvent(evt);
|
||||||
|
window->Destroy();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
{
|
||||||
|
KGE_SYS_LOG(L"Window was destroyed");
|
||||||
|
|
||||||
|
::PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace win32
|
||||||
|
} // namespace kiwano
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
Window& Window::Instance()
|
||||||
|
{
|
||||||
|
static win32::WindowImpl instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -90,17 +90,17 @@ namespace kiwano
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Renderer::instance().CreateSolidBrush(*this, color);
|
Renderer::Instance().CreateSolidBrush(*this, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Brush::SetStyle(LinearGradientStyle const& style)
|
void Brush::SetStyle(LinearGradientStyle const& style)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateLinearGradientBrush(*this, style);
|
Renderer::Instance().CreateLinearGradientBrush(*this, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Brush::SetStyle(RadialGradientStyle const& style)
|
void Brush::SetStyle(RadialGradientStyle const& style)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateRadialGradientBrush(*this, style);
|
Renderer::Instance().CreateRadialGradientBrush(*this, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
|
void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateFontCollection(*this, files);
|
Renderer::Instance().CreateFontCollection(*this, files);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error&)
|
catch (std::runtime_error&)
|
||||||
{
|
{
|
||||||
|
|
@ -54,7 +54,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateFontCollection(*this, resources);
|
Renderer::Instance().CreateFontCollection(*this, resources);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error&)
|
catch (std::runtime_error&)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -118,35 +118,35 @@ namespace kiwano
|
||||||
Geometry Geometry::CreateLine(Point const& begin, Point const& end)
|
Geometry Geometry::CreateLine(Point const& begin, Point const& end)
|
||||||
{
|
{
|
||||||
Geometry output;
|
Geometry output;
|
||||||
Renderer::instance().CreateLineGeometry(output, begin, end);
|
Renderer::Instance().CreateLineGeometry(output, begin, end);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry Geometry::CreateRect(Rect const& rect)
|
Geometry Geometry::CreateRect(Rect const& rect)
|
||||||
{
|
{
|
||||||
Geometry output;
|
Geometry output;
|
||||||
Renderer::instance().CreateRectGeometry(output, rect);
|
Renderer::Instance().CreateRectGeometry(output, rect);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry Geometry::CreateRoundedRect(Rect const& rect, Vec2 const& radius)
|
Geometry Geometry::CreateRoundedRect(Rect const& rect, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
Geometry output;
|
Geometry output;
|
||||||
Renderer::instance().CreateRoundedRectGeometry(output, rect, radius);
|
Renderer::Instance().CreateRoundedRectGeometry(output, rect, radius);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry Geometry::CreateCircle(Point const& center, float radius)
|
Geometry Geometry::CreateCircle(Point const& center, float radius)
|
||||||
{
|
{
|
||||||
Geometry output;
|
Geometry output;
|
||||||
Renderer::instance().CreateEllipseGeometry(output, center, Vec2{ radius, radius });
|
Renderer::Instance().CreateEllipseGeometry(output, center, Vec2{ radius, radius });
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry Geometry::CreateEllipse(Point const& center, Vec2 const& radius)
|
Geometry Geometry::CreateEllipse(Point const& center, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
Geometry output;
|
Geometry output;
|
||||||
Renderer::instance().CreateEllipseGeometry(output, center, radius);
|
Renderer::Instance().CreateEllipseGeometry(output, center, radius);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace kiwano
|
||||||
if (!IsOpened())
|
if (!IsOpened())
|
||||||
{
|
{
|
||||||
path_geo_.reset();
|
path_geo_.reset();
|
||||||
Renderer::instance().CreateGeometrySink(*this);
|
Renderer::Instance().CreateGeometrySink(*this);
|
||||||
|
|
||||||
win32::ThrowIfFailed(path_geo_->Open(&sink_));
|
win32::ThrowIfFailed(path_geo_->Open(&sink_));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool GifImage::Load(String const& file_path)
|
bool GifImage::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateGifImage(*this, file_path);
|
Renderer::Instance().CreateGifImage(*this, file_path);
|
||||||
|
|
||||||
if (IsValid())
|
if (IsValid())
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +49,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool GifImage::Load(Resource const& res)
|
bool GifImage::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateGifImage(*this, res);
|
Renderer::Instance().CreateGifImage(*this, res);
|
||||||
|
|
||||||
if (IsValid())
|
if (IsValid())
|
||||||
{
|
{
|
||||||
|
|
@ -71,7 +71,7 @@ namespace kiwano
|
||||||
GifImage::Frame GifImage::GetFrame(uint32_t index)
|
GifImage::Frame GifImage::GetFrame(uint32_t index)
|
||||||
{
|
{
|
||||||
Frame frame;
|
Frame frame;
|
||||||
Renderer::instance().CreateGifImageFrame(frame, *this, index);
|
Renderer::Instance().CreateGifImageFrame(frame, *this, index);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,6 @@
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
RenderConfig::RenderConfig(Color clear_color, bool vsync)
|
|
||||||
: clear_color(clear_color)
|
|
||||||
, vsync(vsync)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
: target_window_(nullptr)
|
: target_window_(nullptr)
|
||||||
|
|
@ -43,20 +38,14 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Init(RenderConfig const& config)
|
|
||||||
{
|
|
||||||
SetClearColor(config.clear_color);
|
|
||||||
SetVSyncEnabled(config.vsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetupComponent()
|
void Renderer::SetupComponent()
|
||||||
{
|
{
|
||||||
KGE_SYS_LOG(L"Creating device resources");
|
KGE_SYS_LOG(L"Creating device resources");
|
||||||
|
|
||||||
win32::ThrowIfFailed(::CoInitialize(nullptr));
|
win32::ThrowIfFailed(::CoInitialize(nullptr));
|
||||||
|
|
||||||
target_window_ = Window::instance().GetHandle();
|
target_window_ = Window::Instance().GetHandle();
|
||||||
output_size_ = Window::instance().GetSize();
|
output_size_ = Window::Instance().GetSize();
|
||||||
|
|
||||||
d2d_res_ = nullptr;
|
d2d_res_ = nullptr;
|
||||||
d3d_res_ = nullptr;
|
d3d_res_ = nullptr;
|
||||||
|
|
@ -210,7 +199,7 @@ namespace kiwano
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_WARN(L"Texture file '%s' not found!", file_path.c_str());
|
KGE_WARN(L"Texture file '%s' not found!", file_path.c_str());
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
@ -218,7 +207,7 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
|
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||||
|
|
@ -328,7 +317,7 @@ namespace kiwano
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str());
|
KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str());
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
@ -336,7 +325,7 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
|
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||||
|
|
@ -560,13 +549,13 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
for (auto& file_path : full_paths)
|
for (auto& file_path : full_paths)
|
||||||
{
|
{
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_WARN(L"Font file '%s' not found!", file_path.c_str());
|
KGE_WARN(L"Font file '%s' not found!", file_path.c_str());
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_path = FileSystem::instance().GetFullPathForFile(file_path);
|
file_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,21 +52,6 @@ namespace kiwano
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* \~chinese
|
|
||||||
* @brief 斡횡<EFBFBD>零
|
|
||||||
*/
|
|
||||||
struct RenderConfig
|
|
||||||
{
|
|
||||||
Color clear_color; ///< 헌팁奈<ED8C81>
|
|
||||||
bool vsync; ///< 뉩殮谿꼍
|
|
||||||
|
|
||||||
RenderConfig(
|
|
||||||
Color clear_color = Color::Black,
|
|
||||||
bool vsync = true
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \~chinese
|
* \~chinese
|
||||||
|
|
@ -294,8 +279,6 @@ namespace kiwano
|
||||||
ID3DDeviceResources* GetD3DDeviceResources();
|
ID3DDeviceResources* GetD3DDeviceResources();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(RenderConfig const& config);
|
|
||||||
|
|
||||||
void SetupComponent() override;
|
void SetupComponent() override;
|
||||||
|
|
||||||
void DestroyComponent() override;
|
void DestroyComponent() override;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace kiwano
|
||||||
StrokeStyle StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, const float* dash_array, size_t dash_size, float dash_offset)
|
StrokeStyle StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, const float* dash_array, size_t dash_size, float dash_offset)
|
||||||
{
|
{
|
||||||
StrokeStyle stroke_style;
|
StrokeStyle stroke_style;
|
||||||
Renderer::instance().CreateStrokeStyle(stroke_style, cap, line_join, dash_array, dash_size, dash_offset);
|
Renderer::Instance().CreateStrokeStyle(stroke_style, cap, line_join, dash_array, dash_size, dash_offset);
|
||||||
return stroke_style;
|
return stroke_style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@ namespace kiwano
|
||||||
|
|
||||||
if (!text_format_ || (dirty_flag_ & DirtyFlag::DirtyFormat))
|
if (!text_format_ || (dirty_flag_ & DirtyFlag::DirtyFormat))
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTextFormat(*this);
|
Renderer::Instance().CreateTextFormat(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirty_flag_ & DirtyFlag::DirtyLayout)
|
if (dirty_flag_ & DirtyFlag::DirtyLayout)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTextLayout(*this);
|
Renderer::Instance().CreateTextLayout(*this);
|
||||||
|
|
||||||
if (text_layout_)
|
if (text_layout_)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,13 @@ namespace kiwano
|
||||||
|
|
||||||
bool Texture::Load(String const& file_path)
|
bool Texture::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTexture(*this, file_path);
|
Renderer::Instance().CreateTexture(*this, file_path);
|
||||||
return IsValid();
|
return IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::Load(Resource const& res)
|
bool Texture::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
Renderer::instance().CreateTexture(*this, res);
|
Renderer::Instance().CreateTexture(*this, res);
|
||||||
return IsValid();
|
return IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace kiwano
|
||||||
|
|
||||||
bool ResourceCache::LoadFromJsonFile(String const& file_path)
|
bool ResourceCache::LoadFromJsonFile(String const& file_path)
|
||||||
{
|
{
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_ERROR(L"ResourceCache::LoadFromJsonFile failed: File not found.");
|
KGE_ERROR(L"ResourceCache::LoadFromJsonFile failed: File not found.");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -67,7 +67,7 @@ namespace kiwano
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
|
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
ifs.open(full_path.c_str());
|
ifs.open(full_path.c_str());
|
||||||
ifs >> json_data;
|
ifs >> json_data;
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
|
@ -115,13 +115,13 @@ namespace kiwano
|
||||||
|
|
||||||
bool ResourceCache::LoadFromXmlFile(String const& file_path)
|
bool ResourceCache::LoadFromXmlFile(String const& file_path)
|
||||||
{
|
{
|
||||||
if (!FileSystem::instance().IsFileExists(file_path))
|
if (!FileSystem::Instance().IsFileExists(file_path))
|
||||||
{
|
{
|
||||||
KGE_ERROR(L"ResourceCache::LoadFromXmlFile failed: File not found.");
|
KGE_ERROR(L"ResourceCache::LoadFromXmlFile failed: File not found.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
|
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
|
||||||
|
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(full_path.c_str(), pugi::parse_default, pugi::encoding_auto);
|
pugi::xml_parse_result result = doc.load_file(full_path.c_str(), pugi::parse_default, pugi::encoding_auto);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue