Add ResolutionMode
This commit is contained in:
parent
d9e67fd737
commit
b2a7d89d61
|
|
@ -21,7 +21,8 @@
|
|||
#include "Window.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#define WINDOW_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
||||
#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"
|
||||
|
||||
|
|
@ -44,7 +45,8 @@ namespace kiwano
|
|||
, height_(0)
|
||||
, device_name_(nullptr)
|
||||
, is_fullscreen_(false)
|
||||
, mouse_cursor_(MouseCursor(-1))
|
||||
, resizable_(false)
|
||||
, mouse_cursor_(MouseCursor::Arrow)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +68,7 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool fullscreen, WNDPROC proc)
|
||||
void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc)
|
||||
{
|
||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
||||
WNDCLASSEX wcex = { 0 };
|
||||
|
|
@ -80,7 +82,7 @@ namespace kiwano
|
|||
wcex.hInstance = hinst;
|
||||
wcex.hbrBackground = nullptr;
|
||||
wcex.lpszMenuName = nullptr;
|
||||
wcex.hCursor = nullptr;
|
||||
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
|
||||
|
||||
if (icon)
|
||||
{
|
||||
|
|
@ -106,6 +108,7 @@ namespace kiwano
|
|||
Int32 left = -1;
|
||||
Int32 top = -1;
|
||||
|
||||
resizable_ = resizable;
|
||||
is_fullscreen_ = fullscreen;
|
||||
|
||||
if (is_fullscreen_)
|
||||
|
|
@ -165,8 +168,6 @@ namespace kiwano
|
|||
GetClientRect(handle_, &rc);
|
||||
width_ = rc.right - rc.left;
|
||||
height_ = rc.bottom - rc.top;
|
||||
|
||||
SetMouseCursor(MouseCursor::Arrow);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,24 +297,7 @@ namespace kiwano
|
|||
|
||||
void Window::SetMouseCursor(MouseCursor cursor)
|
||||
{
|
||||
if (mouse_cursor_ != cursor)
|
||||
{
|
||||
mouse_cursor_ = cursor;
|
||||
|
||||
LPTSTR win32_cursor = IDC_ARROW;
|
||||
switch (cursor)
|
||||
{
|
||||
case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
||||
case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
|
||||
}
|
||||
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
||||
}
|
||||
mouse_cursor_ = cursor;
|
||||
}
|
||||
|
||||
HWND Window::GetHandle() const
|
||||
|
|
@ -323,7 +307,7 @@ namespace kiwano
|
|||
|
||||
DWORD Window::GetWindowStyle() const
|
||||
{
|
||||
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE);
|
||||
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));
|
||||
}
|
||||
|
||||
void Window::UpdateWindowRect()
|
||||
|
|
@ -338,6 +322,23 @@ namespace kiwano
|
|||
height_ = rc.bottom - rc.top;
|
||||
}
|
||||
|
||||
void Window::UpdateCursor()
|
||||
{
|
||||
LPTSTR win32_cursor = IDC_ARROW;
|
||||
switch (mouse_cursor_)
|
||||
{
|
||||
case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
||||
case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
|
||||
}
|
||||
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
||||
}
|
||||
|
||||
void Window::SetActive(bool actived)
|
||||
{
|
||||
if (!handle_)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace kiwano
|
|||
Int32 width,
|
||||
Int32 height,
|
||||
UInt32 icon,
|
||||
bool resizable,
|
||||
bool fullscreen,
|
||||
WNDPROC proc
|
||||
);
|
||||
|
|
@ -77,6 +78,8 @@ namespace kiwano
|
|||
|
||||
void UpdateWindowRect();
|
||||
|
||||
void UpdateCursor();
|
||||
|
||||
void SetActive(bool actived);
|
||||
|
||||
protected:
|
||||
|
|
@ -85,8 +88,9 @@ namespace kiwano
|
|||
~Window();
|
||||
|
||||
private:
|
||||
HWND handle_;
|
||||
bool resizable_;
|
||||
bool is_fullscreen_;
|
||||
HWND handle_;
|
||||
Int32 width_;
|
||||
Int32 height_;
|
||||
WCHAR* device_name_;
|
||||
|
|
|
|||
|
|
@ -51,4 +51,13 @@ namespace kiwano
|
|||
GrayScale, // 灰度抗锯齿
|
||||
None // 不启用抗锯齿
|
||||
};
|
||||
|
||||
// 分辨率模式
|
||||
enum class ResolutionMode
|
||||
{
|
||||
Fixed, /* 固定 */
|
||||
Center, /* 居中 */
|
||||
Stretch, /* 拉伸 */
|
||||
Adaptive, /* 宽高自适应 */
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,13 +43,14 @@ namespace kiwano
|
|||
Queue<FunctionToPerform> functions_to_perform_;
|
||||
}
|
||||
|
||||
Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool fullscreen, bool debug)
|
||||
Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool resizable, bool fullscreen, bool debug)
|
||||
: title(title)
|
||||
, width(width)
|
||||
, height(height)
|
||||
, icon(icon)
|
||||
, clear_color(clear_color)
|
||||
, vsync(vsync)
|
||||
, resizable(resizable)
|
||||
, fullscreen(fullscreen)
|
||||
, debug(debug)
|
||||
{}
|
||||
|
|
@ -85,6 +86,7 @@ namespace kiwano
|
|||
options.width,
|
||||
options.height,
|
||||
options.icon,
|
||||
options.resizable,
|
||||
options.fullscreen,
|
||||
Application::WndProc
|
||||
);
|
||||
|
|
@ -380,11 +382,11 @@ namespace kiwano
|
|||
{
|
||||
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
|
||||
{
|
||||
KGE_LOG(L"Window minimized");
|
||||
// KGE_LOG(L"Window minimized");
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_LOG(L"Window resized");
|
||||
// KGE_LOG(L"Window resized");
|
||||
|
||||
Window::GetInstance()->UpdateWindowRect();
|
||||
|
||||
|
|
@ -422,7 +424,7 @@ namespace kiwano
|
|||
|
||||
case WM_SETTEXT:
|
||||
{
|
||||
KGE_LOG(L"Window title changed");
|
||||
// KGE_LOG(L"Window title changed");
|
||||
|
||||
Event evt(Event::WindowTitleChanged);
|
||||
evt.win.title = reinterpret_cast<const WChar*>(lparam);
|
||||
|
|
@ -432,21 +434,27 @@ namespace kiwano
|
|||
|
||||
case WM_SETICON:
|
||||
{
|
||||
KGE_LOG(L"Window icon changed");
|
||||
// KGE_LOG(L"Window icon changed");
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
KGE_LOG(L"The display resolution has changed");
|
||||
// KGE_LOG(L"The display resolution has changed");
|
||||
|
||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
{
|
||||
Window::GetInstance()->UpdateCursor();
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
{
|
||||
KGE_LOG(L"Window is closing");
|
||||
// KGE_LOG(L"Window is closing");
|
||||
|
||||
if (!app->OnClosing())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ namespace kiwano
|
|||
UInt32 icon; // 图标资源 ID
|
||||
Color clear_color; // 清屏颜色
|
||||
bool vsync; // 垂直同步
|
||||
bool resizable; // 窗口大小可拉伸
|
||||
bool fullscreen; // 全屏模式
|
||||
bool debug; // 调试模式
|
||||
|
||||
|
|
@ -45,6 +46,7 @@ namespace kiwano
|
|||
UInt32 icon = 0,
|
||||
Color clear_color = Color::Black,
|
||||
bool vsync = true,
|
||||
bool resizable = false,
|
||||
bool fullscreen = false,
|
||||
bool debug = false
|
||||
);
|
||||
|
|
|
|||
|
|
@ -535,6 +535,11 @@ namespace kiwano
|
|||
return opacity_;
|
||||
}
|
||||
|
||||
Matrix3x2 RenderTarget::GetGlobalTransform() const
|
||||
{
|
||||
return global_matrix_;
|
||||
}
|
||||
|
||||
void RenderTarget::SetTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
|
@ -545,12 +550,18 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
||||
Matrix3x2 result = matrix * global_matrix_;
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RenderTarget::SetGlobalTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
global_matrix_ = matrix;
|
||||
}
|
||||
|
||||
void RenderTarget::SetOpacity(Float32 opacity)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
|
@ -628,7 +639,7 @@ namespace kiwano
|
|||
bool RenderTarget::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform)
|
||||
{
|
||||
return Rect{ Point{}, reinterpret_cast<const Size&>(render_target_->GetSize()) }.Intersects(
|
||||
transform.Transform(bounds)
|
||||
Matrix3x2(transform * global_matrix_).Transform(bounds)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ namespace kiwano
|
|||
|
||||
Float32 GetOpacity() const;
|
||||
|
||||
Matrix3x2 GetGlobalTransform() const;
|
||||
|
||||
void SetOpacity(
|
||||
Float32 opacity
|
||||
);
|
||||
|
|
@ -148,6 +150,10 @@ namespace kiwano
|
|||
const Matrix3x2& matrix
|
||||
);
|
||||
|
||||
void SetGlobalTransform(
|
||||
const Matrix3x2& matrix
|
||||
);
|
||||
|
||||
// ÉèÖÿ¹¾â³Ýģʽ
|
||||
void SetAntialiasMode(
|
||||
bool enabled
|
||||
|
|
@ -202,6 +208,7 @@ namespace kiwano
|
|||
ComPtr<ID2D1SolidColorBrush> default_brush_;
|
||||
ComPtr<ID2D1Brush> current_brush_;
|
||||
ComPtr<ID2DDeviceResources> device_resources_;
|
||||
Matrix3x2 global_matrix_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace kiwano
|
|||
: hwnd_(nullptr)
|
||||
, vsync_(true)
|
||||
, clear_color_(Color::Black)
|
||||
, resolution_mode_(ResolutionMode::Fixed)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ namespace kiwano
|
|||
KGE_LOG(L"Creating device resources");
|
||||
|
||||
hwnd_ = Window::GetInstance()->GetHandle();
|
||||
output_size_ = Window::GetInstance()->GetSize();
|
||||
resolution_ = output_size_ = Window::GetInstance()->GetSize();
|
||||
|
||||
d2d_res_ = nullptr;
|
||||
d3d_res_ = nullptr;
|
||||
|
|
@ -159,6 +160,12 @@ namespace kiwano
|
|||
hr = d3d_res_->ClearRenderTarget(clear_color_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SetTransform(Matrix3x2{});
|
||||
PushClipRect(Rect{ Point{}, resolution_ });
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
|
|
@ -171,8 +178,11 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PopClipRect();
|
||||
|
||||
EndDraw();
|
||||
|
||||
render_target_->RestoreDrawingState(drawing_state_block_.get());
|
||||
|
|
@ -201,7 +211,7 @@ namespace kiwano
|
|||
UInt32 width = LOWORD(lparam);
|
||||
UInt32 height = HIWORD(lparam);
|
||||
|
||||
Resize(width, height);
|
||||
ResizeTarget(width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -670,7 +680,30 @@ namespace kiwano
|
|||
vsync_ = enabled;
|
||||
}
|
||||
|
||||
void Renderer::Resize(UInt32 width, UInt32 height)
|
||||
void Renderer::SetResolution(Size const& resolution)
|
||||
{
|
||||
if (resolution_ != resolution)
|
||||
{
|
||||
resolution_ = resolution;
|
||||
UpdateResolution();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetResolutionMode(ResolutionMode mode)
|
||||
{
|
||||
if (resolution_mode_ != mode)
|
||||
{
|
||||
resolution_mode_ = mode;
|
||||
UpdateResolution();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetClearColor(const Color& color)
|
||||
{
|
||||
clear_color_ = color;
|
||||
}
|
||||
|
||||
void Renderer::ResizeTarget(UInt32 width, UInt32 height)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d3d_res_)
|
||||
|
|
@ -685,12 +718,58 @@ namespace kiwano
|
|||
hr = d3d_res_->SetLogicalSize(output_size_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UpdateResolution();
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::SetClearColor(const Color& color)
|
||||
void Renderer::UpdateResolution()
|
||||
{
|
||||
clear_color_ = color;
|
||||
switch (resolution_mode_)
|
||||
{
|
||||
case ResolutionMode::Fixed:
|
||||
{
|
||||
SetGlobalTransform(Matrix3x2{});
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolutionMode::Center:
|
||||
{
|
||||
Float32 left = math::Ceil((output_size_.x - resolution_.x) / 2);
|
||||
Float32 top = math::Ceil((output_size_.y - resolution_.y) / 2);
|
||||
SetGlobalTransform(Matrix3x2::Translation(Vec2{ left, top }));
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolutionMode::Stretch:
|
||||
{
|
||||
Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100;
|
||||
Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100;
|
||||
SetGlobalTransform(Matrix3x2::Scaling(Vec2{ scalex, scaley }));
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolutionMode::Adaptive:
|
||||
{
|
||||
Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100;
|
||||
Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100;
|
||||
if (scalex > scaley)
|
||||
{
|
||||
Float32 left = math::Ceil((output_size_.x - resolution_.x * scaley) / 2);
|
||||
SetGlobalTransform(Matrix3x2::SRT(Vec2{ left, 0 }, Vec2{ scaley, scaley }, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Float32 top = math::Ceil((output_size_.y - resolution_.y * scalex) / 2);
|
||||
SetGlobalTransform(Matrix3x2::SRT(Vec2{ 0, top }, Vec2{ scalex, scalex }, 0));
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,9 +131,12 @@ namespace kiwano
|
|||
ImageRenderTarget& render_target
|
||||
);
|
||||
|
||||
void Resize(
|
||||
UInt32 width,
|
||||
UInt32 height
|
||||
void SetResolution(
|
||||
Size const& resolution
|
||||
);
|
||||
|
||||
void SetResolutionMode(
|
||||
ResolutionMode mode
|
||||
);
|
||||
|
||||
public:
|
||||
|
|
@ -152,6 +155,10 @@ namespace kiwano
|
|||
|
||||
inline Size const& GetOutputSize() const { return output_size_; }
|
||||
|
||||
inline Size const& GetResolution() const { return resolution_; }
|
||||
|
||||
inline Color const& GetClearColor() const { return clear_color_; }
|
||||
|
||||
inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
|
||||
|
||||
inline ID3DDeviceResources* GetD3DDeviceResources() const { KGE_ASSERT(d3d_res_); return d3d_res_.get(); }
|
||||
|
|
@ -165,11 +172,17 @@ namespace kiwano
|
|||
|
||||
HRESULT HandleDeviceLost();
|
||||
|
||||
void ResizeTarget(UInt32 width, UInt32 height);
|
||||
|
||||
void UpdateResolution();
|
||||
|
||||
private:
|
||||
bool vsync_;
|
||||
HWND hwnd_;
|
||||
Size output_size_;
|
||||
Color clear_color_;
|
||||
bool vsync_;
|
||||
HWND hwnd_;
|
||||
Color clear_color_;
|
||||
Size output_size_;
|
||||
Size resolution_;
|
||||
ResolutionMode resolution_mode_;
|
||||
|
||||
ComPtr<ID2DDeviceResources> d2d_res_;
|
||||
ComPtr<ID3DDeviceResources> d3d_res_;
|
||||
|
|
|
|||
Loading…
Reference in New Issue