Initial engine repository
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/base/RefObject.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <frostbite2D/types/uuid.h>
|
||||
#include <frostbite2D/utils/intrusive_list.hpp>
|
||||
#include <frostbite2D/event/event.h>
|
||||
#include <frostbite2D/event/key_event.h>
|
||||
#include <frostbite2D/event/mouse_event.h>
|
||||
#include <frostbite2D/event/touch_event.h>
|
||||
#include <frostbite2D/event/joystick_event.h>
|
||||
#include <frostbite2D/event/window_event.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Actor;
|
||||
class Scene;
|
||||
|
||||
using ActorList = IntrusiveList<RefPtr<Actor>>;
|
||||
|
||||
class Actor : public RefObject, protected IntrusiveListValue<RefPtr<Actor>> {
|
||||
public:
|
||||
using IntrusiveListValue<RefPtr<Actor>>::GetNext;
|
||||
using IntrusiveListValue<RefPtr<Actor>>::GetPrev;
|
||||
|
||||
Actor();
|
||||
virtual ~Actor();
|
||||
|
||||
virtual void Update(float deltaTime);
|
||||
virtual void Render();
|
||||
virtual void OnUpdate(float deltaTime) {}
|
||||
virtual void OnAdded(Actor* parent) {}
|
||||
|
||||
void AddChild(RefPtr<Actor> child);
|
||||
void RemoveChild(RefPtr<Actor> child);
|
||||
void RemoveAllChildren();
|
||||
|
||||
Actor* GetParent() const { return parent_; }
|
||||
Scene* GetScene() const { return scene_; }
|
||||
|
||||
const std::string& GetName() const { return name_; }
|
||||
void SetName(const std::string& name) { name_ = name; }
|
||||
|
||||
const UUID& GetUUID() const { return uuid_; }
|
||||
std::string GetUUIDString() const { return uuid_.toString(); }
|
||||
|
||||
/**
|
||||
* @brief 获取锚点在父坐标系中的位置
|
||||
*/
|
||||
const Vec2& GetPosition() const { return position_; }
|
||||
/**
|
||||
* @brief 设置锚点在父坐标系中的位置
|
||||
*/
|
||||
void SetPosition(const Vec2& pos);
|
||||
void SetPosition(float x, float y);
|
||||
|
||||
float GetRotation() const { return rotation_; }
|
||||
void SetRotation(float rotation);
|
||||
|
||||
const Vec2& GetScale() const { return scale_; }
|
||||
void SetScale(const Vec2& scale);
|
||||
void SetScale(float scale);
|
||||
|
||||
const Vec2& GetSkew() const { return skew_; }
|
||||
void SetSkew(const Vec2& skew);
|
||||
void SetSkew(float skewX, float skewY);
|
||||
|
||||
const Transform2D& GetLocalTransform() const;
|
||||
const Transform2D& GetWorldTransform() const;
|
||||
|
||||
const Vec2& GetSize() const { return size_; }
|
||||
void SetSize(const Vec2& size);
|
||||
void SetSize(float width, float height);
|
||||
|
||||
/**
|
||||
* @brief 获取归一化锚点,(0, 0) 为左上角,(0.5, 0.5) 为中心
|
||||
*/
|
||||
const Vec2& GetAnchor() const { return anchor_; }
|
||||
/**
|
||||
* @brief 设置归一化锚点,不会自动补偿 position
|
||||
*/
|
||||
void SetAnchor(const Vec2& anchor);
|
||||
void SetAnchor(float x, float y);
|
||||
|
||||
/**
|
||||
* @brief 获取未旋转矩形左上角在父坐标系中的位置
|
||||
*/
|
||||
Vec2 GetTopLeftPosition() const;
|
||||
/**
|
||||
* @brief 设置未旋转矩形左上角在父坐标系中的位置
|
||||
*/
|
||||
void SetTopLeftPosition(const Vec2& pos);
|
||||
void SetTopLeftPosition(float x, float y);
|
||||
Vec2 LocalToWorld(const Vec2& point) const;
|
||||
Vec2 WorldToLocal(const Vec2& point) const;
|
||||
Rect GetWorldBounds() const;
|
||||
bool ContainsWorldPoint(const Vec2& point) const;
|
||||
bool ContainsWorldPoint(float x, float y) const;
|
||||
|
||||
bool IsVisible() const { return visible_; }
|
||||
void SetVisible(bool visible) { visible_ = visible; }
|
||||
|
||||
int GetZOrder() const { return zOrder_; }
|
||||
void SetZOrder(int zOrder);
|
||||
|
||||
float GetOpacity() const { return opacity_; }
|
||||
void SetOpacity(float opacity);
|
||||
float GetWorldOpacity() const;
|
||||
|
||||
ActorList& GetChildren() { return children_; }
|
||||
const ActorList& GetChildren() const { return children_; }
|
||||
|
||||
bool IsEventReceiveEnabled() const { return eventReceiveEnabled_; }
|
||||
void EnableEventReceive() { eventReceiveEnabled_ = true; }
|
||||
void DisableEventReceive() { eventReceiveEnabled_ = false; }
|
||||
|
||||
int32 GetEventPriority() const { return eventPriority_; }
|
||||
void SetEventPriority(int32 priority) { eventPriority_ = priority; }
|
||||
|
||||
bool IsEventInterceptEnabled() const { return eventInterceptEnabled_; }
|
||||
void EnableEventIntercept() { eventInterceptEnabled_ = true; }
|
||||
void DisableEventIntercept() { eventInterceptEnabled_ = false; }
|
||||
|
||||
enum class UpdatePhase {
|
||||
BeforeChildren,
|
||||
AfterChildren
|
||||
};
|
||||
|
||||
using UpdateCallback = Function<void(Actor&, float)>;
|
||||
using EventCallback = std::function<bool(const Event&)>;
|
||||
|
||||
uint32 AddUpdateListener(UpdateCallback callback,
|
||||
UpdatePhase phase = UpdatePhase::BeforeChildren);
|
||||
bool RemoveUpdateListener(uint32 listenerId);
|
||||
void ClearUpdateListeners();
|
||||
|
||||
uint32 AddEventListener(EventType type, EventCallback callback);
|
||||
bool RemoveEventListener(uint32 listenerId);
|
||||
void ClearEventListeners();
|
||||
|
||||
virtual bool OnEvent(const Event& event);
|
||||
|
||||
bool DispatchEvent(const Event& event);
|
||||
bool BubbleEvent(const Event& event);
|
||||
|
||||
protected:
|
||||
void SetParent(Actor* parent) { parent_ = parent; }
|
||||
void SetScene(Scene* scene) { scene_ = scene; }
|
||||
|
||||
void insertChildByZOrder(RefPtr<Actor> child);
|
||||
void UpdateChildren(float deltaTime);
|
||||
void RenderChildren();
|
||||
|
||||
virtual void OnTransformChanged() {};
|
||||
|
||||
private:
|
||||
void markChildrenOrderDirty();
|
||||
void reorderChildrenByZOrder();
|
||||
|
||||
Actor* parent_;
|
||||
Scene* scene_;
|
||||
ActorList children_;
|
||||
|
||||
UUID uuid_;
|
||||
std::string name_;
|
||||
Vec2 position_;
|
||||
float rotation_;
|
||||
Vec2 scale_ = Vec2(1.0f, 1.0f);
|
||||
Vec2 skew_;
|
||||
Vec2 size_;
|
||||
Vec2 anchor_;
|
||||
bool visible_;
|
||||
int zOrder_;
|
||||
float opacity_;
|
||||
|
||||
mutable Transform2D localTransform_;
|
||||
mutable Transform2D worldTransform_;
|
||||
mutable bool transformDirty_ = true;
|
||||
|
||||
bool eventReceiveEnabled_ = false;
|
||||
int32 eventPriority_ = 0;
|
||||
bool eventInterceptEnabled_ = false;
|
||||
|
||||
struct UpdateListener {
|
||||
uint32 id;
|
||||
UpdatePhase phase;
|
||||
UpdateCallback callback;
|
||||
bool active = true;
|
||||
};
|
||||
std::vector<UpdateListener> updateListeners_;
|
||||
uint32 nextUpdateListenerId_ = 1;
|
||||
bool iteratingUpdateListeners_ = false;
|
||||
bool updateListenersDirty_ = false;
|
||||
bool iteratingChildren_ = false;
|
||||
bool childrenOrderDirty_ = false;
|
||||
|
||||
struct EventListener {
|
||||
uint32 id;
|
||||
EventType type;
|
||||
EventCallback callback;
|
||||
};
|
||||
std::vector<EventListener> eventListeners_;
|
||||
uint32 nextListenerId_ = 1;
|
||||
|
||||
void markTransformDirty();
|
||||
void updateLocalTransform() const;
|
||||
void updateWorldTransform() const;
|
||||
void executeUpdateListeners(UpdatePhase phase, float deltaTime);
|
||||
void compactUpdateListeners();
|
||||
|
||||
friend class Scene;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/2d/sprite.h>
|
||||
#include <frostbite2D/graphics/camera.h>
|
||||
#include <frostbite2D/graphics/render_texture.h>
|
||||
#include <functional>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
/// @brief 离屏画布节点。
|
||||
///
|
||||
/// 子节点通过 `AddCanvasChild()` 挂到内部画布树,只会在重绘到离屏纹理时参与渲染,
|
||||
/// 不会像普通场景子节点那样直接显示到屏幕。
|
||||
class CanvasActor : public Sprite {
|
||||
public:
|
||||
CanvasActor();
|
||||
~CanvasActor() override = default;
|
||||
|
||||
bool Init(int width, int height);
|
||||
bool SetCanvasSize(int width, int height);
|
||||
Vec2 GetCanvasSize() const {
|
||||
return Vec2(static_cast<float>(canvasWidth_), static_cast<float>(canvasHeight_));
|
||||
}
|
||||
|
||||
void SetClearColor(const Color& color);
|
||||
const Color& GetClearColor() const { return clearColor_; }
|
||||
|
||||
void SetDirty();
|
||||
bool IsDirty() const { return dirty_; }
|
||||
bool Redraw();
|
||||
void SetCustomDrawCallback(std::function<void()> callback);
|
||||
void ClearCustomDrawCallback();
|
||||
|
||||
void AddCanvasChild(RefPtr<Actor> child);
|
||||
void RemoveCanvasChild(RefPtr<Actor> child);
|
||||
void RemoveAllCanvasChildren();
|
||||
Actor* GetCanvasRoot() const { return canvasRoot_.Get(); }
|
||||
ActorList& GetCanvasChildren() { return canvasRoot_->GetChildren(); }
|
||||
const ActorList& GetCanvasChildren() const { return canvasRoot_->GetChildren(); }
|
||||
|
||||
Ptr<Texture> GetOutputTexture() const;
|
||||
Ptr<RenderTexture> GetRenderTexture() const { return renderTexture_; }
|
||||
bool IsCanvasReady() const { return renderTexture_ && renderTexture_->IsValid(); }
|
||||
Camera& GetCanvasCamera() { return canvasCamera_; }
|
||||
const Camera& GetCanvasCamera() const { return canvasCamera_; }
|
||||
|
||||
void OnUpdate(float deltaTime) override;
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
bool redrawInternal();
|
||||
void syncCanvasResources();
|
||||
|
||||
RefPtr<Actor> canvasRoot_;
|
||||
Ptr<RenderTexture> renderTexture_ = nullptr;
|
||||
Camera canvasCamera_;
|
||||
Color clearColor_ = Colors::Transparent;
|
||||
int canvasWidth_ = 0;
|
||||
int canvasHeight_ = 0;
|
||||
bool dirty_ = true;
|
||||
std::function<void()> customDrawCallback_;
|
||||
};
|
||||
|
||||
} // namespace frostbite2D
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/2d/actor.h>
|
||||
#include <frostbite2D/graphics/texture.h>
|
||||
#include <frostbite2D/graphics/shader.h>
|
||||
#include <frostbite2D/graphics/types.h>
|
||||
#include <string>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Sprite : public Actor {
|
||||
public:
|
||||
Sprite();
|
||||
explicit Sprite(Ptr<Texture> texture);
|
||||
virtual ~Sprite();
|
||||
|
||||
static Ptr<Sprite> createFromFile(const std::string& path);
|
||||
static Ptr<Sprite> createFromMemory(const uint8* data, int width, int height, int channels);
|
||||
static Ptr<Sprite> createFromNpk(const std::string& imgPath, size_t frameIndex = 0);
|
||||
|
||||
void Render() override;
|
||||
|
||||
void SetTexture(Ptr<Texture> texture);
|
||||
Ptr<Texture> GetTexture() const { return texture_; }
|
||||
|
||||
void SetShader(const std::string& shaderName);
|
||||
void SetDefaultShader();
|
||||
const std::string& GetShaderName() const { return shaderName_; }
|
||||
bool HasCustomShader() const { return !shaderName_.empty(); }
|
||||
|
||||
void SetSourceRect(const Rect& rect);
|
||||
const Rect& GetSourceRect() const { return srcRect_; }
|
||||
|
||||
void SetColor(const Color& color);
|
||||
void SetColor(float r, float g, float b, float a = 1.0f);
|
||||
const Color& GetColor() const { return color_; }
|
||||
|
||||
void SetFlippedX(bool flipped);
|
||||
void SetFlippedY(bool flipped);
|
||||
bool IsFlippedX() const { return flippedX_; }
|
||||
bool IsFlippedY() const { return flippedY_; }
|
||||
|
||||
void SetBlendMode(BlendMode mode);
|
||||
BlendMode GetBlendMode() const { return blendMode_; }
|
||||
|
||||
void SetSizeToTexture();
|
||||
|
||||
const Vec2& GetOffset() const { return offset_; }
|
||||
void SetOffset(const Vec2& offset);
|
||||
void SetOffset(float x, float y);
|
||||
|
||||
protected:
|
||||
virtual void ConfigureShader(Shader* shader) const;
|
||||
void updateTransform();
|
||||
Shader* getActiveShader() const;
|
||||
Quad createQuad() const;
|
||||
|
||||
private:
|
||||
Ptr<Texture> texture_;
|
||||
std::string shaderName_;
|
||||
Color color_ = Color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Rect srcRect_;
|
||||
bool flippedX_ = false;
|
||||
bool flippedY_ = false;
|
||||
BlendMode blendMode_ = BlendMode::Normal;
|
||||
Vec2 offset_ = Vec2::Zero();
|
||||
Transform2D transform_;
|
||||
|
||||
static constexpr const char* DEFAULT_SHADER = "sprite";
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/2d/sprite.h>
|
||||
#include <frostbite2D/types/type_color.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <string>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class TextSprite : public Sprite {
|
||||
public:
|
||||
enum class Align {
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
};
|
||||
|
||||
TextSprite();
|
||||
~TextSprite();
|
||||
|
||||
static Ptr<TextSprite> create();
|
||||
static Ptr<TextSprite> create(const std::string& text, const std::string& fontName);
|
||||
|
||||
void SetText(const std::string& text);
|
||||
const std::string& GetText() const { return text_; }
|
||||
|
||||
void SetFont(const std::string& fontName);
|
||||
const std::string& GetFontName() const { return fontName_; }
|
||||
|
||||
void SetTextColor(const Color& color);
|
||||
void SetTextColor(float r, float g, float b, float a = 1.0f);
|
||||
const Color& GetTextColor() const { return textColor_; }
|
||||
|
||||
void SetAlign(Align align);
|
||||
Align GetAlign() const { return align_; }
|
||||
|
||||
void RenderText();
|
||||
Vec2 GetTextSize() const;
|
||||
|
||||
private:
|
||||
void updateTexture();
|
||||
|
||||
std::string text_;
|
||||
std::string fontName_;
|
||||
Color textColor_ = Colors::White;
|
||||
Align align_ = Align::Left;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user