simplified component manager, removed ref type
This commit is contained in:
@@ -106,13 +106,9 @@ CameraWindow::CameraWindow(wiGUI* gui) :GUI(gui)
|
||||
|
||||
Entity proxy = CreateEntity();
|
||||
|
||||
auto name_ref = scene.names.Create(proxy);
|
||||
auto transform_ref = scene.transforms.Create(proxy);
|
||||
auto camera_ref = scene.cameras.Create(proxy);
|
||||
|
||||
auto& name = scene.names.GetComponent(name_ref);
|
||||
auto& transform = scene.transforms.GetComponent(transform_ref);
|
||||
auto& camera = scene.cameras.GetComponent(camera_ref);
|
||||
auto& name = scene.names.Create(proxy);
|
||||
auto& transform = scene.transforms.Create(proxy);
|
||||
auto& camera = scene.cameras.Create(proxy);
|
||||
|
||||
name = "cam";
|
||||
camera = *wiRenderer::getCamera();
|
||||
@@ -166,7 +162,7 @@ void CameraWindow::SetEntity(Entity entity)
|
||||
|
||||
Scene& scene = wiRenderer::GetScene();
|
||||
|
||||
if (scene.cameras.Find(entity))
|
||||
if (scene.cameras.GetComponent(entity) != nullptr)
|
||||
{
|
||||
followCheckBox->SetEnabled(true);
|
||||
followSlider->SetEnabled(true);
|
||||
|
||||
+2
-3
@@ -1082,11 +1082,10 @@ void EditorComponent::Update(float dt)
|
||||
else
|
||||
{
|
||||
// Orbital Camera
|
||||
auto parented = scene.parents.Find(wiRenderer::getCameraID());
|
||||
|
||||
ParentComponent* parented = scene.parents.GetComponent(wiRenderer::getCameraID());
|
||||
TransformComponent* target_transform = scene.transforms.GetComponent(cameraWnd->target);
|
||||
|
||||
if (!parented)
|
||||
if (parented == nullptr)
|
||||
{
|
||||
//cam->attachTo(cameraWnd->orbitalCamTarget);
|
||||
scene.Component_Attach(wiRenderer::getCameraID(), cameraWnd->target);
|
||||
|
||||
@@ -168,16 +168,14 @@ LightWindow::LightWindow(wiGUI* gui) : GUI(gui)
|
||||
|
||||
scene.owned_entities.insert(newEntity);
|
||||
|
||||
auto ref_light = scene.lights.Create(newEntity);
|
||||
LightComponent& light = scene.lights.GetComponent(ref_light);
|
||||
LightComponent& light = scene.lights.Create(newEntity);
|
||||
light.energy = 2;
|
||||
light.range = 60;
|
||||
light.fov = XM_PIDIV4;
|
||||
light.color = XMFLOAT3(1, 1, 1);
|
||||
light.SetType(LightComponent::POINT);
|
||||
|
||||
auto ref_transform = scene.transforms.Create(newEntity);
|
||||
TransformComponent& transform = scene.transforms.GetComponent(ref_transform);
|
||||
TransformComponent& transform = scene.transforms.Create(newEntity);
|
||||
transform.Translate(XMFLOAT3(0, 3, 0));
|
||||
|
||||
scene.cullables.Create(newEntity);
|
||||
|
||||
+58
-140
@@ -27,183 +27,105 @@ namespace wiECS
|
||||
components.reserve(reservedCount);
|
||||
entities.reserve(reservedCount);
|
||||
lookup.reserve(reservedCount);
|
||||
indices.reserve(reservedCount);
|
||||
}
|
||||
|
||||
// The ref is an indirection to the components. Components will be moved around to remain compacted, but ref will always be able to reference a component.
|
||||
struct ref
|
||||
{
|
||||
size_t value = ~0;
|
||||
|
||||
inline ref operator=(ref other) { value = other.value; return *this; }
|
||||
inline bool operator==(ref other) const { return value == other.value; }
|
||||
inline bool operator!=(ref other) const { return value != other.value; }
|
||||
inline ref& operator++() { value++; return *this; }
|
||||
inline ref operator++(int v) { ref temp = *this; ++*this; return temp; }
|
||||
inline ref& operator--() { value--; return *this; }
|
||||
inline ref operator--(int v) { ref temp = *this; --*this; return temp; }
|
||||
inline operator bool() const { return value != ~0; }
|
||||
};
|
||||
|
||||
// Clear the whole container, invalidate all refs
|
||||
// Clear the whole container
|
||||
inline void Clear()
|
||||
{
|
||||
components.clear();
|
||||
entities.clear();
|
||||
lookup.clear();
|
||||
indices.clear();
|
||||
dead.clear();
|
||||
}
|
||||
|
||||
// Check if an ref is referencing a component or not (ref is safe but uses indirection):
|
||||
inline bool IsValid(ref it) const
|
||||
{
|
||||
return it.value < indices.size() && indices[it.value] < components.size();
|
||||
}
|
||||
|
||||
// Check if an ref is referencing a specific entity or not (ref is safe but uses indirection):
|
||||
inline bool IsValid(ref it, Entity entity) const
|
||||
{
|
||||
assert(entities.size() == components.size());
|
||||
return IsValid(it) && entities[indices[it.value]] == entity;
|
||||
}
|
||||
|
||||
// Create a new component and retrieve ref (ref is safe but uses indirection):
|
||||
inline ref Create(Entity entity)
|
||||
// Create a new component and retrieve a reference to it:
|
||||
inline T& Create(Entity entity)
|
||||
{
|
||||
// Only one of this component type per entity is allowed!
|
||||
assert(!IsValid(Find(entity)));
|
||||
|
||||
ref it;
|
||||
|
||||
if (dead.empty())
|
||||
{
|
||||
// There are no dead elements, so we must have the same amount of components as indices:
|
||||
assert(components.size() == indices.size());
|
||||
|
||||
// Any new component and index will just be pushed onto the end:
|
||||
it.value = components.size();
|
||||
indices.push_back(it.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have dead elements, which means components was popped, but indices only swapped, so there must be less components than indices:
|
||||
assert(components.size() < indices.size());
|
||||
|
||||
// Essentially we pop the last dead ref and update its value to the new component (that will always be pushed to the end of components):
|
||||
it = dead.back();
|
||||
dead.pop_back();
|
||||
indices[it.value] = components.size();
|
||||
}
|
||||
assert(lookup.find(entity) == lookup.end());
|
||||
|
||||
// Entity count must always be the same as the number of coponents!
|
||||
assert(entities.size() == components.size());
|
||||
assert(lookup.size() == components.size());
|
||||
|
||||
// Update the entity lookup table:
|
||||
lookup[entity] = components.size();
|
||||
|
||||
// New components are always pushed to the end:
|
||||
components.push_back(T());
|
||||
|
||||
// Also push corresponding entity:
|
||||
entities.push_back(entity);
|
||||
|
||||
// Update the entity lookup table:
|
||||
lookup[entity] = it;
|
||||
|
||||
return it;
|
||||
return components.back();
|
||||
}
|
||||
|
||||
// Remove a component of a certain entity if it exists (referencing by Entity involves multiple indirection):
|
||||
// Remove a component of a certain entity if it exists:
|
||||
inline void Remove(Entity entity)
|
||||
{
|
||||
ref it = Find(entity);
|
||||
if (IsValid(it, entity))
|
||||
{
|
||||
Remove(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a component referenced by a certain ref (ref is safe but uses indirection):
|
||||
inline void Remove(ref it)
|
||||
{
|
||||
// ref should be valid:
|
||||
assert(IsValid(it));
|
||||
|
||||
// Directly index into components and entities array:
|
||||
const size_t index = indices[it.value];
|
||||
|
||||
// Remove the corresponding entry from the lookup table:
|
||||
const Entity entity = entities[index];
|
||||
lookup.erase(entity);
|
||||
|
||||
// Swap out the dead element with the last one, and shrink the container:
|
||||
components[index] = std::move(components.back()); // try to use move instead of copy
|
||||
components.pop_back();
|
||||
entities[index] = entities.back();
|
||||
entities.pop_back();
|
||||
|
||||
// Because the last element of the container was moved to the position of the removed element, we update its ref accordingly:
|
||||
indices[components.size()] = index;
|
||||
|
||||
//The current ref is marked as dead:
|
||||
indices[it.value] = ~0;
|
||||
dead.push_back(it);
|
||||
}
|
||||
|
||||
// Swap two components' data that are referenced by refs (ref is safe but uses indirection):
|
||||
inline void Swap(ref a, ref b)
|
||||
{
|
||||
const size_t index_a = indices[a.value];
|
||||
const size_t index_b = indices[b.value];
|
||||
|
||||
const size_t index_tmp = index_a;
|
||||
const Entity entity_tmp = entities[index_a];
|
||||
const T component_tmp = std::move(components[index_a]);
|
||||
|
||||
indices[a.value] = index_b;
|
||||
entities[index_a] = entities[index_b];
|
||||
components[index_a] = std::move(components[index_b]);
|
||||
|
||||
indices[b.value] = index_tmp;
|
||||
entities[index_b] = entity_tmp;
|
||||
components[index_b] = std::move(component_tmp);
|
||||
}
|
||||
|
||||
// Find a specific component of a certain entity if exists (referencing by Entity involves multiple indirection):
|
||||
inline ref Find(Entity entity) const
|
||||
{
|
||||
auto it = lookup.find(entity);
|
||||
if (it != lookup.end())
|
||||
{
|
||||
return it->second;
|
||||
// Directly index into components and entities array:
|
||||
const size_t index = it->second;
|
||||
|
||||
// Remove the corresponding entry from the lookup table:
|
||||
const Entity entity = entities[index];
|
||||
lookup.erase(entity);
|
||||
|
||||
if (components.size() > 1)
|
||||
{
|
||||
// Swap out the dead element with the last one:
|
||||
components[index] = std::move(components.back()); // try to use move instead of copy
|
||||
entities[index] = entities.back();
|
||||
|
||||
// Update the lookup table:
|
||||
lookup[entities[index]] = index;
|
||||
}
|
||||
|
||||
// Shrink the container:
|
||||
components.pop_back();
|
||||
entities.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Swap two components' data:
|
||||
inline void Swap(Entity a, Entity b)
|
||||
{
|
||||
auto it_a = lookup.find(a);
|
||||
auto it_b = lookup.find(b);
|
||||
|
||||
if (it_a != lookup.end() && it_b != lookup.end())
|
||||
{
|
||||
const size_t index_a = it_a->second;
|
||||
const size_t index_b = it_b->second;
|
||||
|
||||
const Entity entity_tmp = entities[index_a];
|
||||
const T component_tmp = std::move(components[index_a]);
|
||||
|
||||
entities[index_a] = entities[index_b];
|
||||
components[index_a] = std::move(components[index_b]);
|
||||
|
||||
entities[index_b] = entity_tmp;
|
||||
components[index_b] = std::move(component_tmp);
|
||||
|
||||
lookup[a] = index_b;
|
||||
lookup[b] = index_a;
|
||||
}
|
||||
|
||||
return ref();
|
||||
}
|
||||
|
||||
// Retrieve a component specified by an entity (if it exists, otherwise nullptr):
|
||||
inline T* GetComponent(Entity entity)
|
||||
{
|
||||
ref it = Find(entity);
|
||||
if (IsValid(it, entity))
|
||||
auto it = lookup.find(entity);
|
||||
if (it != lookup.end())
|
||||
{
|
||||
return &components[indices[it.value]];
|
||||
return &components[it->second];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Retrieve a component specified by an ref (ref is safe but uses indirection):
|
||||
inline T& GetComponent(ref it)
|
||||
{
|
||||
assert(IsValid(it));
|
||||
return components[indices[it.value]];
|
||||
}
|
||||
// Retrieve an entity specified by an ref (ref is safe but uses indirection):
|
||||
inline Entity GetEntity(ref it) const
|
||||
{
|
||||
assert(IsValid(it));
|
||||
return entities[indices[it.value]];
|
||||
}
|
||||
|
||||
// Retrieve the number of existing entries:
|
||||
inline size_t GetCount() const { return components.size(); }
|
||||
|
||||
@@ -225,11 +147,7 @@ namespace wiECS
|
||||
// This is a linear array of entities corresponding to each alive component:
|
||||
std::vector<Entity> entities;
|
||||
// This is a lookup table for entities:
|
||||
std::unordered_map<Entity, ref> lookup;
|
||||
// This is the indirection of ref->component index:
|
||||
std::vector<size_t> indices;
|
||||
// The indices will also contain dead elements, and those are saved here:
|
||||
std::vector<ref> dead;
|
||||
std::unordered_map<Entity, size_t> lookup;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7969,7 +7969,7 @@ wiRenderer::RayIntersectWorldResult wiRenderer::RayIntersectWorld(const RAY& ray
|
||||
return result;
|
||||
}
|
||||
|
||||
ComponentManager<ModelComponent>::ref wiRenderer::LoadModel(const std::string& fileName, const XMMATRIX& transform)
|
||||
Entity wiRenderer::LoadModel(const std::string& fileName, const XMMATRIX& transform)
|
||||
{
|
||||
//Model* model = nullptr;
|
||||
|
||||
@@ -7991,7 +7991,7 @@ ComponentManager<ModelComponent>::ref wiRenderer::LoadModel(const std::string& f
|
||||
|
||||
//return model;
|
||||
|
||||
return ComponentManager<ModelComponent>::ref();
|
||||
return INVALID_ENTITY;
|
||||
}
|
||||
void wiRenderer::LoadWorldInfo(const std::string& fileName)
|
||||
{
|
||||
@@ -8072,9 +8072,8 @@ Scene& wiRenderer::GetScene()
|
||||
{
|
||||
scene = new Scene;
|
||||
|
||||
auto transform_ref = scene->transforms.Create(cameraID);
|
||||
auto camera_ref = scene->cameras.Create(cameraID);
|
||||
scene->cameras.GetComponent(camera_ref).CreatePerspective((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800);
|
||||
scene->transforms.Create(cameraID);
|
||||
scene->cameras.Create(cameraID).CreatePerspective((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800);
|
||||
}
|
||||
return *scene;
|
||||
}
|
||||
@@ -8165,7 +8164,7 @@ void wiRenderer::PutEnvProbe(const XMFLOAT3& position)
|
||||
//GetScene().GetWorldNode()->environmentProbes.push_back(probe);
|
||||
}
|
||||
|
||||
void wiRenderer::CreateImpostor(ComponentManager<MeshComponent>::ref mesh_ref, GRAPHICSTHREAD threadID)
|
||||
void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID)
|
||||
{
|
||||
//MeshComponent& mesh = GetScene().meshes.GetComponent(mesh_ref);
|
||||
|
||||
|
||||
@@ -500,12 +500,12 @@ public:
|
||||
static void SetOceanEnabled(bool enabled, const wiOceanParameter& params);
|
||||
static wiOcean* GetOcean() { return ocean; }
|
||||
|
||||
static wiECS::ComponentManager<wiSceneSystem::ModelComponent>::ref LoadModel(const std::string& fileName, const XMMATRIX& transform = XMMatrixIdentity());
|
||||
static wiECS::Entity LoadModel(const std::string& fileName, const XMMATRIX& transform = XMMatrixIdentity());
|
||||
static void LoadWorldInfo(const std::string& fileName);
|
||||
|
||||
static void PutEnvProbe(const XMFLOAT3& position);
|
||||
|
||||
static void CreateImpostor(wiECS::ComponentManager<wiSceneSystem::MeshComponent>::ref mesh_ref, GRAPHICSTHREAD threadID);
|
||||
static void CreateImpostor(wiECS::Entity, GRAPHICSTHREAD threadID);
|
||||
|
||||
static std::vector<std::pair<XMFLOAT4X4,XMFLOAT4>> renderableBoxes;
|
||||
// Add box to render in next frame
|
||||
|
||||
@@ -591,19 +591,18 @@ namespace wiSceneSystem
|
||||
{
|
||||
assert(entity != parent);
|
||||
|
||||
auto it = parents.Find(entity);
|
||||
ParentComponent* parentcomponent = parents.GetComponent(entity);
|
||||
|
||||
if (!it)
|
||||
if (parentcomponent == nullptr)
|
||||
{
|
||||
it = parents.Create(entity);
|
||||
parentcomponent = &parents.Create(entity);
|
||||
}
|
||||
|
||||
ParentComponent& parentcomponent = parents.GetComponent(it);
|
||||
TransformComponent* transformcomponent = transforms.GetComponent(parent);
|
||||
assert(transformcomponent != nullptr);
|
||||
|
||||
parentcomponent.parentID = parent;
|
||||
XMStoreFloat4x4(&parentcomponent.world_parent_bind, XMMatrixInverse(nullptr, XMLoadFloat4x4(&transformcomponent->world)));
|
||||
parentcomponent->parentID = parent;
|
||||
XMStoreFloat4x4(&parentcomponent->world_parent_bind, XMMatrixInverse(nullptr, XMLoadFloat4x4(&transformcomponent->world)));
|
||||
}
|
||||
void Scene::Component_Detach(wiECS::Entity entity)
|
||||
{
|
||||
|
||||
@@ -357,7 +357,7 @@ namespace wiSceneSystem
|
||||
|
||||
struct ArmatureComponent
|
||||
{
|
||||
std::vector<wiECS::ComponentManager<BoneComponent>::ref> boneCollection;
|
||||
std::vector<wiECS::Entity> boneCollection;
|
||||
|
||||
GFX_STRUCT ShaderBoneType
|
||||
{
|
||||
@@ -563,19 +563,7 @@ namespace wiSceneSystem
|
||||
|
||||
struct ModelComponent
|
||||
{
|
||||
|
||||
std::vector<wiECS::ComponentManager<MaterialComponent>::ref> material_refs;
|
||||
std::vector<wiECS::ComponentManager<MeshComponent>::ref> mesh_refs;
|
||||
std::vector<wiECS::ComponentManager<ObjectComponent>::ref> object_refs;
|
||||
std::vector<wiECS::ComponentManager<PhysicsComponent>::ref> physicscomponent_refs;
|
||||
std::vector<wiECS::ComponentManager<CullableComponent>::ref> cullable_refs;
|
||||
std::vector<wiECS::ComponentManager<BoneComponent>::ref> bone_refs;
|
||||
std::vector<wiECS::ComponentManager<ArmatureComponent>::ref> armature_refs;
|
||||
std::vector<wiECS::ComponentManager<LightComponent>::ref> light_refs;
|
||||
std::vector<wiECS::ComponentManager<EnvironmentProbeComponent>::ref> probe_refs;
|
||||
std::vector<wiECS::ComponentManager<ForceFieldComponent>::ref> force_refs;
|
||||
std::vector<wiECS::ComponentManager<DecalComponent>::ref> decal_refs;
|
||||
std::vector<wiECS::ComponentManager<CameraComponent>::ref> camera_refs;
|
||||
std::unordered_set<wiECS::Entity> entities;
|
||||
};
|
||||
|
||||
struct Scene
|
||||
|
||||
Reference in New Issue
Block a user