跳转至

Entt介绍

由于EnTT的System部分由用户自己编写,所以EnTT并没有提供任何System并行支持,本系列也不会说。并行支持部分可自行参阅flecs源码。 EnTT 是一个仅有头的、微小的、易于使用的库,用于游戏编程以及用现代C++编写的更多内容

面是一个简短的,但不完整的清单,它今天提供了什么。

  • 内建的RTTI系统与标准系统相似。
  • 一个constexpr 工具,用于人类可读的资源名称
  • 使用单态模式建立的最小的配置系统
  • 令人难以置信的快速的实体-组件系统,它有自己的_付费_政策。
  • 视图和组来迭代实体和组件,并允许不同的访问模式,从完美的SoA到完全随机。
  • 在实体-组件系统的基础上建立了很多设施,以帮助用户,避免重新发明轮子。
  • 见过的最小和最基本的服务定位器的实现。
  • 一个内置的、非侵入性的、无宏的运行时反射系统
  • 静态多态性变得简单,每个人都可以做到。
  • 一些自制的容器,如基于稀疏集的哈希图
  • 一个适用于任何类型进程的合作调度器
  • 资源管理所需的一切(缓存、加载器、手柄)。
  • 代表、信号处理程序和一个小小的事件调度器。
  • 一个通用的事件发射器,作为一个基于CRTP习语的类模板。
  • 还有更多!请看 维基.

把这些列表看作是正在进行的工作,也是项目的一部分。整个API对于那些敢于阅读它的人来说是有完整的代码记录的。
请注意,现在所有的工具也都是DLL友好的,并且可以跨边界顺利运行。

大多数人都知道的一件事是,EnTT 也被用于Minecraft

组件类Component.h

单独存放各种组件(也许后面还可以再分细点)。 * 不需要做任何继承 * 只需要提供:参数+构造方法+运算符 * 运算符重载:运算符重载允许 TransformComponent 实例被当作 glm::mat4 类型的左值引用使用。这意味着你可以像操作 glm::mat4 对象一样直接操作 TransformComponent 实例的 Transform 成员变量。 * 举个栗子:

cpp
void DoSomethingWithTransform(const glm::mat4& transform) {
    // ...
}


TransformComponent tc;
DoSomethingWithTransform(tc); // 直接传递实例,不需要显式访问 Transform 成员变量
代码:
#pragma once
#include <glm/glm.hpp>
namespace CryDust {

    struct TransformComponent
    {
        glm::mat4 Transform{ 1.0f };
        TransformComponent() = default;
        TransformComponent(const TransformComponent&) = default;
        TransformComponent(const glm::mat4& transform) 
            : Transform(transform) {}
        operator glm::mat4& () { return Transform; }
        operator const glm::mat4& () const { return Transform; }
    };


    struct SpriteRendererComponent
    {
        glm::vec4 Color{ 1.0f, 1.0f, 1.0f, 1.0f };
        SpriteRendererComponent() = default;
        SpriteRendererComponent(const SpriteRendererComponent&) = default;
        SpriteRendererComponent(const glm::vec4& color)
            : Color(color) {}
    };
}

Scene类

构造

  • 使用registry.create创建一个entity
  • m_Registry.emplace添加组件,如TransformComponent

其他

  • registry注册表:包含了组件数据

  • DoMath():用来处理数学变换

  • OnTransformConstruct()::用于绑定组件构造,需要提供一个registry参数和entity参数
  • Scene()
  • CreateEntity()
  • OnUpdate(ts):拿到registry的group中的组件,遍历调用,并逐个绘制对应的Mesh
    #pragma once
    #include "entt.hpp"
    #include "CryDust/Core/Timestep.h"
    namespace CryDust {
        class Scene
        {
        public:
            Scene();
            ~Scene();
            entt::entity CreateEntity(); //创建实体
            // TEMP
            entt::registry& Reg() { return m_Registry; } //注册实体
            void OnUpdate(Timestep ts);
        private:
            entt::registry m_Registry;//注册
        };
    }
    

CPP

#include "cdpch.h"
#include "Scene.h"
#include "Components.h"
#include "CryDust/Renderer/Renderer2D.h"
#include <glm/glm.hpp>
namespace CryDust {
    static void DoMath(const glm::mat4& transform)
    {
    }
    static void OnTransformConstruct(entt::registry& registry, entt::entity entity)
    {
    }
    Scene::Scene()
    {
#if ENTT_EXAMPLE_CODE
        entt::entity entity = m_Registry.create();
        m_Registry.emplace<TransformComponent>(entity, glm::mat4(1.0f));
        m_Registry.on_construct<TransformComponent>().connect<&OnTransformConstruct>();
        if (m_Registry.has<TransformComponent>(entity))
            TransformComponent& transform = m_Registry.get<TransformComponent>(entity);
        auto view = m_Registry.view<TransformComponent>();
        for (auto entity : view)
        {
            TransformComponent& transform = view.get<TransformComponent>(entity);
        }
        auto group = m_Registry.group<TransformComponent>(entt::get<MeshComponent>);
        for (auto entity : group)
        {
            auto& [transform, mesh] = group.get<TransformComponent, MeshComponent>(entity);
        }
#endif
    }
    Scene::~Scene()
    {
    }
    entt::entity Scene::CreateEntity()
    {
        return m_Registry.create();
    }

    //拿到组件
    void Scene::OnUpdate(Timestep ts)
    {
        //注册组件
        auto group = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
        for (auto entity : group)
        {
            //拿到对应的组件
            auto& [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
            Renderer2D::DrawQuad(transform, sprite.Color);
        }
    }
}