diff --git a/kiwano/2d/Node.cpp b/kiwano/2d/Node.cpp index 99e9fd1a..e8c5eee6 100644 --- a/kiwano/2d/Node.cpp +++ b/kiwano/2d/Node.cpp @@ -47,6 +47,8 @@ namespace kiwano , dirty_transform_(false) , dirty_transform_inverse_(false) , cascade_opacity_(false) + , show_border_(false) + , is_fast_transform_(true) , parent_(nullptr) , scene_(nullptr) , hash_name_(0) @@ -117,6 +119,22 @@ namespace kiwano } } + void Node::RenderBorder() + { + if (show_border_) + { + Rect bounds = GetBounds(); + Renderer::Instance()->SetTransform(transform_matrix_); + Renderer::Instance()->FillRectangle(bounds, Color(Color::Red, .4f)); + Renderer::Instance()->DrawRectangle(bounds, Color(Color::Red, .8f), 4.f); + } + + for (auto child = children_.First(); child; child = child->NextItem()) + { + child->RenderBorder(); + } + } + void Node::Dispatch(Event& evt) { if (!visible_) diff --git a/kiwano/2d/Node.h b/kiwano/2d/Node.h index 923d160a..673415bc 100644 --- a/kiwano/2d/Node.h +++ b/kiwano/2d/Node.h @@ -392,7 +392,10 @@ namespace kiwano inline void SetCallbackOnUpdate(UpdateCallback const& cb) { cb_update_ = cb; } // 获取更新时的回调函数 - inline UpdateCallback const& GetCallbackOnUpdate() { return cb_update_; } + inline UpdateCallback GetCallbackOnUpdate() const { return cb_update_; } + + // 渲染节点边界 + inline void ShowBorder(bool show) { show_border_ = show; } // 设置默认锚点 static void SetDefaultAnchor( @@ -409,16 +412,18 @@ namespace kiwano virtual void Update(Duration dt); - void Render(); + virtual void Render(); + + void RenderBorder(); void UpdateTransform() const; void UpdateOpacity(); - void SetScene(Scene* scene); - void Reorder(); + void SetScene(Scene* scene); + protected: bool visible_; bool hover_; @@ -426,6 +431,7 @@ namespace kiwano bool responsible_; bool update_pausing_; bool cascade_opacity_; + bool show_border_; int z_order_; float opacity_; float displayed_opacity_; diff --git a/kiwano/2d/Scene.cpp b/kiwano/2d/Scene.cpp index 5cb6e6a5..a19667f5 100644 --- a/kiwano/2d/Scene.cpp +++ b/kiwano/2d/Scene.cpp @@ -25,6 +25,7 @@ namespace kiwano { Scene::Scene() + : render_border_enabled_(false) { scene_ = this; @@ -46,4 +47,14 @@ namespace kiwano KGE_LOG(L"Scene exited"); } + void Scene::Render() + { + Node::Render(); + + if (render_border_enabled_) + { + Node::RenderBorder(); + } + } + } diff --git a/kiwano/2d/Scene.h b/kiwano/2d/Scene.h index 3dbddae5..f42f8ae8 100644 --- a/kiwano/2d/Scene.h +++ b/kiwano/2d/Scene.h @@ -27,6 +27,9 @@ namespace kiwano class KGE_API Scene : public Node { + friend class Transition; + friend class Application; + public: Scene(); @@ -37,5 +40,14 @@ namespace kiwano // 退出场景 virtual void OnExit(); + + // 启用或禁用场景内的节点边界渲染功能 + inline void SetRenderBorderEnabled(bool enabled) { render_border_enabled_ = enabled; } + + protected: + void Render() override; + + protected: + bool render_border_enabled_; }; } diff --git a/kiwano/common/Json.h b/kiwano/common/Json.h index 7ff64e3b..34512b75 100644 --- a/kiwano/common/Json.h +++ b/kiwano/common/Json.h @@ -775,6 +775,7 @@ namespace kiwano : out(out) , indent_char(indent_char) , indent_string(32, indent_char) + , number_buffer() {} void dump( @@ -2706,7 +2707,7 @@ namespace std }; template<> - inline void swap<::kiwano::Json>(::kiwano::Json& lhs, ::kiwano::Json& rhs) + inline void swap<::kiwano::Json>(::kiwano::Json& lhs, ::kiwano::Json& rhs) noexcept { lhs.swap(rhs); } diff --git a/kiwano/common/String.h b/kiwano/common/String.h index ded533a7..970b10e4 100644 --- a/kiwano/common/String.h +++ b/kiwano/common/String.h @@ -1377,7 +1377,7 @@ namespace std }; template<> - inline void swap<::kiwano::String>(::kiwano::String& lhs, ::kiwano::String& rhs) + inline void swap<::kiwano::String>(::kiwano::String& lhs, ::kiwano::String& rhs) noexcept { lhs.swap(rhs); } diff --git a/kiwano/renderer/render.cpp b/kiwano/renderer/render.cpp index 4a6a8638..6a145494 100644 --- a/kiwano/renderer/render.cpp +++ b/kiwano/renderer/render.cpp @@ -261,6 +261,39 @@ namespace kiwano return S_OK; } + HRESULT Renderer::DrawRectangle(Rect const& rect, const Color& stroke_color, float stroke_width, StrokeStyle stroke) + { + if (!solid_color_brush_ || !device_context_) + return E_UNEXPECTED; + + solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + + device_context_->DrawRectangle( + DX::ConvertToRectF(rect), + solid_color_brush_.Get(), + stroke_width, + d2d_res_->GetStrokeStyle(stroke) + ); + + if (collecting_status_) + ++status_.primitives; + return S_OK; + } + + HRESULT Renderer::FillRectangle(Rect const& rect, Color const& fill_color) + { + if (!solid_color_brush_ || !device_context_) + return E_UNEXPECTED; + + solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); + device_context_->FillRectangle( + DX::ConvertToRectF(rect), + solid_color_brush_.Get() + ); + + return S_OK; + } + HRESULT Renderer::DrawImage(ImagePtr image, Rect const& dest_rect) { if (!device_context_) @@ -400,13 +433,17 @@ namespace kiwano return S_OK; } - void Renderer::SetOpacity(float opacity) + HRESULT Renderer::SetOpacity(float opacity) { + if (!solid_color_brush_) + return E_UNEXPECTED; + if (opacity_ != opacity) { opacity_ = opacity; solid_color_brush_->SetOpacity(opacity); } + return S_OK; } HRESULT Renderer::SetTextStyle( diff --git a/kiwano/renderer/render.h b/kiwano/renderer/render.h index 6f4127fc..b38392b1 100644 --- a/kiwano/renderer/render.h +++ b/kiwano/renderer/render.h @@ -67,6 +67,18 @@ namespace kiwano Color const& fill_color ); + HRESULT DrawRectangle( + Rect const& rect, + const Color& stroke_color, + float stroke_width, + StrokeStyle stroke = StrokeStyle::Miter + ); + + HRESULT FillRectangle( + Rect const& rect, + Color const& fill_color + ); + HRESULT DrawImage( ImagePtr image, Rect const& dest_rect @@ -103,7 +115,7 @@ namespace kiwano ); // 设置画笔透明度 - void SetOpacity( + HRESULT SetOpacity( float opacity ); @@ -187,8 +199,6 @@ namespace kiwano HRESULT EndDraw(); private: - unsigned long ref_count_; - HWND hwnd_; float opacity_; bool antialias_;