Example scene loading

This commit is contained in:
2024-12-02 14:53:41 -06:00
parent ac0f0e86c5
commit 2af55041c8
48 changed files with 698 additions and 38 deletions

View File

@@ -4,11 +4,13 @@
// https://opensource.org/licenses/MIT
#include "AssetManager.hpp"
#include "assert/assert.hpp"
using namespace Dawn;
void AssetManager::init() {
void AssetManager::init(const std::shared_ptr<Game> &game) {
assertNotNull(game, "Game is NULL?");
this->game = game;
}
void AssetManager::update() {
@@ -27,6 +29,22 @@ void AssetManager::update() {
}
}
void AssetManager::remove(const std::shared_ptr<AssetLoader> loader) {
auto existing = std::find(
pendingAssetLoaders.begin(), pendingAssetLoaders.end(), loader
);
if(existing != pendingAssetLoaders.end()) {
pendingAssetLoaders.erase(existing);
}
existing = std::find(
finishedAssetLoaders.begin(), finishedAssetLoaders.end(), loader
);
if(existing != finishedAssetLoaders.end()) {
finishedAssetLoaders.erase(existing);
}
}
// Disabled because it does not respect scopes
// void AssetManager::removeExisting(const std::string &filename) {
// auto existing = std::find_if(
@@ -54,6 +72,12 @@ bool_t AssetManager::isEverythingLoaded() {
return pendingAssetLoaders.size() == 0;
}
std::shared_ptr<Game> AssetManager::getGame() {
auto g = game.lock();
assertNotNull(g, "Game is NULL?");
return g;
}
AssetManager::~AssetManager() {
}

View File

@@ -8,8 +8,11 @@
#include "asset/AssetLoader.hpp"
namespace Dawn {
class Game;
class AssetManager final : public std::enable_shared_from_this<AssetManager> {
private:
std::weak_ptr<Game> game;
std::vector<std::shared_ptr<AssetLoader>> pendingAssetLoaders;
std::vector<std::shared_ptr<AssetLoader>> finishedAssetLoaders;
@@ -59,8 +62,10 @@ namespace Dawn {
public:
/**
* Initializes this asset manager so it can begin accepting assets.
*
* @param game Game context that this asset manager is attached to.
*/
void init();
void init(const std::shared_ptr<Game> &game);
/**
* Updates the asset manager.
@@ -96,6 +101,22 @@ namespace Dawn {
return loader;
}
/**
* Returns the game context that this asset manager is attached to.
*
* @return The game context.
*/
std::shared_ptr<Game> getGame();
/**
* Removes the given asset loader from the asset manager, assumes that
* nothing else needs to access it and any dangling shared_ptrs will have
* to remain in memory.
*
* @param loader The asset loader to remove.
*/
void remove(const std::shared_ptr<AssetLoader> loader);
/**
* Dispose the asset manager, and all attached assets.
*/

View File

@@ -6,9 +6,7 @@
#pragma once
#include "asset/AssetLoader.hpp"
#include "asset/AssetDataLoader.hpp"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace Dawn {
enum class JSONLoaderState {

View File

@@ -4,6 +4,11 @@
// https://opensource.org/licenses/MIT
#include "SceneLoader.hpp"
#include "game/Game.hpp"
#include "assert/assert.hpp"
#include "asset/loader/TextureLoader.hpp"
#include "scene/Scene.hpp"
#include "component/SceneComponentRegistry.hpp"
using namespace Dawn;
@@ -18,6 +23,83 @@ SceneLoader::SceneLoader(
{
}
void SceneLoader::setupDependencies() {
std::cout << "Setting up dependencies" << std::endl;
// Begin loading dependencies.
auto &data = this->jsonLoader->data;
if(data.contains("assets")) {
for(auto &asset : data["assets"].items()) {
auto &assetName = asset.key();
auto &assetData = asset.value();
assertTrue(assetData.contains("type"), "Asset missing type");
assertTrue(assetData.contains("path"), "Asset missing path");
auto type = assetData["type"].get<std::string>();
auto path = assetData["path"].get<std::string>();
std::shared_ptr<AssetLoader> loader;
if(type == "texture") {
loader = getAssetManager()->get<TextureLoader>(path);
} else if(type == "json") {
loader = getAssetManager()->get<JSONLoader>(path);
} else {
assertUnreachable("Unknown asset type: %s", type.c_str());
}
assertMapNotHasKey(
ctx.assets,
assetName,
"Asset already exists: %s", assetName.c_str()
);
ctx.assets[assetName] = loader;
}
}
this->state = SceneLoaderState::LOADING_DEPENDENCIES;
}
void SceneLoader::sceneInitializer(Scene &scene) {
std::cout << "Initializing scene" << std::endl;
auto &data = this->jsonLoader->data;
if(data.contains("items")) {
// Create the scene items
for(auto &item : data["items"].items()) {
auto &itemName = item.key();
auto &itemData = item.value();
auto sceneItem = scene.createSceneItem();
ctx.items[itemName] = sceneItem;
}
// Add components to each scene item
for(auto &item : data["items"].items()) {
auto &itemName = item.key();
auto &itemData = item.value();
auto sceneItem = ctx.items[itemName];
ctx.data = itemData;
sceneItem->load(ctx);
if(itemData.contains("components")) {
for(auto &cmpItem : itemData["components"].items()) {
auto &cmpName = cmpItem.key();
auto &cmpData = cmpItem.value();
assertTrue(cmpData.contains("type"), "Component missing type in %s", itemName.c_str());
auto cmpType = cmpData["type"].get<std::string>();
auto cmp = SceneComponentRegistry::createComponent(cmpType, sceneItem);
ctx.data = cmpData;
ctx.components[cmpName] = cmp;
cmp->load(ctx);
}
}
}
}
this->jsonLoader = nullptr;
this->state = SceneLoaderState::DONE;
getAssetManager()->remove(shared_from_this());
}
void SceneLoader::updateAsync() {
switch(this->state) {
case SceneLoaderState::INITIAL:
@@ -26,6 +108,31 @@ void SceneLoader::updateAsync() {
break;
case SceneLoaderState::LOADING_JSON:
assertNotNull(this->jsonLoader, "JSON Loader is NULL?");
if(!this->jsonLoader->loaded) return;
this->setupDependencies();
break;
case SceneLoaderState::LOADING_DEPENDENCIES:
// Check if all dependencies are loaded.
for(auto &asset : ctx.assets) {
if(!asset.second->loaded) return;
}
this->state = SceneLoaderState::DEPENDENCIES_LOADED;
break;
case SceneLoaderState::DEPENDENCIES_LOADED:
std::cout << "Deps Loaded" << std::endl;
this->loaded = true;
ctx.scene = std::make_shared<Scene>(
this->getAssetManager()->getGame(),
[this](Scene &scene) -> void {
this->sceneInitializer(scene);
}
);
this->state = SceneLoaderState::PENDING_STAGE;
this->loaded = true;
break;
default:
@@ -42,9 +149,11 @@ std::string SceneLoader::getAssetType() const {
}
std::shared_ptr<Scene> SceneLoader::getScene() {
return scene;
return ctx.scene;
}
SceneLoader::~SceneLoader() {
ctx = {};
jsonLoader = nullptr;
std::cout << "Scene Loader removed" << std::endl;
}

View File

@@ -11,14 +11,32 @@ namespace Dawn {
enum class SceneLoaderState {
INITIAL,
LOADING_JSON,
LOADING_DEPENDENCIES,
DEPENDENCIES_LOADED,
PENDING_STAGE,
DONE
};
class SceneLoader : public AssetLoader {
class SceneLoader :
public AssetLoader,
public std::enable_shared_from_this<SceneLoader>
{
protected:
SceneLoaderState state;
std::shared_ptr<JSONLoader> jsonLoader;
std::shared_ptr<Scene> scene;
struct SceneComponentLoadContext ctx;
/**
* Loads the dependencies of the scene.
*/
void setupDependencies();
/**
* Scene intializer function to stage the loaded scene.
*
* @param scene Scene that is being staged.
*/
void sceneInitializer(Scene &scene);
public:
const static std::string ASSET_TYPE;