Skip to content

Commit cc1d5a8

Browse files
committed
Game objects can now be removed from scene (complexity of O(3N)
1 parent 5079ed7 commit cc1d5a8

File tree

8 files changed

+84
-63
lines changed

8 files changed

+84
-63
lines changed

src/WaterDropEngine/WdeCore/Core/WdeInstance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ namespace wde {
6666
auto camModule = camera->addModule<scene::CameraModule>();
6767
camModule->setAsActive();
6868
camModule->setFarPlane(std::numeric_limits<float>::max());
69-
_scene->_activeCameraID = static_cast<int>(camera->getID());
69+
_scene->setActiveCamera(camera.get());
7070
camera->addModule<scene::ControllerModule>();
7171
camera->transform->position = glm::vec3 {0.0f, 0.0f, 0.0f};
7272
camera->transform->rotation = glm::vec3 {0.0f, 0.0f, 0.0f};

src/WaterDropEngine/WdeScene/GameObject.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ namespace wde::scene {
103103
ImGui::PushStyleColor(ImGuiCol_ButtonActive, gui::GUITheme::colorRedMinor);
104104
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GUITheme::colorRedMinor);
105105
if (ImGui::Button("Delete")) {
106-
// TODO
106+
WaterDropEngine::get().getInstance().getScene()->removeGameObject(this);
107107
ImGui::CloseCurrentPopup();
108108
}
109109
ImGui::PopStyleColor(3);
@@ -197,8 +197,8 @@ namespace wde::scene {
197197
bool moduleRemoved = false;
198198
if (module->getName() != "Transform" && ImGui::BeginPopupContextItem()) {
199199
if (ImGui::Button("Remove Module")) {
200-
if (module->getName() == "Camera" && WaterDropEngine::get().getInstance().getScene()->getActiveCamera().get() == this)
201-
WaterDropEngine::get().getInstance().getScene()->_activeCameraID = -1;
200+
if (module->getName() == "Camera" && WaterDropEngine::get().getInstance().getScene()->getActiveCamera() == this)
201+
WaterDropEngine::get().getInstance().getScene()->setActiveCamera(nullptr);
202202
moduleRemoved = true;
203203
ModuleSerializer::removeModuleFromName(module->getName(), *this);
204204
}

src/WaterDropEngine/WdeScene/WdeScene.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ namespace wde::scene {
123123

124124
// Load game objects
125125
uint32_t currentGOID = scene->getGameObjects().size();
126+
std::unordered_map<int, int> oldToNewIds {}; // <oldID, newID>
126127
for (const auto& goIDs : fileData["data"]["gameObjects"]) {
127128
const auto& goData = json::parse(WdeFileUtils::readFile(path + "gameObjects/go_" + std::to_string(goIDs.get<uint32_t>()) + ".json"));
128129
if (goData["type"] != "gameObject")
@@ -132,18 +133,19 @@ namespace wde::scene {
132133
auto go = scene->createGameObject(goData["name"], goData["data"]["static"].get<bool>());
133134
go->active = goData["data"]["active"].get<bool>();
134135

136+
// Add parent id to list
137+
oldToNewIds.emplace(goIDs.get<int>(), go->getID());
138+
135139
// Create game object modules
136-
for (const auto& modData : goData["modules"]) {
140+
for (const auto& modData : goData["modules"])
137141
ModuleSerializer::addModuleFromName(modData["name"], to_string(modData["data"]), *go);
138-
}
139142
}
140143

141144
// Set game object parents and children
142145
for (const auto& goIDs : fileData["data"]["gameObjects"]) {
143146
const auto& goData = json::parse(WdeFileUtils::readFile(path + "gameObjects/go_" + std::to_string(goIDs.get<uint32_t>()) + ".json"));
144-
if (goData["modules"][0]["name"] == "Transform"
145-
&& goData["modules"][0]["data"]["parentID"].get<int>() != -1) // First module should always be the transform module
146-
scene->getGameObject((int)currentGOID)->transform->setParent(scene->getGameObject(goData["modules"][0]["data"]["parentID"].get<int>())->transform);
147+
if (goData["modules"][0]["name"] == "Transform" && goData["modules"][0]["data"]["parentID"].get<int>() != -1) // First module should always be the transform module
148+
scene->getGameObjects()[(int) currentGOID]->transform->setParent(scene->getGameObjects()[oldToNewIds.at(goData["modules"][0]["data"]["parentID"].get<int>())]->transform);
147149
currentGOID++;
148150
}
149151
}

src/WaterDropEngine/WdeScene/WdeSceneInstance.cpp

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,33 @@ namespace wde::scene {
99
logger::log(LogLevel::DEBUG, LogChannel::SCENE) << "Removing deleted game objects." << logger::endl;
1010
{
1111
WDE_PROFILE_SCOPE("wde::scene::WdeSceneInstance::tick::deleteGameObjects");
12-
for (auto& go : _gameObjectsToDelete) {
13-
/*_selectedGameObjectID = -1;
14-
* TODO
12+
13+
if (!_gameObjectsToDelete.empty()) {
14+
// Remove selected and active camera
15+
for (GameObject* go : _gameObjectsToDelete) {
16+
if (_selectedGameObject == go)
17+
_selectedGameObject = nullptr;
18+
if (_activeCamera == go)
19+
_activeCamera = nullptr;
20+
}
1521

1622
// Remove from static list
17-
if (go->isStatic()) {
18-
for (auto& go : _gameObjectsStatic)
19-
_gameObjectsStatic.r
20-
}*/
23+
_gameObjectsStatic.erase(std::remove_if(_gameObjectsStatic.begin(), _gameObjectsStatic.end(), [this](const auto&x) {
24+
return std::find(_gameObjectsToDelete.begin(), _gameObjectsToDelete.end(), x.get()) != _gameObjectsToDelete.end();
25+
}), _gameObjectsStatic.end());
26+
27+
// Remove from dynamic list
28+
_gameObjectsDynamic.erase(std::remove_if(_gameObjectsDynamic.begin(), _gameObjectsDynamic.end(), [this](const auto&x) {
29+
return std::find(_gameObjectsToDelete.begin(), _gameObjectsToDelete.end(), x.get()) != _gameObjectsToDelete.end();
30+
}), _gameObjectsDynamic.end());
31+
32+
// Remove from game objects
33+
_gameObjects.erase(std::remove_if(_gameObjects.begin(), _gameObjects.end(), [this](const auto&x) {
34+
return std::find(_gameObjectsToDelete.begin(), _gameObjectsToDelete.end(), x.get()) != _gameObjectsToDelete.end();
35+
}), _gameObjects.end());
36+
37+
// Clear game objects to delete
38+
_gameObjectsToDelete.clear();
2139
}
2240
}
2341

@@ -38,6 +56,11 @@ namespace wde::scene {
3856
}
3957

4058
void WdeSceneInstance::cleanUpInstance() {
59+
// Remove references
60+
_selectedGameObject = nullptr;
61+
_activeCamera = nullptr;
62+
63+
// Remove game objects
4164
_gameObjectsDynamic.clear();
4265
_gameObjectsStatic.clear();
4366
_gameObjects.clear();
@@ -88,25 +111,24 @@ namespace wde::scene {
88111

89112
// Scene game objects
90113
ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_NoClip;
91-
static int selected = -1;
114+
GameObject* oldSelected = _selectedGameObject;
92115
if (ImGui::BeginTable("Game Objects List", 3, flags)) {
93116
// Draw game objects list
94117
for (auto& go : _gameObjects) {
95118
if (go->transform->getParent() == nullptr) {
96119
ImGui::TableNextRow();
97-
drawGUIForGo(go, &selected);
120+
drawGUIForGo(go, _selectedGameObject);
98121
}
99122
}
100123
ImGui::EndTable();
101124
}
102125

103126
// Selected game object changed
104-
if (selected != _selectedGameObjectID) {
105-
if (_selectedGameObjectID >= 0)
106-
_gameObjects[_selectedGameObjectID]->setSelected(false);
107-
_selectedGameObjectID = selected;
108-
if (_selectedGameObjectID >= 0)
109-
_gameObjects[_selectedGameObjectID]->setSelected(true);
127+
if (oldSelected != _selectedGameObject) {
128+
if (oldSelected != nullptr)
129+
oldSelected->setSelected(false);
130+
if (_selectedGameObject != nullptr)
131+
_selectedGameObject->setSelected(true);
110132
}
111133

112134
ImGui::EndChild();
@@ -120,15 +142,15 @@ namespace wde::scene {
120142
gui::GUIRenderer::popWindowTabStyle();
121143
ImGui::PushFont(ImGui::GetIO().FontDefault);
122144
ImGui::Dummy(ImVec2(0.0f, 0.15f));
123-
if (_selectedGameObjectID != -1)
124-
_gameObjects.at(_selectedGameObjectID)->drawGUI();
145+
if (_selectedGameObject != nullptr)
146+
_selectedGameObject->drawGUI();
125147
ImGui::End();
126148
ImGui::PopFont();
127149
}
128150
#endif
129151
}
130152

131-
void WdeSceneInstance::drawGUIForGo(const std::shared_ptr<GameObject> &go, int* selected) const {
153+
void WdeSceneInstance::drawGUIForGo(const std::shared_ptr<GameObject> &go, GameObject*& selected) const {
132154
#ifdef WDE_GUI_ENABLED
133155
std::string typeName;
134156
if (go->getModule<MeshRendererModule>())
@@ -173,8 +195,8 @@ namespace wde::scene {
173195
// Draw tree node
174196
ImGui::SameLine();
175197
ImGui::PushID(static_cast<int>(go->getID()) + 216846353);
176-
if (ImGui::Selectable(buf3, *selected == go->getID(), ImGuiSelectableFlags_SpanAllColumns))
177-
*selected = static_cast<int>(go->getID());
198+
if (ImGui::Selectable(buf3, selected == go.get(), ImGuiSelectableFlags_SpanAllColumns))
199+
selected = go.get();
178200
ImGui::PopID();
179201
ImGui::PopFont();
180202

@@ -210,8 +232,8 @@ namespace wde::scene {
210232

211233
ImGui::SameLine();
212234
ImGui::PushID(static_cast<int>(go->getID()) + 216846354);
213-
if (ImGui::Selectable(buf2, *selected == go->getID(), ImGuiSelectableFlags_SpanAllColumns))
214-
*selected = static_cast<int>(go->getID());
235+
if (ImGui::Selectable(buf2, selected == go.get(), ImGuiSelectableFlags_SpanAllColumns))
236+
selected = go.get();
215237
ImGui::PopID();
216238
ImGui::PopFont();
217239

src/WaterDropEngine/WdeScene/WdeSceneInstance.hpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ namespace wde::scene {
1111
*/
1212
class WdeSceneInstance : public core::Observer {
1313
public:
14-
/** Active camera ID (none = -1) */
15-
int _activeCameraID = -1;
16-
1714
// Scene engine override methods
1815
virtual void setup() {};
1916
virtual void update() {};
@@ -31,28 +28,23 @@ namespace wde::scene {
3128
const std::string& getPath() const { return _scenePath; }
3229
void setName(const std::string& name) { _sceneName = name; }
3330
const std::string& getName() const { return _sceneName; }
34-
const std::shared_ptr<GameObject>& getGameObject(int goID) { return _gameObjects[goID]; }
31+
3532
std::vector<std::shared_ptr<GameObject>>& getGameObjects() { return _gameObjects; }
3633
std::vector<std::shared_ptr<GameObject>>& getStaticGameObjects() { return _gameObjectsStatic; }
3734
std::vector<std::shared_ptr<GameObject>>& getDynamicGameObjects() { return _gameObjectsDynamic; }
38-
std::shared_ptr<GameObject> getActiveGameObject() const {
39-
if (_selectedGameObjectID == -1)
40-
return nullptr;
41-
return _gameObjects[_selectedGameObjectID];
42-
}
43-
std::shared_ptr<GameObject> getFirstGameCamera() const {
44-
for (auto& go : _gameObjects) {
35+
36+
GameObject* getActiveGameObject() const { return _selectedGameObject; }
37+
/** @return The first camera in the scene that is not the editor camera */
38+
GameObject* getFirstGameCamera() {
39+
for (auto& go : _gameObjectsDynamic) {
4540
auto mod = go->getModule<CameraModule>();
4641
if (mod != nullptr && mod->getName() != "Editor Camera")
47-
return go;
42+
return go.get();
4843
}
4944
return nullptr;
5045
}
51-
std::shared_ptr<GameObject> getActiveCamera() const {
52-
if (_activeCameraID == -1)
53-
return nullptr;
54-
return _gameObjects[_activeCameraID];
55-
}
46+
void setActiveCamera(GameObject* camera) { _activeCamera = camera; }
47+
GameObject* getActiveCamera() const { return _activeCamera; }
5648

5749

5850
/**
@@ -61,21 +53,22 @@ namespace wde::scene {
6153
* @param isStatic True if the game object is a static one (default false)
6254
*/
6355
std::shared_ptr<GameObject> createGameObject(const std::string& name, bool isStatic = false) {
64-
_gameObjects.push_back(std::make_shared<GameObject>(_gameObjectsIDCurr++, name, isStatic));
56+
auto goPtr = std::make_shared<GameObject>(_gameObjectsIDCurr++, name, isStatic);
57+
_gameObjects.push_back(goPtr);
6558
if (isStatic)
66-
_gameObjectsStatic.push_back(_gameObjects[_gameObjects.size() - 1]);
59+
_gameObjectsStatic.push_back(goPtr);
6760
else
68-
_gameObjectsDynamic.push_back(_gameObjects[_gameObjects.size() - 1]);
69-
return _gameObjects[_gameObjects.size() - 1];
61+
_gameObjectsDynamic.push_back(goPtr);
62+
return goPtr;
7063
}
7164

7265
/**
7366
* Remove a given GameObject
7467
* @param go
7568
*/
76-
void removeGameObject(GameObject& go) {
69+
void removeGameObject(GameObject* go) {
7770
// Remove GameObject
78-
_gameObjectsToDelete.push_back(&go);
71+
_gameObjectsToDelete.push_back(go);
7972
}
8073

8174

@@ -95,12 +88,16 @@ namespace wde::scene {
9588
std::string _scenePath;
9689
/** Name of the scene object */
9790
std::string _sceneName;
98-
/** Selected game object ID for GUI (default : 0) */
99-
int _selectedGameObjectID = 0;
10091
/** Last create game object ID */
10192
uint32_t _gameObjectsIDCurr = 0;
10293

94+
// Selected game objects
95+
/** Selected game object for GUI (none : nullptr) */
96+
GameObject* _selectedGameObject = nullptr;
97+
/** Active camera (none = nullptr) */
98+
GameObject* _activeCamera = nullptr;
99+
103100
// Helper functions
104-
void drawGUIForGo(const std::shared_ptr<GameObject>& go, int* selected) const;
101+
void drawGUIForGo(const std::shared_ptr<GameObject>& go, GameObject*& selected) const;
105102
};
106103
}

src/WaterDropEngine/WdeScene/culling/CullingInstance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ namespace wde::scene {
205205
_gpuRenderBatches->unmap();
206206
}
207207

208-
void CullingInstance::cull(const std::shared_ptr<GameObject> &cullingCamera) {
208+
void CullingInstance::cull(GameObject* cullingCamera) {
209209
WDE_PROFILE_FUNCTION();
210210
if (cullingCamera == nullptr)
211211
return;
@@ -278,7 +278,7 @@ namespace wde::scene {
278278

279279

280280
// Helper functions
281-
void CullingInstance::updateScene(const std::shared_ptr<GameObject> &cullingCamera) {
281+
void CullingInstance::updateScene(GameObject* cullingCamera) {
282282
WDE_PROFILE_FUNCTION();
283283
if (cullingCamera == nullptr)
284284
throw WdeException(LogChannel::SCENE, "Trying to run culling without a camera set.");

src/WaterDropEngine/WdeScene/culling/CullingInstance.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ namespace wde::scene {
7272
* Do culling based on it's batches for a specific scene camera
7373
* @param cullingCamera
7474
*/
75-
void cull(const std::shared_ptr<GameObject>& cullingCamera);
75+
void cull(GameObject* cullingCamera);
7676

7777
/**
7878
* Draws the objects in the culled buffers
@@ -111,7 +111,7 @@ namespace wde::scene {
111111

112112
// Helper functions
113113
/** Update the culling scene parameters based on the scene and on it's configured camera */
114-
void updateScene(const std::shared_ptr<GameObject>& cullingCamera);
114+
void updateScene(GameObject* cullingCamera);
115115

116116
inline static glm::vec4 normalizePlane(glm::vec4 p) {
117117
return p / glm::length(glm::vec3(p));

src/WaterDropEngine/WdeScene/modules/CameraModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ namespace wde::scene {
140140

141141
void CameraModule::drawGizmo(Gizmo& gizmo, render::CommandBuffer& commandBuffer) {
142142
// Active camera, do not draw gizmo
143-
if (WaterDropEngine::get().getInstance().getScene()->_activeCameraID == static_cast<int>(_gameObject.getID()))
143+
if (WaterDropEngine::get().getInstance().getScene()->getActiveCamera() == &_gameObject)
144144
return;
145145

146146
// Draw camera frustum gizmo
@@ -215,7 +215,7 @@ namespace wde::scene {
215215
}
216216

217217
void CameraModule::setAsActive() {
218-
WaterDropEngine::get().getInstance().getScene()->_activeCameraID = static_cast<int>(_gameObject.getID());
218+
WaterDropEngine::get().getInstance().getScene()->setActiveCamera(&_gameObject);
219219
}
220220

221221
void CameraModule::setFarPlane(float farPlane) {

0 commit comments

Comments
 (0)