Skip to content

Commit

Permalink
Added ECS copy semantics.
Browse files Browse the repository at this point in the history
Added missing copy semantics for Terrain component.
  • Loading branch information
MStachowicz committed Apr 6, 2024
1 parent e1a8a6f commit 3e37619
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 4 deletions.
19 changes: 19 additions & 0 deletions source/Component/Terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@ Component::Terrain::Terrain(const glm::vec3& p_position, int p_size_x, int p_siz
, m_mesh{generate_mesh()}
{}

Component::Terrain::Terrain(const Terrain& p_other) noexcept
: m_position{p_other.m_position}
, m_size_x{p_other.m_size_x}
, m_size_z{p_other.m_size_z}
, m_scale_factor{p_other.m_scale_factor}
, m_texture{p_other.m_texture}
, m_mesh{generate_mesh()} // TODO: Implement a Data::Mesh copy.
{}
Component::Terrain& Component::Terrain::operator=(const Terrain& p_other) noexcept
{
m_position = p_other.m_position;
m_size_x = p_other.m_size_x;
m_size_z = p_other.m_size_z;
m_scale_factor = p_other.m_scale_factor;
m_texture = p_other.m_texture;
m_mesh = generate_mesh(); // TODO: Implement a Data::Mesh copy.
return *this;
}

float compute_height(float p_x, float p_z, float p_scale_factor, const siv::PerlinNoise& perlin)
{
return static_cast<float>(perlin.noise2D(p_x * p_scale_factor, p_z * p_scale_factor));
Expand Down
5 changes: 5 additions & 0 deletions source/Component/Terrain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ namespace Component
Data::Mesh m_mesh;

Terrain(const glm::vec3& p_position, int p_size_x, int p_size_z) noexcept;
// Copy constructor has to be implemented because Data::Mesh GL members are not copyable.
Terrain(const Terrain& p_other) noexcept;
// Copy assignment operator has to be implemented because Data::Mesh GL members are not copyable.
Terrain& operator=(const Terrain& p_other) noexcept;

void draw_UI(System::TextureSystem& p_texture_system);
};
} // namespace Component
7 changes: 7 additions & 0 deletions source/ECS/Component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace ECS
void (*MoveAssign)(void* p_destination_address, void* p_source_address);
// placement-new move-construct the object pointed to by p_source_address into the memory pointed to by p_destination_address.
void (*MoveConstruct)(void* p_destination_address, void* p_source_address);
// placement-new copy-construct the object pointed to by p_source_address into the memory pointed to by p_destination_address.
void (*CopyConstruct)(void* p_destination_address, const void* p_source_address);
// Serialise the object at p_address into p_out. (Optional function)
void (*Serialise)(void* p_address, std::ofstream& p_out, uint16_t p_version);
// Deserialise the object into p_destination_address from p_in. (Optional function)
Expand Down Expand Up @@ -126,6 +128,11 @@ namespace ECS
using Type = std::decay_t<ComponentType>;
new (p_destination_address) Type(std::move(*static_cast<Type*>(p_source_address)));
}}
, CopyConstruct{[](void* p_destination_address, const void* p_source_address)
{
using Type = std::decay_t<ComponentType>;
new (p_destination_address) Type(*static_cast<const Type*>(p_source_address));
}}
, Serialise{[](void* p_address, std::ofstream& p_out, uint16_t p_version)
{
using Type = std::decay_t<ComponentType>;
Expand Down
71 changes: 67 additions & 4 deletions source/ECS/Storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,73 @@ namespace ECS
LOG("[ECS][Archetype] Move assigning {} from {}", (void*)(this), (void*)(&p_other));
return *this;
}
// Copy-construct
Archetype(const Archetype& p_other)
: m_bitset{p_other.m_bitset}
, m_components{p_other.m_components}
, m_is_serialisable{p_other.m_is_serialisable}
, m_entities{p_other.m_entities}
, m_instance_size{p_other.m_instance_size}
, m_next_instance_ID{p_other.m_next_instance_ID}
, m_capacity{p_other.m_capacity}
, m_data{(std::byte*)malloc(m_instance_size * m_capacity)}
{
// Copy construct all the components from p_other into this.
if (p_other.m_data != nullptr)
{
for (ArchetypeInstanceID instance = 0; instance < m_next_instance_ID; instance++)
{
const auto instance_start = m_instance_size * instance;

// No copying archetypes
Archetype(const Archetype& p_other) = delete;
Archetype& operator=(const Archetype& p_other) = delete;
for (const auto& comp : m_components)
{
const auto address_offset = instance_start + comp.offset;
comp.type_info.CopyConstruct(&m_data[address_offset], &p_other.m_data[address_offset]);
}
}
}

LOG("[ECS][Archetype] Copy constructed {} from {}", (void*)(this), (void*)(&p_other));
}
// Copy-assign
Archetype& operator=(const Archetype& p_other)
{
if (this != &p_other)
{
if (m_data != nullptr)
{
clear();
free(m_data);
}

m_bitset = p_other.m_bitset;
m_components = p_other.m_components;
m_is_serialisable = p_other.m_is_serialisable;
m_entities = p_other.m_entities;
m_instance_size = p_other.m_instance_size;
m_next_instance_ID = p_other.m_next_instance_ID;
m_capacity = p_other.m_capacity;
m_data = (std::byte*)malloc(m_instance_size * m_capacity);

// Copy construct all the components from p_other into this.
if (p_other.m_data != nullptr)
{
for (ArchetypeInstanceID instance = 0; instance < m_next_instance_ID; instance++)
{
const auto instance_start = m_instance_size * instance;

for (const auto& comp : m_components)
{
const auto address_offset = instance_start + comp.offset;
comp.type_info.CopyConstruct(&m_data[address_offset], &p_other.m_data[address_offset]);
}
}
}
}

LOG("[ECS][Archetype] Copy assigned {} from {}", (void*)(this), (void*)(&p_other));
return *this;
}

// Search the m_components vector for the p_component_ID and return its ComponentLayout.
// Non-template version (when we know the ComponentID but not the Type).
Expand Down Expand Up @@ -450,7 +513,7 @@ namespace ECS
// Size is 0 after clear.
void clear()
{
for (size_t instance = 0; instance < m_next_instance_ID; instance++)
for (ArchetypeInstanceID instance = 0; instance < m_next_instance_ID; instance++)
{
const auto instance_start = m_instance_size * instance;

Expand Down

0 comments on commit 3e37619

Please sign in to comment.