#pragma once #include #include #include #include #include #include #include namespace extra2d { class Node; class Comp; class Act; namespace Anchor { constexpr Vec2 BottomLeft = Vec2(0.0f, 0.0f); constexpr Vec2 Bottom = Vec2(0.5f, 0.0f); constexpr Vec2 BottomRight = Vec2(1.0f, 0.0f); constexpr Vec2 Left = Vec2(0.0f, 0.5f); constexpr Vec2 Center = Vec2(0.5f, 0.5f); constexpr Vec2 Right = Vec2(1.0f, 0.5f); constexpr Vec2 TopLeft = Vec2(0.0f, 1.0f); constexpr Vec2 Top = Vec2(0.5f, 1.0f); constexpr Vec2 TopRight = Vec2(1.0f, 1.0f); } class Comp { public: virtual ~Comp() = default; virtual const char* type() const = 0; virtual void onAttach(Node* o) { owner_ = o; } virtual void onDetach() { owner_ = nullptr; } virtual void onEnable() {} virtual void onDisable() {} virtual void update(f32 dt) {} virtual void lateUpdate(f32 dt) {} Node* owner() const { return owner_; } bool enabled() const { return enabled_; } void setEnabled(bool e); protected: Node* owner_ = nullptr; bool enabled_ = true; }; class Node : public std::enable_shared_from_this { friend class SceneGraph; public: virtual ~Node(); Vec2 pos = Vec2(0, 0); Vec2 scale = Vec2(1, 1); f32 rot = 0.0f; Vec2 anchor = Vec2(0.5f, 0.5f); void setAnchor(f32 x, f32 y) { anchor = Vec2(x, y); } void setAnchor(const Vec2& a) { anchor = a; } void setPos(f32 x, f32 y) { pos = Vec2(x, y); } void setPos(const Vec2& p) { pos = p; } void setScale(f32 x, f32 y) { scale = Vec2(x, y); } void setScale(const Vec2& s) { scale = s; } void setScale(f32 s) { scale = Vec2(s, s); } void setRot(f32 r) { rot = r; } Mat3 local() const; Mat3 world() const; Mat4 world4x4() const; Vec2 worldPos() const; f32 worldRot() const; Vec2 worldScale() const; template T* add(Args&&... args) { auto c = std::make_unique(std::forward(args)...); T* p = c.get(); addInternal(std::move(c)); return p; } template T* get() { for (auto& c : comps_) { if (auto* p = dynamic_cast(c.get())) { return p; } } return nullptr; } template const T* get() const { for (auto& c : comps_) { if (auto* p = dynamic_cast(c.get())) { return p; } } return nullptr; } template void remove() { comps_.erase( std::remove_if(comps_.begin(), comps_.end(), [](const auto& c) { return dynamic_cast(c.get()) != nullptr; }), comps_.end() ); } void updateComps(f32 dt); void lateUpdateComps(f32 dt); void addChild(Ref child); void removeChild(Ref child); void removeFromParent(); Node* parent() const { return parent_; } const std::vector>& children() const { return children_; } virtual void onInit() {} virtual void onUpdate(f32 dt) {} virtual void onRender() {} const std::string& name() const { return name_; } void setName(const std::string& n) { name_ = n; } bool visible() const { return visible_; } void setVisible(bool v) { visible_ = v; } i32 tag() const { return tag_; } void setTag(i32 t) { tag_ = t; } Act* run(Act* a); void stop(Act* a); void stopByTag(i32 tag); void stopAll(); Act* getActByTag(i32 tag); i32 runningActs() const; void updateActs(f32 dt); protected: virtual Vec2 defaultAnchor() const { return Vec2(0.5f, 0.5f); } std::vector> comps_; Node* parent_ = nullptr; std::vector> children_; std::string name_; bool visible_ = true; i32 tag_ = 0; std::vector acts_; void addInternal(Unique c); }; inline void Comp::setEnabled(bool e) { if (enabled_ != e) { enabled_ = e; if (enabled_) { onEnable(); } else { onDisable(); } } } }