|
|
@ -16,7 +16,7 @@ |
|
|
|
namespace guecs { |
|
|
|
namespace guecs { |
|
|
|
using std::shared_ptr, std::make_shared, std::wstring, std::string; |
|
|
|
using std::shared_ptr, std::make_shared, std::wstring, std::string; |
|
|
|
|
|
|
|
|
|
|
|
using Entity = DinkyECS::Entity; |
|
|
|
using Entity = unsigned long; |
|
|
|
|
|
|
|
|
|
|
|
using EntityMap = std::unordered_map<Entity, size_t>; |
|
|
|
using EntityMap = std::unordered_map<Entity, size_t>; |
|
|
|
|
|
|
|
|
|
|
@ -140,7 +140,6 @@ namespace guecs { |
|
|
|
|
|
|
|
|
|
|
|
class UI { |
|
|
|
class UI { |
|
|
|
public: |
|
|
|
public: |
|
|
|
DinkyECS::World $world; |
|
|
|
|
|
|
|
unsigned long entity_count = 0; |
|
|
|
unsigned long entity_count = 0; |
|
|
|
std::unordered_map<std::type_index, EntityMap> $components; |
|
|
|
std::unordered_map<std::type_index, EntityMap> $components; |
|
|
|
std::unordered_map<std::type_index, std::any> $facts; |
|
|
|
std::unordered_map<std::type_index, std::any> $facts; |
|
|
@ -165,10 +164,6 @@ namespace guecs { |
|
|
|
return $parser.cells; |
|
|
|
return $parser.cells; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline DinkyECS::World& world() { |
|
|
|
|
|
|
|
return $world; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void init(); |
|
|
|
void init(); |
|
|
|
void render(sf::RenderWindow& window); |
|
|
|
void render(sf::RenderWindow& window); |
|
|
|
bool mouse(float x, float y, bool hover); |
|
|
|
bool mouse(float x, float y, bool hover); |
|
|
@ -176,60 +171,132 @@ namespace guecs { |
|
|
|
void click_on(Entity slot_id); |
|
|
|
void click_on(Entity slot_id); |
|
|
|
void debug_layout(sf::RenderWindow& window); |
|
|
|
void debug_layout(sf::RenderWindow& window); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Entity entity() { return ++entity_count; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
|
|
|
|
size_t make_component() { |
|
|
|
|
|
|
|
auto &storage = component_storage_for<Comp>(); |
|
|
|
|
|
|
|
size_t index; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!storage.free_indices.empty()) { |
|
|
|
|
|
|
|
index = storage.free_indices.front(); |
|
|
|
|
|
|
|
storage.free_indices.pop(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
storage.data.emplace_back(); |
|
|
|
|
|
|
|
index = storage.data.size() - 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return index; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Entity entity() { return $world.entity(); } |
|
|
|
template <typename Comp> |
|
|
|
|
|
|
|
ComponentStorage<Comp> &component_storage_for() { |
|
|
|
|
|
|
|
auto type_index = std::type_index(typeid(Comp)); |
|
|
|
|
|
|
|
$component_storages.try_emplace(type_index, ComponentStorage<Comp>{}); |
|
|
|
|
|
|
|
return std::any_cast<ComponentStorage<Comp> &>( |
|
|
|
|
|
|
|
$component_storages.at(type_index)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
|
|
|
|
EntityMap &entity_map_for() { |
|
|
|
|
|
|
|
return $components[std::type_index(typeid(Comp))]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
bool has_the() { |
|
|
|
bool has_the() { |
|
|
|
return $world.has_the<Comp>(); |
|
|
|
auto comp_id = std::type_index(typeid(Comp)); |
|
|
|
|
|
|
|
return $facts.contains(comp_id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
void set_the(Comp val) { |
|
|
|
void set_the(Comp val) { |
|
|
|
return $world.set_the<Comp>(val); |
|
|
|
$facts.insert_or_assign(std::type_index(typeid(Comp)), val); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
Comp &get_the() { |
|
|
|
Comp &get_the() { |
|
|
|
return $world.get_the<Comp>(); |
|
|
|
auto comp_id = std::type_index(typeid(Comp)); |
|
|
|
|
|
|
|
dbc::check($facts.contains(comp_id), |
|
|
|
|
|
|
|
fmt::format("!!!! ATTEMPT to access world fact that hasn't " |
|
|
|
|
|
|
|
"been set yet: {}", |
|
|
|
|
|
|
|
typeid(Comp).name())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// use .at to get std::out_of_range if fact not set
|
|
|
|
|
|
|
|
std::any &res = $facts.at(comp_id); |
|
|
|
|
|
|
|
return std::any_cast<Comp &>(res); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
void set(Entity ent, Comp val) { |
|
|
|
void set(Entity ent, Comp val) { |
|
|
|
$world.set<Comp>(ent, val); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(has<Comp>(ent)) { |
|
|
|
|
|
|
|
get<Comp>(ent) = val; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.insert_or_assign(ent, make_component<Comp>()); |
|
|
|
|
|
|
|
get<Comp>(ent) = val; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
Comp& get(Entity entity) { |
|
|
|
Comp& get(Entity ent) { |
|
|
|
return $world.get<Comp>(entity); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
auto &storage = component_storage_for<Comp>(); |
|
|
|
|
|
|
|
auto index = map.at(ent); |
|
|
|
|
|
|
|
return storage.data[index]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
Comp* get_if(Entity entity) { |
|
|
|
Comp* get_if(Entity entity) { |
|
|
|
return $world.get_if<Comp>(entity); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
auto &storage = component_storage_for<Comp>(); |
|
|
|
|
|
|
|
if(map.contains(entity)) { |
|
|
|
|
|
|
|
auto index = map.at(entity); |
|
|
|
|
|
|
|
return &storage.data[index]; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return nullptr; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
bool has(Entity entity) { |
|
|
|
bool has(Entity ent) { |
|
|
|
return $world.has<Comp>(entity); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
return map.contains(ent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
void remove(Entity ent) { |
|
|
|
void remove(Entity ent) { |
|
|
|
$world.remove<Comp>(ent); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(map.contains(ent)) { |
|
|
|
|
|
|
|
size_t index = map.at(ent); |
|
|
|
|
|
|
|
component_storage_for<Comp>().free_indices.push(index); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.erase(ent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
void query(std::function<void(Entity, Comp &)> cb) { |
|
|
|
void query(std::function<void(Entity, Comp &)> cb) { |
|
|
|
$world.query<Comp>(cb); |
|
|
|
EntityMap &map = entity_map_for<Comp>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &[entity, index] : map) { |
|
|
|
|
|
|
|
cb(entity, get<Comp>(entity)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename CompA, typename CompB> |
|
|
|
template <typename CompA, typename CompB> |
|
|
|
void query(std::function<void(Entity, CompA &, CompB &)> cb) { |
|
|
|
void query(std::function<void(Entity, CompA &, CompB &)> cb) { |
|
|
|
$world.query<CompA, CompB>(cb); |
|
|
|
EntityMap &map_a = entity_map_for<CompA>(); |
|
|
|
|
|
|
|
EntityMap &map_b = entity_map_for<CompB>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(auto &[entity, index_a] : map_a) { |
|
|
|
|
|
|
|
if(map_b.contains(entity)) { |
|
|
|
|
|
|
|
cb(entity, get<CompA>(entity), get<CompB>(entity)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
@ -237,23 +304,23 @@ namespace guecs { |
|
|
|
dbc::check(has<lel::Cell>(ent),"WRONG! slot is missing its cell?!"); |
|
|
|
dbc::check(has<lel::Cell>(ent),"WRONG! slot is missing its cell?!"); |
|
|
|
auto& cell = get<lel::Cell>(ent); |
|
|
|
auto& cell = get<lel::Cell>(ent); |
|
|
|
val.init(cell); |
|
|
|
val.init(cell); |
|
|
|
$world.set<Comp>(ent, val); |
|
|
|
set<Comp>(ent, val); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Comp> |
|
|
|
template <typename Comp> |
|
|
|
void do_if(Entity ent, std::function<void(Comp &)> cb) { |
|
|
|
void do_if(Entity ent, std::function<void(Comp &)> cb) { |
|
|
|
if($world.has<Comp>(ent)) { |
|
|
|
if(has<Comp>(ent)) { |
|
|
|
cb($world.get<Comp>(ent)); |
|
|
|
cb(get<Comp>(ent)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lel::Cell& cell_for(Entity ent) { |
|
|
|
lel::Cell& cell_for(Entity ent) { |
|
|
|
return $world.get<lel::Cell>(ent); |
|
|
|
return get<lel::Cell>(ent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lel::Cell& cell_for(const string& name) { |
|
|
|
lel::Cell& cell_for(const string& name) { |
|
|
|
Entity ent = entity(name); |
|
|
|
Entity ent = entity(name); |
|
|
|
return $world.get<lel::Cell>(ent); |
|
|
|
return get<lel::Cell>(ent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -270,7 +337,7 @@ namespace guecs { |
|
|
|
void render_helper(sf::RenderWindow& window, Entity ent, bool is_shape, T& target) { |
|
|
|
void render_helper(sf::RenderWindow& window, Entity ent, bool is_shape, T& target) { |
|
|
|
sf::Shader *shader_ptr = nullptr; |
|
|
|
sf::Shader *shader_ptr = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
if(auto shader = $world.get_if<Effect>(ent)) { |
|
|
|
if(auto shader = get_if<Effect>(ent)) { |
|
|
|
if(shader->$active && !is_shape) { |
|
|
|
if(shader->$active && !is_shape) { |
|
|
|
auto ptr = shader->checkout_ptr(); |
|
|
|
auto ptr = shader->checkout_ptr(); |
|
|
|
ptr->setUniform("is_shape", is_shape); |
|
|
|
ptr->setUniform("is_shape", is_shape); |
|
|
@ -289,5 +356,4 @@ namespace guecs { |
|
|
|
|
|
|
|
|
|
|
|
Clickable make_action(DinkyECS::World& target, Events::GUI event); |
|
|
|
Clickable make_action(DinkyECS::World& target, Events::GUI event); |
|
|
|
Clickable make_action(DinkyECS::World& target, Events::GUI event, std::any data); |
|
|
|
Clickable make_action(DinkyECS::World& target, Events::GUI event, std::any data); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|