Dawn/src/dawn/scene/SceneItem.cpp

123 lines
3.5 KiB
C++

// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "scene/SceneItem.hpp"
#include "scene/Scene.hpp"
#include "util/JSON.hpp"
#include "assert/assert.hpp"
#include "asset/loader/scene/PrefabLoader.hpp"
using namespace Dawn;
SceneItem::SceneItem(const std::weak_ptr<Scene> scene) :
scene(scene),
SceneItemTransform(),
SceneItemComponents()
{
}
std::shared_ptr<SceneItem> SceneItem::sceneItemComponentsSelf() {
return shared_from_this();
}
std::shared_ptr<Scene> SceneItem::getScene() {
auto s = scene.lock();
assertNotNull(s, "Scene has unloaded?");
return s;
}
void SceneItem::init() {
assertFlagOff(state, SceneItemState::INITIALIZED, "Already initialized.");
assertFlagOff(state, SceneItemState::DEINITIALIZED, "Already deinited.");
Flag::turnOn(state, SceneItemState::INITIALIZED);
auto sharedThis = shared_from_this();
// Loop until all components initialized...
while(true) {
// Create copy of the components, components may chose to add more
// components but those sub components will not be initialized at this time.
auto components = this->components;
for(auto &component : components) {
if(component->isInitialized()) continue;
component->init(sharedThis);
}
// If they are all initalized we are fine.
components = this->components;
bool_t allInitialized = std::all_of(
components.begin(),
components.end(),
[](auto &component) {
return component->isInitialized();
}
);
if(allInitialized) break;
}
}
void SceneItem::deinit() {
assertFlagOn(state, SceneItemState::INITIALIZED, "SceneItem not ready.");
assertFlagOff(state, SceneItemState::DEINITIALIZED, "Already deinited");
Flag::turnOn(state, SceneItemState::DEINITIALIZED);
// Create copy of the components, components may chose to add more components
// but those sub components will not be disposed at this time.
auto components = this->components;
for(auto &component : components) {
if(!component->isInitialized()) continue;
component->dispose();
}
this->components.clear();
}
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>();
}
// Transforms
if(ctx->data.contains("position")) {
this->setLocalPosition(JSON::vec3(ctx->data["position"]));
}
if(ctx->data.contains("lookAt")) {
auto &lookAt = ctx->data["lookAt"];
glm::vec3 pos = glm::vec3(3, 3, 3);
glm::vec3 look = glm::vec3(0, 0, 0);
glm::vec3 up = glm::vec3(0, 1, 0);
if(lookAt.contains("position")) pos = JSON::vec3(lookAt["position"]);
if(lookAt.contains("look")) look = JSON::vec3(lookAt["look"]);
if(lookAt.contains("up")) up = JSON::vec3(lookAt["up"]);
this->lookAt(pos, look, up);
}
if(ctx->data.contains("scale")) {
this->setLocalScale(JSON::vec3(ctx->data["scale"]));
}
}
void SceneItem::remove() {
auto scene = getScene();
if(!scene) return;
scene->removeItem(shared_from_this());
}
SceneItem::~SceneItem() {
if(Flag::isOn(state, SceneItemState::INITIALIZED)) {
assertFlagOn(state, SceneItemState::DEINITIALIZED, "Not deinited");
}
}