Skip to content

Commit

Permalink
Scene switching entity clean up bug (#29)
Browse files Browse the repository at this point in the history
Fixing bug with scene switching where all scene nodes weren't being cleaned up.
  • Loading branch information
Chukobyte authored Jan 17, 2022
1 parent 7c4f9f2 commit 2c7d4cb
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 122 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ RELEASE_FLAGS = -DHAVE_SNPRINTF=1
BUILD_OBJECT := $(PROJECT_NAME).exe
TEST_BUILD_OBJECT := test_$(PROJECT_NAME).exe

SRC = $(wildcard src/main.cpp src/core/*.cpp src/core/math/*.cpp src/core/utils/*.cpp src/core/rendering/*.cpp src/core/rendering/shader/*.cpp src/core/input/*.cpp src/core/audio/*.cpp src/core/timer/*.cpp src/core/scripting/python/*.cpp src/core/ecs/*.cpp src/core/ecs/system/systems/*.cpp src/core/networking/*.cpp include/stb_image/*.cpp)
SRC = $(wildcard src/main.cpp src/core/*.cpp src/core/math/*.cpp src/core/utils/*.cpp src/core/rendering/*.cpp src/core/rendering/shader/*.cpp src/core/input/*.cpp src/core/audio/*.cpp src/core/timer/*.cpp src/core/scripting/python/*.cpp src/core/ecs/*.cpp src/core/ecs/system/systems/*.cpp src/core/scene/*.cpp src/core/networking/*.cpp include/stb_image/*.cpp)
SRC_C = $(wildcard lib/glad.c include/kuba_zip/zip.c)

OBJ = $(SRC:.cpp=.o)
OBJ_C = $(SRC_C:.c=.o)

TEST_SRC = $(wildcard src/test/*.cpp src/test/unit/*.cpp src/core/*.cpp src/core/math/*.cpp src/core/utils/*.cpp src/core/rendering/*.cpp src/core/rendering/shader/*.cpp src/core/input/*.cpp src/core/timer/*.cpp src/core/scripting/python/*.cpp src/core/audio/*.cpp src/core/ecs/*.cpp src/core/ecs/system/systems/*.cpp src/core/networking/*.cpp include/stb_image/*.cpp)
TEST_SRC = $(wildcard src/test/*.cpp src/test/unit/*.cpp src/core/*.cpp src/core/math/*.cpp src/core/utils/*.cpp src/core/rendering/*.cpp src/core/rendering/shader/*.cpp src/core/input/*.cpp src/core/timer/*.cpp src/core/scripting/python/*.cpp src/core/audio/*.cpp src/core/ecs/*.cpp src/core/ecs/system/systems/*.cpp src/core/scene/*.cpp src/core/networking/*.cpp include/stb_image/*.cpp)
TEST_OBJ = $(TEST_SRC:.cpp=.o)

EXPORT_PACKAGE_DIR := export_package
Expand Down
2 changes: 1 addition & 1 deletion _version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "0.50.0"
"version": "0.51.0"
}
19 changes: 10 additions & 9 deletions src/core/ecs/entity_component_orchestrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ void EntityComponentOrchestrator::NewEntity(SceneNode sceneNode) {
}
}

void EntityComponentOrchestrator::NewEntityAddChild(Entity parent, Entity child) {
SceneNode childNode = SceneNode{.entity = child, .parent = parent};
AddChildToEntityScene(childNode.parent, childNode.entity);
NodeComponent nodeComponent = componentManager->GetComponent<NodeComponent>(childNode.entity);
nodeNameToEntityMap.emplace(nodeComponent.name, childNode.entity);
entitySystemManager->OnEntityTagsUpdatedSystemsHook(child, {}, nodeComponent.tags);
CallStartOnScriptInstances(childNode);
}

void EntityComponentOrchestrator::QueueEntityForDeletion(Entity entity) {
entitiesQueuedForDeletion.emplace_back(entity);
}
Expand Down Expand Up @@ -99,6 +90,16 @@ void EntityComponentOrchestrator::AddChildToEntityScene(Entity parentEntity, Ent
sceneManager->AddChild(parentEntity, childEntity);
}

// Used when adding a new entity to a scene from scripting
void EntityComponentOrchestrator::NewEntityAddChild(Entity parent, Entity child) {
SceneNode childNode = SceneNode{.entity = child, .parent = parent};
AddChildToEntityScene(childNode.parent, childNode.entity);
NodeComponent nodeComponent = componentManager->GetComponent<NodeComponent>(childNode.entity);
nodeNameToEntityMap.emplace(nodeComponent.name, childNode.entity);
entitySystemManager->OnEntityTagsUpdatedSystemsHook(child, {}, nodeComponent.tags);
CallStartOnScriptInstances(childNode);
}

// Will be the function to initialize stuff for a scene
void EntityComponentOrchestrator::RegisterSceneNodeInstances(SceneNode sceneNode) {
AddChildToEntityScene(sceneNode.parent, sceneNode.entity);
Expand Down
1 change: 1 addition & 0 deletions src/core/scene/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define SCENE_H

#include <vector>
#include "../ecs/entity/entity.h"

struct SceneNode {
Entity entity = NULL_ENTITY;
Expand Down
119 changes: 119 additions & 0 deletions src/core/scene/scene_manager.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,120 @@
#include "scene_manager.h"

SceneManager::SceneManager(SceneContext *vSceneContext, EntityManager *vEntityManager, ComponentManager *vComponentManager, AssetManager *vAssetManager) :
sceneContext(vSceneContext), entityManager(vEntityManager), componentManager(vComponentManager), assetManager(vAssetManager) {
timerManager = TimerManager::GetInstance();
archiveLoader = ArchiveLoader::GetInstance();
sceneNodeJsonParser = SceneNodeJsonParser(entityManager, componentManager, assetManager, timerManager);
}

Scene SceneManager::GetCurrentScene() {
return currentScene;
}

SceneNode SceneManager::GetEntitySceneNode(Entity entity) {
if (!HasEntitySceneNode(entity)) {
Logger::GetInstance()->Error("Doesn't have entity " + std::to_string(entity));
}
assert(HasEntitySceneNode(entity) && "Tried to get scene node that doesn't exist!");
return entityToSceneNodeMap[entity];
}

bool SceneManager::HasEntitySceneNode(Entity entity) const {
return entityToSceneNodeMap.count(entity) > 0;
}

//void SceneManager::AddSingletonScene(Entity singletonEntity) {
// SceneNode sceneNode = SceneNode{.entity = singletonEntity};
// Scene scene = Scene{.rootNode = sceneNode};
// entityToMainScenesMap.emplace(singletonEntity, scene);
//}

void SceneManager::ChangeToScene(Scene scene) {
currentScene = scene;
sceneContext->currentSceneEntity = currentScene.rootNode.entity;
entityToMainScenesMap.emplace(currentScene.rootNode.entity, currentScene);
AddChild(NULL_ENTITY, currentScene.rootNode.entity);
}

void SceneManager::AddChild(Entity parent, Entity child) {
SceneNode childNode = SceneNode{.entity = child, .parent = parent};
if (parent != NULL_ENTITY) {
assert((entityToSceneNodeMap.count(parent) > 0) && "Parent scene node doesn't exist!");
entityToSceneNodeMap.emplace(childNode.entity, childNode);
Entity currentParent = parent;
Entity currentChild = child;
while (currentParent != NULL_ENTITY) {
entityToSceneNodeMap[currentParent].children.emplace_back(entityToSceneNodeMap[currentChild]);
if (currentParent == currentScene.rootNode.entity) {
currentScene.rootNode.children.emplace_back(childNode);
}
currentChild = entityToSceneNodeMap[currentParent].entity;
currentParent = entityToSceneNodeMap[currentParent].parent;
}
} else {
entityToSceneNodeMap.emplace(childNode.entity, childNode);
}
}

std::vector<Entity> SceneManager::GetAllChildEntities(Entity entity) {
std::vector<Entity> childrenEntities;
SceneNode parentNode = GetEntitySceneNode(entity);
for (SceneNode childNode : parentNode.children) {
if (IsEntityInScene(childNode.entity)) {
childrenEntities.emplace_back(childNode.entity);
}
}
return childrenEntities;
}

Entity SceneManager::GetParent(Entity entity) {
if (IsEntityInScene(entity)) {
SceneNode sceneNode = entityToSceneNodeMap[entity];
return sceneNode.parent;
}
return NULL_ENTITY;
}

void SceneManager::RemoveNode(SceneNode sceneNode) {
for (SceneNode childNode : sceneNode.children) {
RemoveNode(childNode);
}
entityToSceneNodeMap.erase(sceneNode.entity);
entityToMainScenesMap.erase(sceneNode.entity);
entitiesRecentlyRemoved.emplace_back(sceneNode.entity);
}

//void SceneManager::RemoveNode(Entity entity) {
// if (entityToSceneNodeMap.count(entity) > 0) {
// RemoveNode(entityToSceneNodeMap[entity]);
// } else {
// Logger::GetInstance()->Warn("Tried to remove non existent entity");
// }
//}

std::vector<Entity> SceneManager::FlushRemovedEntities() {
std::vector<Entity> removedEntitiesCopy = entitiesRecentlyRemoved;
entitiesRecentlyRemoved.clear();
return removedEntitiesCopy;
}

bool SceneManager::IsEntityInScene(Entity entity) const {
return entityToSceneNodeMap.count(entity) > 0;
}

Scene SceneManager::LoadSceneFromFile(const std::string &filePath) {
nlohmann::json sceneJson = JsonFileHelper::LoadJsonFile(filePath);
SceneNode rootNode = sceneNodeJsonParser.ParseSceneJson(sceneJson, true);
Scene loadedScene = Scene{.rootNode = rootNode};
ChangeToScene(loadedScene);
return loadedScene;
}

Scene SceneManager::LoadSceneFromMemory(const std::string &filePath) {
const std::string &sceneArchiveJsonString = archiveLoader->LoadAsString(filePath);
nlohmann::json sceneJson = JsonFileHelper::ConvertStringToJson(sceneArchiveJsonString);
SceneNode rootNode = sceneNodeJsonParser.ParseSceneJson(sceneJson, true);
Scene loadedScene = Scene{.rootNode = rootNode};
ChangeToScene(loadedScene);
return loadedScene;
}
125 changes: 15 additions & 110 deletions src/core/scene/scene_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,116 +465,21 @@ class SceneManager {
ArchiveLoader *archiveLoader = nullptr;

public:
SceneManager(SceneContext *vSceneContext, EntityManager *vEntityManager, ComponentManager *vComponentManager, AssetManager *vAssetManager) :
sceneContext(vSceneContext), entityManager(vEntityManager), componentManager(vComponentManager), assetManager(vAssetManager) {
timerManager = TimerManager::GetInstance();
archiveLoader = ArchiveLoader::GetInstance();
sceneNodeJsonParser = SceneNodeJsonParser(entityManager, componentManager, assetManager, timerManager);
}

Scene GetCurrentScene() {
return currentScene;
}

SceneNode GetEntitySceneNode(Entity entity) {
assert(HasEntitySceneNode(entity) && "Tried to get scene node that doesn't exist!");
return entityToSceneNodeMap[entity];
}

bool HasEntitySceneNode(Entity entity) {
return entityToSceneNodeMap.count(entity) > 0;
}

void AddSingletonScene(Entity singletonEntity) {
SceneNode sceneNode = SceneNode{.entity = singletonEntity};
Scene scene = Scene{.rootNode = sceneNode};
entityToMainScenesMap.emplace(singletonEntity, scene);
}

void ChangeToScene(Scene scene) {
currentScene = scene;
sceneContext->currentSceneEntity = currentScene.rootNode.entity;
entityToMainScenesMap.emplace(currentScene.rootNode.entity, currentScene);
AddChild(NULL_ENTITY, currentScene.rootNode.entity);
}

void AddChild(Entity parent, Entity child) {
SceneNode childNode = SceneNode{.entity = child, .parent = parent};
if (parent != NULL_ENTITY) {
assert((entityToSceneNodeMap.count(parent) > 0) && "Parent scene node doesn't exist!");
SceneNode parentNode = entityToSceneNodeMap[parent];
parentNode.children.emplace_back(childNode);
entityToSceneNodeMap[parent] = parentNode;
if (parentNode.entity == currentScene.rootNode.entity) {
currentScene.rootNode.children.emplace_back(childNode);
}
}
// assert((entityToSceneNodeMap.count(child) <= 0) && "Child already exists!");
entityToSceneNodeMap.emplace(childNode.entity, childNode);
}

std::vector<Entity> GetAllChildEntities(Entity entity) {
std::vector<Entity> childrenEntities;
SceneNode parentNode = GetEntitySceneNode(entity);
for (SceneNode childNode : parentNode.children) {
if (IsEntityInScene(childNode.entity)) {
childrenEntities.emplace_back(childNode.entity);
}
}
return childrenEntities;
}

Entity GetParent(Entity entity) {
if (IsEntityInScene(entity)) {
SceneNode sceneNode = entityToSceneNodeMap[entity];
return sceneNode.parent;
}
return NULL_ENTITY;
}

void RemoveNode(SceneNode sceneNode) {
entityToSceneNodeMap.erase(sceneNode.entity);
entityToMainScenesMap.erase(sceneNode.entity);
entitiesRecentlyRemoved.emplace_back(sceneNode.entity);
for (SceneNode childNode : sceneNode.children) {
RemoveNode(childNode);
}
}

void RemoveNode(Entity entity) {
if (entityToSceneNodeMap.count(entity) > 0) {
RemoveNode(entityToSceneNodeMap[entity]);
} else {
Logger::GetInstance()->Warn("Tried to remove non existent entity");
}
}

std::vector<Entity> FlushRemovedEntities() {
std::vector<Entity> removedEntitiesCopy = entitiesRecentlyRemoved;
entitiesRecentlyRemoved.clear();
return removedEntitiesCopy;
}

bool IsEntityInScene(Entity entity) {
return entityToSceneNodeMap.count(entity) > 0;
}

Scene LoadSceneFromFile(const std::string &filePath) {
nlohmann::json sceneJson = JsonFileHelper::LoadJsonFile(filePath);
SceneNode rootNode = sceneNodeJsonParser.ParseSceneJson(sceneJson, true);
Scene loadedScene = Scene{.rootNode = rootNode};
ChangeToScene(loadedScene);
return loadedScene;
}

Scene LoadSceneFromMemory(const std::string &filePath) {
const std::string &sceneArchiveJsonString = archiveLoader->LoadAsString(filePath);
nlohmann::json sceneJson = JsonFileHelper::ConvertStringToJson(sceneArchiveJsonString);
SceneNode rootNode = sceneNodeJsonParser.ParseSceneJson(sceneJson, true);
Scene loadedScene = Scene{.rootNode = rootNode};
ChangeToScene(loadedScene);
return loadedScene;
}
SceneManager(SceneContext *vSceneContext, EntityManager *vEntityManager, ComponentManager *vComponentManager, AssetManager *vAssetManager);
Scene GetCurrentScene();
SceneNode GetEntitySceneNode(Entity entity);
bool HasEntitySceneNode(Entity entity) const;
// void AddSingletonScene(Entity singletonEntity);
void ChangeToScene(Scene scene);
void AddChild(Entity parent, Entity child);
std::vector<Entity> GetAllChildEntities(Entity entity);
Entity GetParent(Entity entity);
void RemoveNode(SceneNode sceneNode);
// void RemoveNode(Entity entity);
std::vector<Entity> FlushRemovedEntities();
bool IsEntityInScene(Entity entity) const;
Scene LoadSceneFromFile(const std::string &filePath);
Scene LoadSceneFromMemory(const std::string &filePath);
};

class SceneNodeHelper {
Expand Down

0 comments on commit 2c7d4cb

Please sign in to comment.