[deploy] Merge pull request #58 from KiwanoEngine/dev

Merge dev branch
This commit is contained in:
Haibo 2020-06-23 21:02:14 +08:00 committed by GitHub
commit 3885c44938
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 162 additions and 83 deletions

View File

@ -45,6 +45,7 @@ private:
} // namespace
DebugActor::DebugActor()
: frame_buffer_(70 /* pre-alloc for 70 frames */)
{
SetName("kiwano-debug-actor");
SetPosition(Point{ 10, 10 });
@ -77,10 +78,10 @@ void DebugActor::OnRender(RenderContext& ctx)
ctx.FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f });
ctx.DrawTextLayout(debug_text_, Point(10, 10));
frame_time_.push_back(Time::Now());
while (frame_time_.back() - frame_time_.front() >= Duration::Second)
frame_buffer_.PushBack(Time::Now());
while (frame_buffer_.Back() - frame_buffer_.Front() >= Duration::Second)
{
frame_time_.erase(frame_time_.begin());
frame_buffer_.PopFront();
}
}
@ -93,7 +94,7 @@ void DebugActor::OnUpdate(Duration dt)
// For formatting integers with commas
(void)ss.imbue(comma_locale_);
ss << "Fps: " << frame_time_.size() << std::endl;
ss << "Fps: " << frame_buffer_.Size() << std::endl;
#if defined(KGE_DEBUG)
if (ObjectBase::IsTracingLeaks())
@ -106,7 +107,7 @@ void DebugActor::OnUpdate(Duration dt)
ss << "Render: " << status.duration.Milliseconds() << "ms" << std::endl;
ss << "Primitives / sec: " << std::fixed << status.primitives * frame_time_.size() << std::endl;
ss << "Primitives / sec: " << std::fixed << status.primitives * frame_buffer_.Size() << std::endl;
ss << "Memory: ";
{

View File

@ -24,6 +24,99 @@
namespace kiwano
{
template <typename T>
class SimpleRingBuffer
{
public:
SimpleRingBuffer(size_t capcity)
{
Reserve(capcity);
}
void PushBack(const T& val)
{
if (IsFull())
Reserve(Capacity() * 2);
buffer_[rear_] = val;
IncreaseRear();
}
void PopFront()
{
IncreaseFront();
}
const T& Front() const
{
return buffer_[front_];
}
T& Front()
{
return buffer_[front_];
}
const T& Back() const
{
return buffer_[ClampCursor(rear_, 1)];
}
T& Back()
{
return buffer_[ClampCursor(rear_, 1)];
}
bool IsEmpty() const noexcept
{
return front_ = rear_;
}
bool IsFull() const noexcept
{
return front_ == (rear_ + 1) % Capacity();
}
size_t Size() const
{
return ClampCursor(rear_, front_);
}
size_t Capacity() const
{
return buffer_.size();
}
void Reserve(size_t capacity)
{
buffer_.resize(capacity);
}
private:
void IncreaseFront()
{
if (buffer_.empty())
return;
front_ = (front_ + 1) % Capacity();
}
void IncreaseRear()
{
rear_ = (rear_ + 1) % Capacity();
}
size_t ClampCursor(size_t cursor, size_t off) const
{
return (cursor + Capacity() - off) % Capacity();
}
private:
Vector<T> buffer_;
size_t front_ = 0;
size_t rear_ = 0;
};
/**
* \addtogroup Actors
* @{
@ -52,7 +145,8 @@ private:
BrushPtr background_brush_;
TextStyle debug_text_style_;
TextLayout debug_text_;
List<Time> frame_time_;
SimpleRingBuffer<Time> frame_buffer_;
};
/** @} */

View File

@ -82,8 +82,7 @@ void Runner::InitSettings()
}
// Create game window
WindowPtr window = Window::Create(settings_.title, settings_.width, settings_.height, settings_.icon,
settings_.resizable, settings_.fullscreen);
WindowPtr window = Window::Create(settings_.window);
SetWindow(window);
// Update renderer settings
@ -131,9 +130,9 @@ bool Runner::MainLoop(Duration dt)
app.DispatchEvent(evt.Get());
}
// Update frame ticker
if (frame_ticker_)
{
// Update frame ticker
if (frame_ticker_->Tick(dt))
{
app.UpdateFrame(frame_ticker_->GetDeltaTime());

View File

@ -40,25 +40,14 @@ KGE_DECLARE_SMART_PTR(Runner);
*/
struct Settings
{
uint32_t width; ///< 窗口宽度
uint32_t height; ///< 窗口高度
String title; ///< 窗口标题
Icon icon; ///< 窗口图标
bool resizable; ///< 窗口大小可调整
bool fullscreen; ///< 窗口全屏
Color bg_color; ///< 窗口背景色
Duration frame_interval; ///< 帧间隔
bool vsync_enabled; ///< 垂直同步
bool debug_mode; ///< 调试模式
WindowConfig window; ///< ´°¿ÚÉèÖÃ
Color bg_color; ///< ±³¾°É«
Duration frame_interval; ///< Ö¡¼ä¸ô
bool vsync_enabled; ///< ´¹Ö±Í¬²½
bool debug_mode; ///< µ÷ÊÔģʽ
Settings()
: width(800)
, height(600)
, title("Kiwano")
, icon()
, resizable(false)
, fullscreen(false)
, bg_color(Color::Black)
: bg_color(Color::Black)
, frame_interval(0)
, vsync_enabled(true)
, debug_mode(false)

View File

@ -82,6 +82,21 @@ struct Icon
};
/**
* \~chinese
* @brief
*/
struct WindowConfig
{
uint32_t width = 640; ///< 窗口宽度
uint32_t height = 480; ///< 窗口高度
String title = "Kiwano Game"; ///< 窗口标题
Icon icon; ///< 窗口图标
bool resizable = false; ///< 窗口大小可调整
bool fullscreen = false; ///< 窗口全屏
};
#if defined(KGE_PLATFORM_WINDOWS)
typedef HWND WindowHandle;
#endif
@ -97,15 +112,10 @@ public:
/**
* \~chinese
* @brief
* @param title
* @param width
* @param height
* @param icon ID
* @param resizable
* @param config
* @throw kiwano::SystemError
*/
static WindowPtr Create(const String& title, uint32_t width, uint32_t height, Icon icon = Icon(),
bool resizable = false, bool fullscreen = false);
static WindowPtr Create(const WindowConfig& config);
/**
* \~chinese

View File

@ -49,7 +49,7 @@ public:
virtual ~WindowWin32Impl();
void Init(const String& title, uint32_t width, uint32_t height, Icon icon, bool resizable, bool fullscreen);
void Init(const WindowConfig& config);
void SetTitle(const String& title) override;
@ -88,13 +88,12 @@ private:
std::array<KeyCode, 256> key_map_;
};
WindowPtr Window::Create(const String& title, uint32_t width, uint32_t height, Icon icon, bool resizable,
bool fullscreen)
WindowPtr Window::Create(const WindowConfig& config)
{
WindowWin32ImplPtr ptr = memory::New<WindowWin32Impl>();
if (ptr)
{
ptr->Init(title, width, height, icon, resizable, fullscreen);
ptr->Init(config);
}
return ptr;
}
@ -142,6 +141,28 @@ void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_wi
*win_height = screenh;
}
HICON Icon2HIcon(const Icon& icon)
{
HICON hicon = NULL;
if (icon.resource_id != 0 && IS_INTRESOURCE(icon.resource_id))
{
HINSTANCE hinstance = ::GetModuleHandle(nullptr);
hicon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon.resource_id), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
else
{
String full_path = FileSystem::GetInstance().GetFullPathForFile(icon.file_path);
if (!full_path.empty())
{
hicon = (HICON)::LoadImageA(NULL, full_path.c_str(), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
}
}
return hicon;
}
} // namespace
WindowWin32Impl::WindowWin32Impl()
@ -206,16 +227,15 @@ WindowWin32Impl::~WindowWin32Impl()
::timeEndPeriod(0);
}
void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, Icon icon, bool resizable,
bool fullscreen)
void WindowWin32Impl::Init(const WindowConfig& config)
{
HINSTANCE hinst = GetModuleHandle(nullptr);
HINSTANCE hinst = GetModuleHandle(nullptr);
WNDCLASSEXA wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = "KiwanoAppWnd";
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
wcex.lpfnWndProc = WindowWin32Impl::StaticWndProc;
wcex.hIcon = nullptr;
wcex.hIcon = Icon2HIcon(config.icon);
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = hinst;
@ -223,21 +243,6 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height,
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursor(hinst, IDC_ARROW);
if (icon.resource_id != 0 && IS_INTRESOURCE(icon.resource_id))
{
wcex.hIcon = (HICON)::LoadImage(hinst, MAKEINTRESOURCE(icon.resource_id), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
else
{
String full_path = FileSystem::GetInstance().GetFullPathForFile(icon.file_path);
if (!full_path.empty())
{
wcex.hIcon = (HICON)::LoadImageA(NULL, full_path.c_str(), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
}
}
::RegisterClassExA(&wcex);
// Get the nearest monitor to this window
@ -256,21 +261,19 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height,
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
uint32_t win_width, win_height;
AdjustWindow(width, height, GetStyle(), &win_width, &win_height);
AdjustWindow(config.width, config.height, GetStyle(), &win_width, &win_height);
int left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
int top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;
width = win_width;
height = win_height;
width_ = width;
height_ = height;
resizable_ = resizable;
is_fullscreen_ = fullscreen;
width_ = win_width;
height_ = win_height;
resizable_ = config.resizable;
is_fullscreen_ = config.fullscreen;
resolution_ = Resolution{ width_, height_, 0 };
handle_ = ::CreateWindowExA(0, "KiwanoAppWnd", title.c_str(), GetStyle(), left, top, width, height, nullptr,
nullptr, hinst, nullptr);
handle_ = ::CreateWindowExA(0, "KiwanoAppWnd", config.title.c_str(), GetStyle(), left, top, width_, height_,
nullptr, nullptr, hinst, nullptr);
if (handle_ == nullptr)
{
@ -321,24 +324,7 @@ void WindowWin32Impl::SetIcon(Icon icon)
{
KGE_ASSERT(handle_);
HICON hicon = NULL;
if (icon.resource_id != 0 && IS_INTRESOURCE(icon.resource_id))
{
HINSTANCE hinstance = ::GetModuleHandle(nullptr);
hicon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon.resource_id), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
else
{
String full_path = FileSystem::GetInstance().GetFullPathForFile(icon.file_path);
if (!full_path.empty())
{
hicon = (HICON)::LoadImageA(NULL, full_path.c_str(), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
}
}
HICON hicon = Icon2HIcon(icon);
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)hicon);
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
}