Improved prefab loading a bit.
This commit is contained in:
@ -20,8 +20,7 @@
|
||||
"type": "RPGEntity"
|
||||
},
|
||||
"player": {
|
||||
"type": "RPGPlayer",
|
||||
"camera": "camera"
|
||||
"type": "RPGPlayer"
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,12 @@
|
||||
|
||||
"rosa": {
|
||||
"prefab": "rosa",
|
||||
"position": [ 0, 0, 0 ]
|
||||
"position": [ 0, 0, 0 ],
|
||||
"components": {
|
||||
"player": {
|
||||
"camera": "camera"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"npc": {
|
||||
|
@ -32,5 +32,8 @@ namespace Dawn {
|
||||
);
|
||||
|
||||
~LoaderForSceneItems();
|
||||
|
||||
friend class SceneLoader;
|
||||
friend class PrefabLoader;
|
||||
};
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
#include "asset/loader/TextureLoader.hpp"
|
||||
#include "scene/Scene.hpp"
|
||||
#include "component/SceneComponentRegistry.hpp"
|
||||
#include "util/JSON.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -35,6 +36,7 @@ void PrefabLoader::updateSync() {
|
||||
assertNotNull(this->jsonLoader, "JSON Loader is NULL?");
|
||||
if(!this->jsonLoader->loaded) return;
|
||||
this->state = PrefabLoaderState::LOADING_DEPENDENCIES;
|
||||
this->ctx->data = this->jsonLoader->data;
|
||||
this->setupDependencies();
|
||||
break;
|
||||
|
||||
@ -62,37 +64,6 @@ std::string PrefabLoader::getAssetType() const {
|
||||
return PrefabLoader::ASSET_TYPE;
|
||||
}
|
||||
|
||||
void PrefabLoader::stagePrefab(std::shared_ptr<SceneItem> item) {
|
||||
assertTrue(this->loaded, "Prefab not loaded");
|
||||
|
||||
// Force-set new context values
|
||||
ctx->data = this->jsonLoader->data;
|
||||
|
||||
// Load the scene item.
|
||||
item->load(ctx);
|
||||
|
||||
auto &itemData = this->jsonLoader->data;
|
||||
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",
|
||||
cmpName.c_str()
|
||||
);
|
||||
|
||||
auto cmpType = cmpData["type"].get<std::string>();
|
||||
auto cmp = SceneComponentRegistry::createComponent(
|
||||
cmpType, item
|
||||
);
|
||||
ctx->data = cmpData;
|
||||
ctx->components[cmpName] = cmp;
|
||||
cmp->load(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PrefabLoader::~PrefabLoader() {
|
||||
|
||||
}
|
@ -34,13 +34,6 @@ namespace Dawn {
|
||||
void updateAsync() override;
|
||||
std::string getAssetType() const override;
|
||||
|
||||
/**
|
||||
* Stages this prefab onto a scene item.
|
||||
*
|
||||
* @param item The scene item to stage.
|
||||
*/
|
||||
void stagePrefab(std::shared_ptr<SceneItem> item);
|
||||
|
||||
~PrefabLoader();
|
||||
};
|
||||
}
|
@ -42,7 +42,7 @@ namespace Dawn {
|
||||
auto it = assets.find(j);
|
||||
if(it == assets.end()) {
|
||||
auto parent = this->parent.lock();
|
||||
assertNotNull(parent, "Couldn't find asset.");
|
||||
assertNotNull(parent, "Couldn't find asset %s", j.c_str());
|
||||
return parent->getAsset<T>(j);
|
||||
}
|
||||
auto asset = std::dynamic_pointer_cast<T>(it->second);
|
||||
@ -80,5 +80,6 @@ namespace Dawn {
|
||||
friend class PrefabLoader;
|
||||
friend class LoaderForSceneItems;
|
||||
friend class SceneLoader;
|
||||
friend class SceneItem;
|
||||
};
|
||||
}
|
@ -7,7 +7,8 @@
|
||||
#include "game/Game.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "scene/Scene.hpp"
|
||||
#include "component/SceneComponentRegistry.hpp"
|
||||
#include "util/JSON.hpp"
|
||||
#include "PrefabLoader.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -76,29 +77,33 @@ void SceneLoader::updateSync() {
|
||||
auto &itemName = item.key();
|
||||
auto &itemData = item.value();
|
||||
auto sceneItem = ctx->items[itemName];
|
||||
sceneItem->name = 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",
|
||||
cmpName.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);
|
||||
}
|
||||
std::shared_ptr<SceneLoadContext> itemCtx;
|
||||
if(itemData.contains("prefab")) {
|
||||
auto prefabLoader = ctx->getAsset<PrefabLoader>(
|
||||
itemData["prefab"].get<std::string>()
|
||||
);
|
||||
assertNotNull(prefabLoader, "Prefab loader not found");
|
||||
assertTrue(prefabLoader->loaded, "Prefab loader not loaded");
|
||||
assertNotNull(
|
||||
prefabLoader->jsonLoader,
|
||||
"Prefab JSON loader not found"
|
||||
);
|
||||
assertTrue(
|
||||
prefabLoader->jsonLoader->loaded,
|
||||
"Prefab JSON loader not loaded"
|
||||
);
|
||||
itemCtx = prefabLoader->ctx;
|
||||
itemCtx->data = json(prefabLoader->jsonLoader->data);
|
||||
itemCtx->parent = this->ctx;
|
||||
JSON::mergeObjectsRecursive(itemCtx->data, itemData);
|
||||
} else {
|
||||
itemCtx = this->ctx;
|
||||
itemCtx->data = json(itemData);
|
||||
}
|
||||
|
||||
sceneItem->load(itemCtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "util/JSON.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "asset/loader/scene/PrefabLoader.hpp"
|
||||
#include "component/SceneComponentRegistry.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -77,13 +78,6 @@ void SceneItem::deinit() {
|
||||
}
|
||||
|
||||
void SceneItem::load(std::shared_ptr<SceneLoadContext> ctx) {
|
||||
// Load prefab first, it can be overriden by other properties.
|
||||
if(ctx->data.contains("prefab")) {
|
||||
this->name = ctx->data["prefab"].get<std::string>();
|
||||
auto prefabLoader = ctx->getAsset<PrefabLoader>(this->name);
|
||||
prefabLoader->stagePrefab(shared_from_this());
|
||||
}
|
||||
|
||||
if(ctx->data.contains("name")) {
|
||||
this->name = ctx->data["name"].get<std::string>();
|
||||
}
|
||||
@ -108,6 +102,39 @@ void SceneItem::load(std::shared_ptr<SceneLoadContext> ctx) {
|
||||
if(ctx->data.contains("scale")) {
|
||||
this->setLocalScale(JSON::vec3(ctx->data["scale"]));
|
||||
}
|
||||
|
||||
if(ctx->data.contains("components")) {
|
||||
assertTrue(
|
||||
ctx->data["components"].is_object(),
|
||||
"Components must be an object in %s",
|
||||
this->name.c_str()
|
||||
);
|
||||
|
||||
auto components = json(ctx->data["components"]);
|
||||
for(auto &cmpItem : components.items()) {
|
||||
auto &cmpName = cmpItem.key();
|
||||
auto &cmpData = cmpItem.value();
|
||||
assertTrue(
|
||||
cmpData.is_object(),
|
||||
"Component data must be an object in %s",
|
||||
cmpName.c_str()
|
||||
);
|
||||
assertTrue(
|
||||
cmpData.contains("type"),
|
||||
"Component missing type in %s",
|
||||
cmpName.c_str()
|
||||
);
|
||||
|
||||
auto cmpType = cmpData["type"].get<std::string>();
|
||||
auto component = SceneComponentRegistry::createComponent(
|
||||
cmpType, shared_from_this()
|
||||
);
|
||||
assertNotNull(component, "Component %s not found", cmpType.c_str());
|
||||
ctx->data = json(cmpData);
|
||||
ctx->components[cmpName] = component;
|
||||
component->load(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneItem::remove() {
|
||||
|
@ -77,3 +77,26 @@ struct Color JSON::color(const json &j) {
|
||||
assertUnreachable("Invalid JSON type for color");
|
||||
return COLOR_WHITE;
|
||||
}
|
||||
|
||||
void JSON::mergeObjectsRecursive(json &a, const json &b) {
|
||||
assertTrue(a.type() == json::value_t::object, "a is not an object");
|
||||
assertTrue(b.type() == json::value_t::object, "b is not an object");
|
||||
|
||||
for(auto &item : b.items()) {
|
||||
auto &key = item.key();
|
||||
auto &value = item.value();
|
||||
|
||||
if(a.contains(key)) {
|
||||
if(
|
||||
a[key].type() == json::value_t::object &&
|
||||
value.type() == json::value_t::object
|
||||
) {
|
||||
mergeObjectsRecursive(a[key], value);
|
||||
} else {
|
||||
a[key] = json(value);
|
||||
}
|
||||
} else {
|
||||
a[key] = json(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,5 +25,20 @@ namespace Dawn {
|
||||
* @return Parsed color.
|
||||
*/
|
||||
static struct Color color(const json &j);
|
||||
|
||||
/**
|
||||
* Merges all objects in the given JSON object into the first object,
|
||||
* recursively.
|
||||
*
|
||||
* e.g. if; &a is { a: { b: 1, c: 2 }, d: 3 }
|
||||
* &b is { a: { b: 4, d: 5 }, e: 4 }
|
||||
*
|
||||
* The output will become;
|
||||
* { a: { b: 4, c: 2, d: 5 }, e: 4 }
|
||||
*
|
||||
* @param a JSON object to merge into.
|
||||
* @param b JSON object to merge from.
|
||||
*/
|
||||
static void mergeObjectsRecursive(json &a, const json &b);
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user