diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 5263f3e8..4bd46c9f 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -23,6 +23,7 @@ + @@ -150,6 +151,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index 823c4b29..ff452122 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -393,6 +393,9 @@ 2d\transition + + base\component + @@ -647,6 +650,9 @@ 2d\transition + + base\component + diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index ebdfb9ee..caa9dfad 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -44,9 +44,6 @@ Actor::Actor() , visible_(true) , visible_in_rt_(true) , update_pausing_(false) - , hover_(false) - , pressed_(false) - , responsible_(false) , cascade_opacity_(true) , show_border_(false) , evt_dispatch_enabled_(true) @@ -225,8 +222,8 @@ void Actor::SetEventDispatchEnabled(bool enabled) void Actor::DoSerialize(Serializer* serializer) const { ObjectBase::DoSerialize(serializer); - (*serializer) << visible_ << update_pausing_ << cascade_opacity_ << responsible_ << z_order_ << opacity_ << anchor_ - << size_ << transform_; + (*serializer) << visible_ << update_pausing_ << cascade_opacity_ << z_order_ << opacity_ << anchor_ << size_ + << transform_; } void Actor::DoDeserialize(Deserializer* deserializer) @@ -235,8 +232,8 @@ void Actor::DoDeserialize(Deserializer* deserializer) float opacity = 1.0f; Transform transform; - (*deserializer) >> visible_ >> update_pausing_ >> cascade_opacity_ >> responsible_ >> z_order_ >> opacity >> anchor_ - >> size_ >> transform; + (*deserializer) >> visible_ >> update_pausing_ >> cascade_opacity_ >> z_order_ >> opacity >> anchor_ >> size_ + >> transform; SetOpacity(opacity); SetTransform(transform); @@ -248,49 +245,6 @@ bool Actor::HandleEvent(Event* evt) if (!EventDispatcher::DispatchEvent(evt)) return false; - - if (responsible_) - { - if (evt->IsType()) - { - auto mouse_evt = dynamic_cast(evt); - bool contains = ContainsPoint(mouse_evt->pos); - if (!hover_ && contains) - { - hover_ = true; - - MouseHoverEventPtr hover = new MouseHoverEvent; - hover->pos = mouse_evt->pos; - HandleEvent(hover.Get()); - } - else if (hover_ && !contains) - { - hover_ = false; - pressed_ = false; - - MouseOutEventPtr out = new MouseOutEvent; - out->pos = mouse_evt->pos; - HandleEvent(out.Get()); - } - } - - if (evt->IsType() && hover_) - { - pressed_ = true; - } - - if (evt->IsType() && pressed_) - { - pressed_ = false; - - auto mouse_up_evt = dynamic_cast(evt); - - MouseClickEventPtr click = new MouseClickEvent; - click->pos = mouse_up_evt->pos; - click->button = mouse_up_evt->button; - HandleEvent(click.Get()); - } - } return true; } @@ -660,11 +614,6 @@ void Actor::RemoveAllChildren() children_.Clear(); } -void Actor::SetResponsible(bool enable) -{ - responsible_ = enable; -} - bool Actor::ContainsPoint(const Point& point) const { if (size_.x == 0.f || size_.y == 0.f) diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 90d79a7a..324c6d24 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -98,10 +98,6 @@ public: /// @brief 获取显示状态 bool IsVisible() const; - /// \~chinese - /// @brief 获取响应状态 - bool IsResponsible() const; - /// \~chinese /// @brief 是否启用级联透明度 bool IsCascadeOpacityEnabled() const; @@ -334,11 +330,6 @@ public: /// @brief 设置 Z 轴顺序,默认为 0 void SetZOrder(int zorder); - /// \~chinese - /// @brief 设置角色是否可响应,默认为 false - /// @details 可响应的角色会收到鼠标的 Hover | Out | Click 消息 - void SetResponsible(bool enable); - /// \~chinese /// @brief 添加子角色 void AddChild(ActorPtr child); @@ -425,6 +416,11 @@ public: /// @return 是否继续分发该事件 virtual bool DispatchEvent(Event* evt); + /// \~chinese + /// @brief 处理事件且不分发 + /// @param evt 事件 + bool HandleEvent(Event* evt); + /// \~chinese /// @brief 开启或关闭事件分发功能 /// @param enabled 是否开启 @@ -483,10 +479,6 @@ protected: /// @brief 设置节点所在舞台 void SetStage(Stage* stage); - /// \~chinese - /// @brief 处理事件 - bool HandleEvent(Event* evt); - /// \~chinese /// @brief 设置物理身体 void SetPhysicBody(physics::PhysicBody* body); @@ -498,9 +490,6 @@ private: bool update_pausing_; bool cascade_opacity_; bool show_border_; - bool hover_; - bool pressed_; - bool responsible_; bool evt_dispatch_enabled_; mutable bool visible_in_rt_; @@ -549,11 +538,6 @@ inline bool Actor::IsVisible() const return visible_; } -inline bool Actor::IsResponsible() const -{ - return responsible_; -} - inline bool Actor::IsCascadeOpacityEnabled() const { return cascade_opacity_; diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 5c0cf791..361f061e 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #pragma comment(lib, "psapi.lib") @@ -49,9 +50,11 @@ DebugActor::DebugActor() { SetName("kiwano-debug-actor"); SetPosition(Point{ 10, 10 }); - SetResponsible(true); SetCascadeOpacityEnabled(true); + MouseSensorPtr sensor = new MouseSensor; + this->AddComponent(sensor); + comma_locale_ = std::locale(std::locale(), new comma_numpunct); background_brush_ = MakePtr(); diff --git a/src/kiwano/base/component/Button.cpp b/src/kiwano/base/component/Button.cpp index d7f803f4..c7314b88 100644 --- a/src/kiwano/base/component/Button.cpp +++ b/src/kiwano/base/component/Button.cpp @@ -24,7 +24,6 @@ namespace kiwano { ButtonBase::ButtonBase() - : status_(Status::Normal) { SetName("__KGE_BUTTON__"); } @@ -33,41 +32,25 @@ ButtonBase::~ButtonBase() { } -void ButtonBase::InitComponent(Actor* actor) -{ - Component::InitComponent(actor); - if (actor) - { - actor->SetResponsible(true); - } -} - -void ButtonBase::DestroyComponent() -{ - Component::DestroyComponent(); -} - void ButtonBase::HandleEvent(kiwano::Event* evt) { + MouseSensor::HandleEvent(evt); + if (evt->IsType()) { OnEvent(Event::MouseEntered); - status_ = Status::Hover; } else if (evt->IsType()) { OnEvent(Event::MouseExited); - status_ = Status::Normal; } - else if (evt->IsType() && status_ == Status::Hover) + else if (evt->IsType() && this->IsHovering()) { OnEvent(Event::Pressed); - status_ = Status::Pressed; } - else if (evt->IsType() && status_ == Status::Pressed) + else if (evt->IsType() && this->IsPressing()) { OnEvent(Event::Released); - status_ = Status::Hover; } else if (evt->IsType()) { diff --git a/src/kiwano/base/component/Button.h b/src/kiwano/base/component/Button.h index 8adebf37..5a616c02 100644 --- a/src/kiwano/base/component/Button.h +++ b/src/kiwano/base/component/Button.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include namespace kiwano { @@ -35,7 +35,7 @@ KGE_DECLARE_SMART_PTR(Button); * \~chinese * @brief 基础按钮组件 */ -class KGE_API ButtonBase : public Component +class KGE_API ButtonBase : public MouseSensor { public: /// \~chinese @@ -58,25 +58,9 @@ public: virtual void OnEvent(Event evt) = 0; protected: - /// \~chinese - /// @brief 初始化组件 - void InitComponent(Actor* actor) override; - - /// \~chinese - /// @brief 销毁组件 - void DestroyComponent() override; - /// \~chinese /// @brief 处理角色事件 void HandleEvent(kiwano::Event* evt) override; - -private: - enum class Status - { - Normal, - Hover, - Pressed - } status_; }; /** diff --git a/src/kiwano/base/component/ComponentManager.cpp b/src/kiwano/base/component/ComponentManager.cpp index a0d3dbb7..392c4b43 100644 --- a/src/kiwano/base/component/ComponentManager.cpp +++ b/src/kiwano/base/component/ComponentManager.cpp @@ -124,14 +124,11 @@ void ComponentManager::Update(Duration dt) { if (!components_.empty()) { - if (!components_.empty()) + for (auto& p : components_) { - for (auto& p : components_) + if (p.second->IsEnable()) { - if (p.second->IsEnable()) - { - p.second->OnUpdate(dt); - } + p.second->OnUpdate(dt); } } } @@ -141,14 +138,11 @@ void ComponentManager::Render(RenderContext& ctx) { if (!components_.empty()) { - if (!components_.empty()) + for (auto& p : components_) { - for (auto& p : components_) + if (p.second->IsEnable()) { - if (p.second->IsEnable()) - { - p.second->OnRender(ctx); - } + p.second->OnRender(ctx); } } } @@ -158,14 +152,11 @@ void ComponentManager::DispatchToComponents(Event* evt) { if (!components_.empty()) { - if (!components_.empty()) + for (auto& p : components_) { - for (auto& p : components_) + if (p.second->IsEnable()) { - if (p.second->IsEnable()) - { - p.second->HandleEvent(evt); - } + p.second->HandleEvent(evt); } } } diff --git a/src/kiwano/base/component/MouseSensor.cpp b/src/kiwano/base/component/MouseSensor.cpp new file mode 100644 index 00000000..5da183d2 --- /dev/null +++ b/src/kiwano/base/component/MouseSensor.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include + +namespace kiwano +{ +MouseSensor::MouseSensor() + : hover_(false) + , pressed_(false) +{ +} + +MouseSensor::~MouseSensor() {} + +void MouseSensor::HandleEvent(Event* evt) +{ + Actor* target = GetBoundActor(); + if (evt->IsType()) + { + auto mouse_evt = dynamic_cast(evt); + bool contains = target->ContainsPoint(mouse_evt->pos); + if (!hover_ && contains) + { + hover_ = true; + + MouseHoverEventPtr hover = new MouseHoverEvent; + hover->pos = mouse_evt->pos; + target->HandleEvent(hover.Get()); + } + else if (hover_ && !contains) + { + hover_ = false; + pressed_ = false; + + MouseOutEventPtr out = new MouseOutEvent; + out->pos = mouse_evt->pos; + target->HandleEvent(out.Get()); + } + } + + if (evt->IsType() && hover_) + { + pressed_ = true; + } + + if (evt->IsType() && pressed_) + { + pressed_ = false; + + auto mouse_up_evt = dynamic_cast(evt); + + MouseClickEventPtr click = new MouseClickEvent; + click->pos = mouse_up_evt->pos; + click->button = mouse_up_evt->button; + target->HandleEvent(click.Get()); + } +} + +} // namespace kiwano diff --git a/src/kiwano/base/component/MouseSensor.h b/src/kiwano/base/component/MouseSensor.h new file mode 100644 index 00000000..ce366ed8 --- /dev/null +++ b/src/kiwano/base/component/MouseSensor.h @@ -0,0 +1,77 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include + +namespace kiwano +{ + +KGE_DECLARE_SMART_PTR(MouseSensor); + +/** + * \addtogroup Component + * @{ + */ + +/** + * \~chinese + * @brief 鼠标传感器 + * @details 该组件使角色会收到鼠标的 Hover | Out | Click 消息 + */ +class KGE_API MouseSensor : public Component +{ +public: + MouseSensor(); + + virtual ~MouseSensor(); + + /// \~chinese + /// @brief 鼠标是否正悬于角色上 + bool IsHovering() const; + + /// \~chinese + /// @brief 鼠标是否正按于角色上 + bool IsPressing() const; + +protected: + /// \~chinese + /// @brief 处理角色事件 + void HandleEvent(Event* evt) override; + +private: + bool hover_; + bool pressed_; +}; + +/** @} */ + +inline bool MouseSensor::IsHovering() const +{ + return hover_; +} + +inline bool MouseSensor::IsPressing() const +{ + return pressed_; +} + +} // namespace kiwano diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 4b7c65b2..111fbecd 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -49,18 +49,6 @@ #include #include -// -// base -// - -#include -#include -#include -#include -#include -#include -#include - // // event @@ -73,6 +61,19 @@ #include #include +// +// base +// + +#include +#include +#include +#include +#include +#include +#include +#include + // // renderer //