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();
}
void ImGuiModule::OnUpdate(Duration dt)
void ImGuiModule::OnUpdate(UpdateModuleContext& ctx)
{
ImGuiIO& io = ImGui::GetIO();
// Setup time step
io.DeltaTime = dt.Seconds();
io.DeltaTime = ctx.dt.Seconds();
// Read keyboard modifiers inputs
io.KeyCtrl = Input::GetInstance().IsDown(KeyCode::Ctrl);
@ -84,10 +84,14 @@ void ImGuiModule::OnUpdate(Duration dt)
// Update OS mouse cursor with the cursor requested by imgui
UpdateMouseCursor();
ctx.Next();
}
void ImGuiModule::BeforeRender()
void ImGuiModule::OnRender(RenderModuleContext& ctx)
{
// Before render
{
ImGui_Impl_NewFrame();
ImGuiIO& io = ImGui::GetIO();
@ -98,19 +102,23 @@ void ImGuiModule::BeforeRender()
io.DisplaySize = ImVec2(display_size.x, display_size.y);
ImGui::NewFrame();
}
}
void ImGuiModule::AfterRender()
{
ctx.Next();
// After render
{
ImGui::Render();
ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
}
}
void ImGuiModule::HandleEvent(Event* evt)
void ImGuiModule::HandleEvent(EventModuleContext& ctx)
{
if (ImGui::GetCurrentContext() == NULL)
return;
if (ImGui::GetCurrentContext() != NULL)
{
Event* evt = ctx.evt;
ImGuiIO& io = ImGui::GetIO();
if (evt->IsType<MouseEvent>())
@ -164,6 +172,9 @@ void ImGuiModule::HandleEvent(Event* evt)
io.AddInputCharacter(static_cast<ImWchar>(ch));
}
}
}
ctx.Next();
}
void ImGuiModule::UpdateMousePos()

View File

@ -34,9 +34,7 @@ namespace imgui
*/
class ImGuiModule
: public Singleton<ImGuiModule>
, public RenderModule
, public UpdateModule
, public EventModule
, public Module
{
friend Singleton<ImGuiModule>;
@ -47,13 +45,11 @@ public:
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 OnUpdate(Duration dt) override;
void HandleEvent(EventModuleContext& ctx) override;
private:
void UpdateMousePos();

View File

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

View File

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

View File

@ -19,28 +19,86 @@
// THE SOFTWARE.
#include <kiwano/base/Module.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano
{
Module::Module()
: flag_(0)
ModuleContext::ModuleContext(ModuleList& modules)
: 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

View File

@ -25,124 +25,104 @@ namespace kiwano
{
class RenderContext;
class Event;
class Module;
template <typename _CompTy>
struct ModuleFlag;
/// \~chinese
/// @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
* @brief
*/
class KGE_API Module
class KGE_API Module : Noncopyable
{
public:
/// \~chinese
/// @brief 启动模块
virtual void SetupModule() {}
virtual void SetupModule();
/// \~chinese
/// @brief 销毁模块
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() {}
virtual void DestroyModule();
/// \~chinese
/// @brief 渲染时
/// @param ctx 渲染上下文
virtual void OnRender(RenderContext& ctx) {}
/// \~chinese
/// @brief 渲染后
virtual void AfterRender() {}
public:
RenderModule();
};
/**
* \~chinese
* @brief
*/
class KGE_API UpdateModule : public virtual Module
{
public:
/// \~chinese
/// @brief 更新前
virtual void BeforeUpdate() {}
virtual void OnRender(RenderModuleContext& ctx);
/// \~chinese
/// @brief 更新时
/// @param dt 间隔时间
virtual void OnUpdate(Duration dt) {}
/// @param ctx 更新上下文
virtual void OnUpdate(UpdateModuleContext& ctx);
/// \~chinese
/// @brief 更新后
virtual void AfterUpdate() {}
public:
UpdateModule();
};
/**
* \~chinese
* @brief
*/
class KGE_API EventModule : public virtual Module
{
public:
/// \~chinese
/// @brief 事件处理
/// @param evt 事件
virtual void HandleEvent(Event* evt) {}
/// @param ctx 事件上下文
virtual void HandleEvent(EventModuleContext& ctx);
public:
EventModule();
protected:
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

View File

@ -162,13 +162,8 @@ void Application::DispatchEvent(Event* evt)
if (!running_ /* Dispatch events even if application is paused */)
return;
for (auto comp : modules_)
{
if (auto event_comp = comp->Cast<EventModule>())
{
event_comp->HandleEvent(evt);
}
}
auto ctx = EventModuleContext(modules_, evt);
ctx.Next();
}
void Application::Update(Duration dt)
@ -176,17 +171,10 @@ void Application::Update(Duration dt)
if (!running_ || is_paused_)
return;
// Before update
for (auto comp : modules_)
{
if (auto update_comp = comp->Cast<UpdateModule>())
{
update_comp->BeforeUpdate();
}
}
auto ctx = UpdateModuleContext(modules_, dt);
ctx.Next();
// perform functions
{
if (!functions_to_perform_.empty())
{
perform_mutex_.lock();
@ -203,26 +191,6 @@ void Application::Update(Duration dt)
functions.pop();
}
}
}
// 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()
@ -233,33 +201,9 @@ void Application::Render()
Renderer& renderer = Renderer::GetInstance();
renderer.Clear();
// Before render
for (auto comp : modules_)
{
if (auto render_comp = comp->Cast<RenderModule>())
{
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();
}
auto ctx = RenderModuleContext(modules_, renderer.GetContext());
ctx.Next();
}
renderer.Present();

View File

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

View File

@ -34,21 +34,6 @@ 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
{
if (key == KeyCode::Unknown || key == KeyCode::Last)
@ -129,8 +114,27 @@ void Input::UpdateMousePos(const Point& 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<MouseMoveEvent>())
@ -157,5 +161,8 @@ void Input::HandleEvent(Event* evt)
UpdateKey(dynamic_cast<KeyUpEvent*>(evt)->code, false);
}
}
ctx.Next();
}
} // namespace kiwano

View File

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

View File

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

View File

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

View File

@ -166,6 +166,15 @@ void RendererImpl::Destroy()
::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()
{
KGE_ASSERT(d3d_res_);

View File

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

View File

@ -19,8 +19,6 @@
// THE SOFTWARE.
#include <kiwano/render/Renderer.h>
#include <kiwano/event/WindowEvent.h>
#include <kiwano/platform/Application.h>
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

View File

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