Skip to content
Snippets Groups Projects
Commit 53e0b2f4 authored by Joseph Walton-Rivers's avatar Joseph Walton-Rivers
Browse files

allow loading of scene data from disk

parent 76f3c79b
No related branches found
No related tags found
No related merge requests found
...@@ -71,6 +71,8 @@ prefabs: ...@@ -71,6 +71,8 @@ prefabs:
type: sphere type: sphere
radius: 1 radius: 1
- name: rb_collectable - name: rb_collectable
tags:
- "collectable"
components: components:
Transform: Transform:
StaticMesh: StaticMesh:
...@@ -119,6 +121,8 @@ scene: ...@@ -119,6 +121,8 @@ scene:
- prefab: rb_collectable - prefab: rb_collectable
components: components:
Transform: Transform:
origin: [6, -0.5, 15] origin: [6, -0.5, -15]
- prefab: rb_player
name: "player"
scripts: scripts:
- "rollball.lua" - "rollball.lua"
\ No newline at end of file
...@@ -49,57 +49,12 @@ static void setup_camera(fggl::entity::EntityManager& world) { ...@@ -49,57 +49,12 @@ static void setup_camera(fggl::entity::EntityManager& world) {
} }
static fggl::entity::EntityID setup_environment(fggl::entity::EntityManager& world, fggl::entity::EntityFactory* factory, const fggl::math::vec2& size, demo::RollState& state) { static fggl::entity::EntityID setup_environment(fggl::entity::EntityManager& world, fggl::entity::EntityFactory* factory, const fggl::math::vec2& size, demo::RollState& state) {
factory->create(WallNPrefab, world, [size](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin({size.x/2, 0.0F, 0.0F});
});
factory->create(WallNPrefab, world, [size](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin({-size.x/2, 0.0F, 0.0F});
});
factory->create(WallEPrefab, world, [size](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin({0.0F, 0.0F, -size.y/2});
});
factory->create(WallEPrefab, world, [size](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin({0.0F, 0.0F, size.y/2});
});
factory->create(floorPrefab, world, [](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin({0.0F, -2.5F, 0.0F});
});
// the player requires no special setup
state.player = factory->create(playerPrefab, world);
{
// collectables
std::array<fggl::math::vec3, 3> collectPos {{
{-5.0f, -0.5f, 12.0f},
{15.0f, -0.5f, 0.5f},
{6.0f, -0.5f, -15.0f}
}};
// build the collectables
int collectCount = 0;
for (auto& pos : collectPos) {
auto collectable = factory->create(collectablePrefab, world, [pos](auto& manager, const auto& entity) {
auto& transform = manager.template get<fggl::math::Transform>(entity);
transform.origin(pos);
});
state.collectables[collectCount++] = collectable;
}
}
// ensure the state is clean // ensure the state is clean
state.closestPickup = fggl::entity::INVALID; state.closestPickup = fggl::entity::INVALID;
state.mode = demo::DebugMode::NORMAL; state.mode = demo::DebugMode::NORMAL;
state.time = 0.0F; state.time = 0.0F;
state.player = world.findByName("player");
state.collectables = world.findByTag("collectable");
return state.player; return state.player;
} }
...@@ -131,6 +86,7 @@ namespace demo { ...@@ -131,6 +86,7 @@ namespace demo {
// asset loader // asset loader
auto* assetLoader = m_owner.service<fggl::assets::Loader>(); auto* assetLoader = m_owner.service<fggl::assets::Loader>();
assetLoader->load("rollball.yml", fggl::entity::PROTOTYPE_ASSET); assetLoader->load("rollball.yml", fggl::entity::PROTOTYPE_ASSET);
assetLoader->load("rollball.yml", fggl::entity::SCENE, this);
// collectable callbacks // collectable callbacks
/*auto* collectableCallbacks = world().get<fggl::phys::CollisionCallbacks>(prefabs.collectable); /*auto* collectableCallbacks = world().get<fggl::phys::CollisionCallbacks>(prefabs.collectable);
......
...@@ -41,11 +41,7 @@ namespace demo { ...@@ -41,11 +41,7 @@ namespace demo {
fggl::entity::EntityID player = fggl::entity::INVALID; fggl::entity::EntityID player = fggl::entity::INVALID;
fggl::entity::EntityID closestPickup; fggl::entity::EntityID closestPickup;
DebugMode mode = DebugMode::NORMAL; DebugMode mode = DebugMode::NORMAL;
std::vector<fggl::entity::EntityID> collectables;
std::array<fggl::entity::EntityID, 3> collectables {
fggl::entity::INVALID,
fggl::entity::INVALID,
fggl::entity::INVALID };
float time = 0.0f; float time = 0.0f;
}; };
......
...@@ -18,9 +18,65 @@ ...@@ -18,9 +18,65 @@
#include "fggl/entity/loader/loader.hpp" #include "fggl/entity/loader/loader.hpp"
#include "fggl/debug/logging.hpp" #include "fggl/debug/logging.hpp"
#include "fggl/scenes/game.hpp"
namespace fggl::entity { namespace fggl::entity {
assets::AssetRefRaw load_scene(assets::Loader* loader, const assets::AssetGUID& asset, assets::AssetData data, void* ptr) {
auto *filePath = std::get<assets::AssetPath *>(data);
scenes::Game* gamePtr = (scenes::Game*)ptr;
// load assets
auto* entityFactory = gamePtr->owner().service<EntityFactory>();
auto nodes = YAML::LoadAllFromFile(filePath->c_str());
for (const auto& node : nodes) {
auto scene = node["scene"];
if ( !scene ) {
debug::warning("no scene node in YAML file...");
return nullptr;
}
// create and personalize
for (const auto& item : scene) {
// only safe if personalize is called BEFORE end of loop itr
auto personalize = [&entityFactory, &item, gamePtr](EntityManager& manager, const EntityID eid) {
for ( const auto& compConfig : item["components"]) {
auto compName = compConfig.first.as<fggl::util::GUID>();
auto& compInfo = entityFactory->getInfo(compName);
// setup config data
ComponentSpec spec;
spec.config = compConfig.second;
// re-run the factory with the modified arguments (might need to support a 'patch' function...)
compInfo.factory( spec, manager, eid, gamePtr->owner().services());
}
};
// finally, load the entity and trigger personalize
auto prefab = item["prefab"].as<fggl::util::GUID>();
auto entity = entityFactory->create(prefab, gamePtr->world(), personalize);
// metadata
if ( item["name"].IsDefined() ) {
gamePtr->world().setName(item["name"].as<std::string>(), entity);
}
if ( item["tags"].IsDefined() ) {
for ( auto tag : item["tags"] ) {
auto tagGuid = tag.as<fggl::util::GUID>();
gamePtr->world().addTag(entity, tagGuid);
}
}
}
}
return nullptr;
}
assets::AssetRefRaw load_prototype(assets::Loader* loader, EntityFactory *factory, const assets::AssetGUID &guid, assets::AssetData data) { assets::AssetRefRaw load_prototype(assets::Loader* loader, EntityFactory *factory, const assets::AssetGUID &guid, assets::AssetData data) {
auto *filePath = std::get<assets::AssetPath *>(data); auto *filePath = std::get<assets::AssetPath *>(data);
...@@ -48,6 +104,12 @@ namespace fggl::entity { ...@@ -48,6 +104,12 @@ namespace fggl::entity {
debug::trace("prefab {} has component {}", name, compId); debug::trace("prefab {} has component {}", name, compId);
} }
if ( prefab["tags"].IsDefined() ) {
for ( auto& tagNode : prefab["tags"] ) {
entity.tags.push_back( tagNode.as< util::GUID >() );
}
}
factory->define(name, entity); factory->define(name, entity);
} }
} }
......
...@@ -18,11 +18,14 @@ ...@@ -18,11 +18,14 @@
#include "fggl/entity/module.hpp" #include "fggl/entity/module.hpp"
#include "fggl/math/types.hpp" #include "fggl/math/types.hpp"
#include "fggl/scenes/game.hpp"
namespace fggl::entity { namespace fggl::entity {
void make_transform(const entity::ComponentSpec &spec, EntityManager &manager, const entity::EntityID entity, modules::Services &/*svc*/) { void make_transform(const entity::ComponentSpec &spec, EntityManager &manager, const entity::EntityID entity, modules::Services &/*svc*/) {
auto &transform = manager.add<math::Transform>(entity); auto &transform = manager.add<math::Transform>(entity);
//FIXME won't work for patching!
transform.origin(spec.get<math::vec3>("origin", math::VEC3_ZERO)); transform.origin(spec.get<math::vec3>("origin", math::VEC3_ZERO));
transform.euler(spec.get<math::vec3>("rotation", math::VEC3_ZERO)); transform.euler(spec.get<math::vec3>("rotation", math::VEC3_ZERO));
transform.scale(spec.get<math::vec3>("scale", math::VEC3_ONES)); transform.scale(spec.get<math::vec3>("scale", math::VEC3_ONES));
...@@ -41,9 +44,10 @@ namespace fggl::entity { ...@@ -41,9 +44,10 @@ namespace fggl::entity {
// we are responsible for prefabs... // we are responsible for prefabs...
auto *assetLoader = services.get<assets::Loader>(); auto *assetLoader = services.get<assets::Loader>();
assetLoader->setFactory(PROTOTYPE_ASSET, [factory](assets::Loader* loader, const assets::AssetGUID &a, assets::AssetData b) { assetLoader->setFactory(PROTOTYPE_ASSET, [factory](assets::Loader* loader, const assets::AssetGUID &a, assets::AssetData b, void* ptr) {
return load_prototype(loader, factory, a, b); return load_prototype(loader, factory, a, b);
}, assets::LoadType::PATH); }, assets::LoadType::PATH);
assetLoader->setFactory(SCENE, load_scene, assets::LoadType::PATH);
return true; return true;
} }
......
...@@ -76,6 +76,10 @@ namespace fggl { ...@@ -76,6 +76,10 @@ namespace fggl {
virtual void deactivate() {} virtual void deactivate() {}
inline App& owner() {
return m_owner;
}
protected: protected:
App &m_owner; App &m_owner;
}; };
...@@ -128,6 +132,10 @@ namespace fggl { ...@@ -128,6 +132,10 @@ namespace fggl {
} }
} }
inline modules::Services& services() {
return m_subsystems->services();
}
inline bool running() const { inline bool running() const {
return m_running; return m_running;
} }
......
...@@ -68,21 +68,28 @@ namespace fggl::assets { ...@@ -68,21 +68,28 @@ namespace fggl::assets {
m_requests.push(ResourceRequest{guid, type}); m_requests.push(ResourceRequest{guid, type});
} }
void load(const AssetGUID &guid, const AssetType &type) { void load(const AssetGUID &guid, const AssetType &type, void* userPtr = nullptr) {
auto path = m_storage->resolvePath(data::StorageType::Data, guid); auto path = m_storage->resolvePath(data::StorageType::Data, guid);
auto &config = m_factories.at(type); auto factoryItr = m_factories.find(type);
switch (config.second) { if ( factoryItr == m_factories.end() ) {
case LoadType::DIRECT: debug::error("attempted to load asset with unknown type: {}", type.get());
// TODO we load the data into main memory and give a pointer to it. return;
debug::log(debug::Level::error, "Tried to load direct asset - no one wrote that yet!"); }
break;
case LoadType::STAGED: const auto& [callback, callbackType] = factoryItr->second;
// TODO we load the data into temp memory and give a pointer to it. switch (callbackType) {
debug::log(debug::Level::error, "Tried to load staged asset - no one wrote that yet!"); case LoadType::DIRECT:
break; // TODO we load the data into main memory and give a pointer to it.
case LoadType::PATH: config.first(this, guid, AssetData(&path)); debug::log(debug::Level::error, "Tried to load direct asset - no one wrote that yet!");
break; break;
case LoadType::STAGED:
// TODO we load the data into temp memory and give a pointer to it.
debug::log(debug::Level::error, "Tried to load staged asset - no one wrote that yet!");
break;
case LoadType::PATH:
callback(this, guid, AssetData(&path), userPtr);
break;
} }
} }
......
...@@ -48,7 +48,7 @@ namespace fggl::assets { ...@@ -48,7 +48,7 @@ namespace fggl::assets {
class Loader; class Loader;
using AssetData = std::variant<MemoryBlock, AssetPath *, FILE *>; using AssetData = std::variant<MemoryBlock, AssetPath *, FILE *>;
using Checkin = std::function<AssetRefRaw(Loader* loader, const AssetGUID &, const AssetData &)>; using Checkin = std::function<AssetRefRaw(Loader* loader, const AssetGUID &, const AssetData &, void* userPtr)>;
} }
#endif //FGGL_ASSETS_TYPES_HPP #endif //FGGL_ASSETS_TYPES_HPP
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define FGGL_ENTITY_ENTITY_HPP #define FGGL_ENTITY_ENTITY_HPP
#include <cstdint> #include <cstdint>
#include <map>
#include <vector>
#include "fggl/debug/logging.hpp" #include "fggl/debug/logging.hpp"
#include "fggl/vendor/entt.hpp" #include "fggl/vendor/entt.hpp"
...@@ -41,7 +43,7 @@ namespace fggl::entity { ...@@ -41,7 +43,7 @@ namespace fggl::entity {
template<typename Component, typename... Args> template<typename Component, typename... Args>
inline Component &add(EntityID entity, Args &&... args) { inline Component &add(EntityID entity, Args &&... args) {
return m_registry.emplace<Component>(entity, std::forward<Args>(args)...); return m_registry.get_or_emplace<Component>(entity, std::forward<Args>(args)...);
} }
template<typename Component> template<typename Component>
...@@ -75,21 +77,74 @@ namespace fggl::entity { ...@@ -75,21 +77,74 @@ namespace fggl::entity {
return m_registry.view<Components...>(); return m_registry.view<Components...>();
} }
EntityID findByName(const std::string& name) const {
auto itr = m_names.find(name);
if ( itr == m_names.end() ){
return INVALID;
}
return m_registry.valid(itr->second) ? itr->second : INVALID;
}
inline void setName(const std::string& name, EntityID eid ) {
if ( eid == INVALID ) {
m_names.erase(name);
} else {
assert(m_registry.valid(eid));
m_names[name] = eid;
}
}
template<typename ...Components> template<typename ...Components>
bool has(EntityID idx) const { bool has(EntityID idx) const {
return m_registry.template all_of<Components...>(idx); return m_registry.template all_of<Components...>(idx);
} }
inline bool exists(EntityID idx) { bool hasTag(EntityID entity, fggl::util::GUID tag) {
const auto mapItr = m_tags.find( tag );
if ( mapItr == m_tags.end() || !m_registry.valid(entity) ) {
return false;
}
return std::find(mapItr->second.begin(), mapItr->second.end(), entity) != mapItr->second.end();
}
void addTag(const EntityID entity, const fggl::util::GUID tag) {
assert( m_registry.valid(entity) );
auto& tagged = m_tags[ tag ];
tagged.push_back( entity );
}
void removeTag(const EntityID entity, const fggl::util::GUID tag) {
auto mapItr = m_tags.find(tag);
if ( mapItr == m_tags.end() ) {
return;
}
std::remove_if( mapItr->second.begin(), mapItr->second.end(), [entity](auto other) { return other == entity;} );
}
inline std::vector<EntityID> findByTag(const char* tag) {
return findByTag( util::make_guid_rt(tag) );
}
std::vector<EntityID> findByTag(const fggl::util::GUID tag){
auto mapItr = m_tags.find(tag);
if ( mapItr == m_tags.end() ) {
return {};
}
return mapItr->second;
}
inline bool exists(EntityID idx) const {
return m_registry.valid(idx); return m_registry.valid(idx);
} }
inline bool alive(EntityID idx) { inline bool alive(EntityID idx) const {
return m_registry.valid(idx); return m_registry.valid(idx);
} }
private: private:
entt::registry m_registry; entt::registry m_registry;
std::map<std::string, EntityID> m_names;
std::map<fggl::util::GUID, std::vector<EntityID>> m_tags;
}; };
struct Entity { struct Entity {
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
namespace fggl::entity { namespace fggl::entity {
constexpr auto PROTOTYPE_ASSET = assets::AssetType::make("entity_prototype"); constexpr auto PROTOTYPE_ASSET = assets::AssetType::make("entity_prototype");
constexpr auto SCENE = assets::AssetType::make("entity_scene");
using FactoryFunc = std::function<void(const ComponentSpec &config, EntityManager &, const EntityID &, modules::Services &svc)>; using FactoryFunc = std::function<void(const ComponentSpec &config, EntityManager &, const EntityID &, modules::Services &svc)>;
using CustomiseFunc = std::function<void(EntityManager &, const EntityID &)>; using CustomiseFunc = std::function<void(EntityManager &, const EntityID &)>;
...@@ -66,12 +68,22 @@ namespace fggl::entity { ...@@ -66,12 +68,22 @@ namespace fggl::entity {
finisher( manager, entity ); finisher( manager, entity );
} }
// use metadata to finalise
processTags(manager, entity, spec);
return entity; return entity;
} }
void processTags(EntityManager& manager, EntityID id, EntityType spec) {
auto type = m_prototypes.at(spec);
for ( auto& tag : type.tags ) {
manager.addTag(id, tag);
}
}
void log_known_types() const { void log_known_types() const {
debug::debug("dumping known types:"); debug::debug("dumping known types:");
for(auto& [k,v] : m_factories) { for(const auto& [k,v] : m_factories) {
debug::debug("\ttype: {}", k); debug::debug("\ttype: {}", k);
} }
} }
...@@ -90,6 +102,10 @@ namespace fggl::entity { ...@@ -90,6 +102,10 @@ namespace fggl::entity {
m_factories.erase(configNode); m_factories.erase(configNode);
} }
inline FactoryInfo& getInfo(ComponentID comp) {
return m_factories.at(comp);
}
private: private:
modules::Services m_services; modules::Services m_services;
std::map<ComponentID, FactoryInfo> m_factories; std::map<ComponentID, FactoryInfo> m_factories;
...@@ -158,6 +174,7 @@ namespace fggl::entity { ...@@ -158,6 +174,7 @@ namespace fggl::entity {
}; };
assets::AssetRefRaw load_prototype(assets::Loader* loader, EntityFactory *factory, const assets::AssetGUID &guid, assets::AssetData data); assets::AssetRefRaw load_prototype(assets::Loader* loader, EntityFactory *factory, const assets::AssetGUID &guid, assets::AssetData data);
assets::AssetRefRaw load_scene(assets::Loader* loader, const assets::AssetGUID& asset, assets::AssetData data, void* ptr);
} // namespace fggl::entity } // namespace fggl::entity
......
...@@ -51,6 +51,7 @@ namespace fggl::entity { ...@@ -51,6 +51,7 @@ namespace fggl::entity {
struct EntitySpec { struct EntitySpec {
EntityType parent = NO_PARENT; EntityType parent = NO_PARENT;
std::vector<util::GUID> tags;
std::vector<ComponentID> ordering; std::vector<ComponentID> ordering;
std::map<ComponentID, ComponentSpec> components; std::map<ComponentID, ComponentSpec> components;
......
...@@ -235,6 +235,10 @@ namespace fggl::modules { ...@@ -235,6 +235,10 @@ namespace fggl::modules {
m_locked = true; m_locked = true;
} }
inline Services& services() {
return m_services;
}
private: private:
bool m_locked = false; bool m_locked = false;
Services m_services; Services m_services;
......
...@@ -58,11 +58,12 @@ namespace fggl::scenes { ...@@ -58,11 +58,12 @@ namespace fggl::scenes {
void update(float dt) override; void update(float dt) override;
void render(fggl::gfx::Graphics &gfx) override; void render(fggl::gfx::Graphics &gfx) override;
protected:
inline auto world() -> entity::EntityManager & { inline auto world() -> entity::EntityManager & {
return *m_world; return *m_world;
} }
protected:
bool hasPhys() const { bool hasPhys() const {
return m_phys != nullptr; return m_phys != nullptr;
} }
......
...@@ -77,14 +77,18 @@ namespace fggl::util { ...@@ -77,14 +77,18 @@ namespace fggl::util {
return GUID(hash_fnv1a_64(str)); return GUID(hash_fnv1a_64(str));
} }
inline GUID make_guid_rt(const std::string &str) { inline GUID make_guid_rt(const char* str) {
#ifndef NDEBUG #ifndef NDEBUG
return internString(str.c_str()); return internString(str);
#else #else
return make_guid(str.c_str()); return make_guid(str);
#endif #endif
} }
inline GUID make_guid_rt(const std::string &str) {
return make_guid_rt(str.c_str());
}
} // namespace fggl::util } // namespace fggl::util
// formatter // formatter
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment