update: middleware-styled module

This commit is contained in:
Nomango 2020-07-21 20:56:49 +08:00
parent a197ea38bb
commit 765d20c988
16 changed files with 310 additions and 332 deletions

View File

@ -65,12 +65,12 @@ void ImGuiModule::DestroyModule()
ImGui::DestroyContext(); ImGui::DestroyContext();
} }
void ImGuiModule::OnUpdate(Duration dt) void ImGuiModule::OnUpdate(UpdateModuleContext& ctx)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
// Setup time step // Setup time step
io.DeltaTime = dt.Seconds(); io.DeltaTime = ctx.dt.Seconds();
// Read keyboard modifiers inputs // Read keyboard modifiers inputs
io.KeyCtrl = Input::GetInstance().IsDown(KeyCode::Ctrl); io.KeyCtrl = Input::GetInstance().IsDown(KeyCode::Ctrl);
@ -84,9 +84,13 @@ void ImGuiModule::OnUpdate(Duration dt)
// Update OS mouse cursor with the cursor requested by imgui // Update OS mouse cursor with the cursor requested by imgui
UpdateMouseCursor(); UpdateMouseCursor();
ctx.Next();
} }
void ImGuiModule::BeforeRender() void ImGuiModule::OnRender(RenderModuleContext& ctx)
{
// Before render
{ {
ImGui_Impl_NewFrame(); ImGui_Impl_NewFrame();
@ -100,17 +104,21 @@ void ImGuiModule::BeforeRender()
ImGui::NewFrame(); ImGui::NewFrame();
} }
void ImGuiModule::AfterRender() ctx.Next();
// After render
{ {
ImGui::Render(); ImGui::Render();
ImGui_Impl_RenderDrawData(ImGui::GetDrawData()); ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
} }
}
void ImGuiModule::HandleEvent(Event* evt) void ImGuiModule::HandleEvent(EventModuleContext& ctx)
{ {
if (ImGui::GetCurrentContext() == NULL) if (ImGui::GetCurrentContext() != NULL)
return; {
Event* evt = ctx.evt;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (evt->IsType<MouseEvent>()) if (evt->IsType<MouseEvent>())
@ -166,6 +174,9 @@ void ImGuiModule::HandleEvent(Event* evt)
} }
} }
ctx.Next();
}
void ImGuiModule::UpdateMousePos() void ImGuiModule::UpdateMousePos()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@ -34,9 +34,7 @@ namespace imgui
*/ */
class ImGuiModule class ImGuiModule
: public Singleton<ImGuiModule> : public Singleton<ImGuiModule>
, public RenderModule , public Module
, public UpdateModule
, public EventModule
{ {
friend Singleton<ImGuiModule>; friend Singleton<ImGuiModule>;
@ -47,13 +45,11 @@ public:
void DestroyModule() override; void DestroyModule() override;
void BeforeRender() override; void OnUpdate(UpdateModuleContext& ctx) override;
void AfterRender() override; void OnRender(RenderModuleContext& ctx) override;
void HandleEvent(Event* evt) override; void HandleEvent(EventModuleContext& ctx) override;
void OnUpdate(Duration dt) override;
private: private:
void UpdateMousePos(); void UpdateMousePos();

View File

@ -23,7 +23,6 @@
#include <kiwano/2d/Stage.h> #include <kiwano/2d/Stage.h>
#include <kiwano/2d/Transition.h> #include <kiwano/2d/Transition.h>
#include <kiwano/base/Director.h> #include <kiwano/base/Director.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
@ -119,11 +118,11 @@ void Director::ClearStages()
debug_actor_.Reset(); debug_actor_.Reset();
} }
void Director::OnUpdate(Duration dt) void Director::OnUpdate(UpdateModuleContext& ctx)
{ {
if (transition_) if (transition_)
{ {
transition_->Update(dt); transition_->Update(ctx.dt);
if (transition_->IsDone()) if (transition_->IsDone())
transition_ = nullptr; transition_ = nullptr;
@ -143,47 +142,53 @@ void Director::OnUpdate(Duration dt)
} }
if (current_stage_) if (current_stage_)
current_stage_->Update(dt); current_stage_->Update(ctx.dt);
if (next_stage_) if (next_stage_)
next_stage_->Update(dt); next_stage_->Update(ctx.dt);
if (debug_actor_) if (debug_actor_)
debug_actor_->Update(dt); debug_actor_->Update(ctx.dt);
ctx.Next();
} }
void Director::OnRender(RenderContext& ctx) void Director::OnRender(RenderModuleContext& ctx)
{ {
if (transition_) if (transition_)
{ {
transition_->Render(ctx); transition_->Render(ctx.render_ctx);
} }
else if (current_stage_) else if (current_stage_)
{ {
current_stage_->Render(ctx); current_stage_->Render(ctx.render_ctx);
if (render_border_enabled_) if (render_border_enabled_)
{ {
current_stage_->RenderBorder(ctx); current_stage_->RenderBorder(ctx.render_ctx);
} }
} }
if (debug_actor_) if (debug_actor_)
{ {
debug_actor_->Render(ctx); debug_actor_->Render(ctx.render_ctx);
}
} }
void Director::HandleEvent(Event* evt) ctx.Next();
}
void Director::HandleEvent(EventModuleContext& ctx)
{ {
if (current_stage_) if (current_stage_)
current_stage_->DispatchEvent(evt); current_stage_->DispatchEvent(ctx.evt);
if (next_stage_) if (next_stage_)
next_stage_->DispatchEvent(evt); next_stage_->DispatchEvent(ctx.evt);
if (debug_actor_) if (debug_actor_)
debug_actor_->DispatchEvent(evt); debug_actor_->DispatchEvent(ctx.evt);
ctx.Next();
} }
} // namespace kiwano } // namespace kiwano

View File

@ -34,9 +34,7 @@ namespace kiwano
*/ */
class KGE_API Director class KGE_API Director
: public Singleton<Director> : public Singleton<Director>
, public UpdateModule , public Module
, public RenderModule
, public EventModule
{ {
friend Singleton<Director>; friend Singleton<Director>;
@ -92,15 +90,11 @@ public:
void ClearStages(); void ClearStages();
public: public:
void SetupModule() override {} void OnUpdate(UpdateModuleContext& ctx) override;
void DestroyModule() override {} void OnRender(RenderModuleContext& ctx) override;
void OnUpdate(Duration dt) override; void HandleEvent(EventModuleContext& ctx) override;
void OnRender(RenderContext& ctx) override;
void HandleEvent(Event* evt) override;
virtual ~Director(); virtual ~Director();

View File

@ -19,28 +19,86 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/base/Module.h> #include <kiwano/base/Module.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
Module::Module() ModuleContext::ModuleContext(ModuleList& modules)
: flag_(0) : index_(-1)
, modules_(modules)
{ {
} }
RenderModule::RenderModule() ModuleContext::~ModuleContext() {}
void ModuleContext::Next()
{ {
flag_ |= ModuleFlag<RenderModule>::value; index_++;
for (; index_ < (int)modules_.size(); index_++)
{
this->Handle(modules_.at(index_));
}
} }
UpdateModule::UpdateModule() RenderModuleContext::RenderModuleContext(ModuleList& modules, RenderContext& ctx)
: ModuleContext(modules)
, render_ctx(ctx)
{ {
flag_ |= ModuleFlag<UpdateModule>::value; render_ctx.BeginDraw();
} }
EventModule::EventModule() RenderModuleContext::~RenderModuleContext()
{ {
flag_ |= ModuleFlag<EventModule>::value; render_ctx.EndDraw();
}
void RenderModuleContext::Handle(Module* m)
{
m->OnRender(*this);
}
UpdateModuleContext::UpdateModuleContext(ModuleList& modules, Duration dt)
: ModuleContext(modules)
, dt(dt)
{
}
void UpdateModuleContext::Handle(Module* m)
{
m->OnUpdate(*this);
}
EventModuleContext::EventModuleContext(ModuleList& modules, Event* evt)
: ModuleContext(modules)
, evt(evt)
{
}
void EventModuleContext::Handle(Module* m)
{
m->HandleEvent(*this);
}
Module::Module() {}
void Module::SetupModule() {}
void Module::DestroyModule() {}
void Module::OnRender(RenderModuleContext& ctx)
{
ctx.Next();
}
void Module::OnUpdate(UpdateModuleContext& ctx)
{
ctx.Next();
}
void Module::HandleEvent(EventModuleContext& ctx)
{
ctx.Next();
} }
} // namespace kiwano } // namespace kiwano

View File

@ -25,124 +25,104 @@ namespace kiwano
{ {
class RenderContext; class RenderContext;
class Event; class Event;
class Module;
template <typename _CompTy> /// \~chinese
struct ModuleFlag; /// @brief 模块列表
typedef Vector<Module*> ModuleList;
/// \~chinese
/// @brief 模块上下文
class KGE_API ModuleContext
{
public:
void Next();
protected:
ModuleContext(ModuleList& modules);
virtual ~ModuleContext();
virtual void Handle(Module* m) = 0;
private:
int index_;
ModuleList& modules_;
};
/// \~chinese
/// @brief 渲染模块上下文
class KGE_API RenderModuleContext : public ModuleContext
{
public:
RenderContext& render_ctx;
RenderModuleContext(ModuleList& modules, RenderContext& ctx);
virtual ~RenderModuleContext();
protected:
void Handle(Module* m) override;
};
/// \~chinese
/// @brief 更新模块上下文
class KGE_API UpdateModuleContext : public ModuleContext
{
public:
Duration dt;
UpdateModuleContext(ModuleList& modules, Duration dt);
protected:
void Handle(Module* m) override;
};
/// \~chinese
/// @brief 时间模块上下文
class KGE_API EventModuleContext : public ModuleContext
{
public:
Event* evt;
EventModuleContext(ModuleList& modules, Event* evt);
protected:
void Handle(Module* m) override;
};
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Module class KGE_API Module : Noncopyable
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 启动模块 /// @brief 启动模块
virtual void SetupModule() {} virtual void SetupModule();
/// \~chinese /// \~chinese
/// @brief 销毁模块 /// @brief 销毁模块
virtual void DestroyModule() {} virtual void DestroyModule();
template <typename _CompTy>
_CompTy* Cast()
{
if (flag_ & ModuleFlag<_CompTy>::value)
return dynamic_cast<_CompTy*>(this);
return nullptr;
}
protected:
Module();
protected:
int flag_;
};
/**
* \~chinese
* @brief
*/
class KGE_API RenderModule : public virtual Module
{
public:
/// \~chinese
/// @brief 渲染前
virtual void BeforeRender() {}
/// \~chinese /// \~chinese
/// @brief 渲染时 /// @brief 渲染时
/// @param ctx 渲染上下文 /// @param ctx 渲染上下文
virtual void OnRender(RenderContext& ctx) {} virtual void OnRender(RenderModuleContext& ctx);
/// \~chinese
/// @brief 渲染后
virtual void AfterRender() {}
public:
RenderModule();
};
/**
* \~chinese
* @brief
*/
class KGE_API UpdateModule : public virtual Module
{
public:
/// \~chinese
/// @brief 更新前
virtual void BeforeUpdate() {}
/// \~chinese /// \~chinese
/// @brief 更新时 /// @brief 更新时
/// @param dt 间隔时间 /// @param ctx 更新上下文
virtual void OnUpdate(Duration dt) {} virtual void OnUpdate(UpdateModuleContext& ctx);
/// \~chinese
/// @brief 更新后
virtual void AfterUpdate() {}
public:
UpdateModule();
};
/**
* \~chinese
* @brief
*/
class KGE_API EventModule : public virtual Module
{
public:
/// \~chinese /// \~chinese
/// @brief 事件处理 /// @brief 事件处理
/// @param evt 事件 /// @param ctx 事件上下文
virtual void HandleEvent(Event* evt) {} virtual void HandleEvent(EventModuleContext& ctx);
public: protected:
EventModule(); Module();
}; };
#define KGE_DEFINE_COMPONENT_FLAG(OFFSET) (0x01 << (OFFSET % 32))
template <>
struct ModuleFlag<RenderModule>
{
static constexpr int value = KGE_DEFINE_COMPONENT_FLAG(0);
};
template <>
struct ModuleFlag<UpdateModule>
{
static constexpr int value = KGE_DEFINE_COMPONENT_FLAG(1);
};
template <>
struct ModuleFlag<EventModule>
{
static constexpr int value = KGE_DEFINE_COMPONENT_FLAG(2);
};
#undef KGE_DEFINE_COMPONENT_FLAG
} // namespace kiwano } // namespace kiwano

View File

@ -162,13 +162,8 @@ void Application::DispatchEvent(Event* evt)
if (!running_ /* Dispatch events even if application is paused */) if (!running_ /* Dispatch events even if application is paused */)
return; return;
for (auto comp : modules_) auto ctx = EventModuleContext(modules_, evt);
{ ctx.Next();
if (auto event_comp = comp->Cast<EventModule>())
{
event_comp->HandleEvent(evt);
}
}
} }
void Application::Update(Duration dt) void Application::Update(Duration dt)
@ -176,17 +171,10 @@ void Application::Update(Duration dt)
if (!running_ || is_paused_) if (!running_ || is_paused_)
return; return;
// Before update auto ctx = UpdateModuleContext(modules_, dt);
for (auto comp : modules_) ctx.Next();
{
if (auto update_comp = comp->Cast<UpdateModule>())
{
update_comp->BeforeUpdate();
}
}
// perform functions // perform functions
{
if (!functions_to_perform_.empty()) if (!functions_to_perform_.empty())
{ {
perform_mutex_.lock(); perform_mutex_.lock();
@ -205,26 +193,6 @@ void Application::Update(Duration dt)
} }
} }
// Updating
Duration scaled_dt = dt * time_scale_;
for (auto comp : modules_)
{
if (auto update_comp = comp->Cast<UpdateModule>())
{
update_comp->OnUpdate(scaled_dt);
}
}
// After update
for (auto rit = modules_.rbegin(); rit != modules_.rend(); ++rit)
{
if (auto update_comp = (*rit)->Cast<UpdateModule>())
{
update_comp->AfterUpdate();
}
}
}
void Application::Render() void Application::Render()
{ {
if (!running_ /* Render even if application is paused */) if (!running_ /* Render even if application is paused */)
@ -233,33 +201,9 @@ void Application::Render()
Renderer& renderer = Renderer::GetInstance(); Renderer& renderer = Renderer::GetInstance();
renderer.Clear(); renderer.Clear();
// Before render
for (auto comp : modules_)
{ {
if (auto render_comp = comp->Cast<RenderModule>()) auto ctx = RenderModuleContext(modules_, renderer.GetContext());
{ ctx.Next();
render_comp->BeforeRender();
}
}
// Rendering
renderer.BeginDraw();
for (auto comp : modules_)
{
if (auto render_comp = comp->Cast<RenderModule>())
{
render_comp->OnRender(renderer.GetContext());
}
}
renderer.EndDraw();
// After render
for (auto rit = modules_.rbegin(); rit != modules_.rend(); ++rit)
{
if (auto render_comp = (*rit)->Cast<RenderModule>())
{
render_comp->AfterRender();
}
} }
renderer.Present(); renderer.Present();

View File

@ -42,7 +42,8 @@ extern KGE_API int GetVersion();
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Application : public Singleton<Application> class KGE_API Application
: public Singleton<Application>
{ {
friend Singleton<Application>; friend Singleton<Application>;
@ -169,7 +170,7 @@ private:
float time_scale_; float time_scale_;
RunnerPtr runner_; RunnerPtr runner_;
TimerPtr timer_; TimerPtr timer_;
List<Module*> modules_; ModuleList modules_;
std::mutex perform_mutex_; std::mutex perform_mutex_;
Queue<Function<void()>> functions_to_perform_; Queue<Function<void()>> functions_to_perform_;
}; };

View File

@ -34,21 +34,6 @@ Input::Input()
Input::~Input() {} Input::~Input() {}
void Input::AfterUpdate()
{
if (want_update_keys_)
{
want_update_keys_ = false;
::memcpy(keys_[Prev].data(), keys_[Current].data(), KEY_NUM * sizeof(bool));
}
if (want_update_buttons_)
{
want_update_buttons_ = false;
buttons_[Prev] = buttons_[Current];
}
}
bool Input::IsDown(KeyCode key) const bool Input::IsDown(KeyCode key) const
{ {
if (key == KeyCode::Unknown || key == KeyCode::Last) if (key == KeyCode::Unknown || key == KeyCode::Last)
@ -129,8 +114,27 @@ void Input::UpdateMousePos(const Point& pos)
mouse_pos_ = pos; mouse_pos_ = pos;
} }
void Input::HandleEvent(Event* evt) void Input::OnUpdate(UpdateModuleContext& ctx)
{ {
ctx.Next();
if (want_update_keys_)
{
want_update_keys_ = false;
::memcpy(keys_[Prev].data(), keys_[Current].data(), KEY_NUM * sizeof(bool));
}
if (want_update_buttons_)
{
want_update_buttons_ = false;
buttons_[Prev] = buttons_[Current];
}
}
void Input::HandleEvent(EventModuleContext& ctx)
{
Event* evt = ctx.evt;
if (evt->IsType<MouseEvent>()) if (evt->IsType<MouseEvent>())
{ {
if (evt->IsType<MouseMoveEvent>()) if (evt->IsType<MouseMoveEvent>())
@ -157,5 +161,8 @@ void Input::HandleEvent(Event* evt)
UpdateKey(dynamic_cast<KeyUpEvent*>(evt)->code, false); UpdateKey(dynamic_cast<KeyUpEvent*>(evt)->code, false);
} }
} }
ctx.Next();
} }
} // namespace kiwano } // namespace kiwano

View File

@ -35,8 +35,7 @@ namespace kiwano
*/ */
class KGE_API Input class KGE_API Input
: public Singleton<Input> : public Singleton<Input>
, public UpdateModule , public Module
, public EventModule
{ {
friend Singleton<Input>; friend Singleton<Input>;
@ -104,13 +103,9 @@ public:
Point GetMousePos() const; Point GetMousePos() const;
public: public:
void SetupModule() override {} void OnUpdate(UpdateModuleContext& ctx) override;
void DestroyModule() override {} void HandleEvent(EventModuleContext& ctx) override;
void AfterUpdate() override;
void HandleEvent(Event* evt) override;
~Input(); ~Input();

View File

@ -91,6 +91,7 @@ void Runner::InitSettings()
Renderer::GetInstance().SetVSyncEnabled(settings_.vsync_enabled); Renderer::GetInstance().SetVSyncEnabled(settings_.vsync_enabled);
// Use defaut modules // Use defaut modules
Application::GetInstance().Use(Renderer::GetInstance());
Application::GetInstance().Use(Input::GetInstance()); Application::GetInstance().Use(Input::GetInstance());
Application::GetInstance().Use(Director::GetInstance()); Application::GetInstance().Use(Director::GetInstance());

View File

@ -20,7 +20,6 @@
#include <kiwano/utils/Logger.h> #include <kiwano/utils/Logger.h>
#include <kiwano/render/DirectX/D3D11DeviceResources.h> #include <kiwano/render/DirectX/D3D11DeviceResources.h>
#include <memory>
KGE_SUPPRESS_WARNING_PUSH KGE_SUPPRESS_WARNING_PUSH
KGE_SUPPRESS_WARNING(4800) // Implicit conversion from 'type' to bool KGE_SUPPRESS_WARNING(4800) // Implicit conversion from 'type' to bool

View File

@ -166,6 +166,15 @@ void RendererImpl::Destroy()
::CoUninitialize(); ::CoUninitialize();
} }
void RendererImpl::HandleEvent(EventModuleContext& ctx)
{
if (ctx.evt->IsType<WindowResizedEvent>())
{
auto evt = ctx.evt->SafeCast<WindowResizedEvent>();
Resize(evt->width, evt->height);
}
}
void RendererImpl::Clear() void RendererImpl::Clear()
{ {
KGE_ASSERT(d3d_res_); KGE_ASSERT(d3d_res_);

View File

@ -83,6 +83,8 @@ public:
void Destroy() override; void Destroy() override;
void HandleEvent(EventModuleContext& ctx) override;
protected: protected:
RendererImpl(); RendererImpl();

View File

@ -19,8 +19,6 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/render/Renderer.h> #include <kiwano/render/Renderer.h>
#include <kiwano/event/WindowEvent.h>
#include <kiwano/platform/Application.h>
namespace kiwano namespace kiwano
{ {
@ -31,18 +29,4 @@ Renderer::Renderer()
{ {
} }
void Renderer::BeginDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->BeginDraw();
}
void Renderer::EndDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->EndDraw();
}
} // namespace kiwano } // namespace kiwano

View File

@ -44,7 +44,7 @@ namespace kiwano
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Renderer : public Noncopyable class KGE_API Renderer : public Module
{ {
public: public:
/// \~chinese /// \~chinese
@ -218,14 +218,6 @@ public:
virtual RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) = 0; virtual RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) = 0;
public: public:
/// \~chinese
/// @brief ¿ªÊ¼äÖȾ
virtual void BeginDraw();
/// \~chinese
/// @brief ½áÊøäÖȾ
virtual void EndDraw();
/// \~chinese /// \~chinese
/// @brief 清除绘制内容 /// @brief 清除绘制内容
virtual void Clear() = 0; virtual void Clear() = 0;