VEX Engine
Retro looking game engine made in vulkan mostly because i wanted to understand it better.
Loading...
Searching...
No Matches
EditorCommands.hpp
Go to the documentation of this file.
1
6
7#pragma once
8
13#include <vector>
14#include <deque>
15#include <unordered_map>
16#include <nlohmann/json.hpp>
17
18namespace vex {
19
21 struct ICommand {
22 virtual ~ICommand() = default;
23 virtual void Execute() = 0;
24 virtual void Undo() = 0;
25 };
26
28 class TransformCommand : public ICommand {
29 vex::GameObject* m_object;
30 glm::vec3 m_oldPos, m_oldScale, m_oldRot;
31 glm::vec3 m_newPos, m_newScale, m_newRot;
32 bool m_valid;
33
34 public:
37 glm::vec3 oldP, glm::vec3 oldR, glm::vec3 oldS,
38 glm::vec3 newP, glm::vec3 newR, glm::vec3 newS)
39 : m_object(obj),
40 m_oldPos(oldP), m_oldRot(oldR), m_oldScale(oldS),
41 m_newPos(newP), m_newRot(newR), m_newScale(newS)
42 {
43 m_valid = (obj != nullptr);
44 }
45
47 void Execute() override {
48 if (!m_valid || !m_object || !m_object->HasComponent<vex::TransformComponent>()) return;
49 auto& tc = m_object->GetComponent<vex::TransformComponent>();
50 tc.setLocalPosition(m_newPos);
51 tc.rotation = m_newRot;
52 tc.setLocalScale(m_newScale);
53 tc.convertRot();
54 tc.enableLastTransformed();
55 }
56
58 void Undo() override {
59 if (!m_valid || !m_object || !m_object->HasComponent<vex::TransformComponent>()) return;
60 auto& tc = m_object->GetComponent<vex::TransformComponent>();
61 tc.setLocalPosition(m_oldPos);
62 tc.rotation = m_oldRot;
63 tc.setLocalScale(m_oldScale);
64 tc.convertRot();
65 tc.enableLastTransformed();
66 }
67 };
68
71 std::string name;
72 std::string type;
73 vex::Entity originalID;
74 vex::Entity originalParentID;
75 std::unordered_map<std::string, nlohmann::json> components;
76 };
77
79 class DeleteCommand : public ICommand {
80 vex::Engine& m_engine;
81 std::string m_sceneName;
82
83 std::vector<SerializedObject> m_serializedData;
84
85 std::vector<vex::Entity> m_runtimeIDs;
86
88 void GatherHierarchy(vex::GameObject* obj, std::vector<vex::GameObject*>& outList) {
89 if (!obj) return;
90 outList.push_back(obj);
91
92 auto& registry = m_engine.getRegistry();
93 vex::Entity parentID = obj->GetEntity();
94
96 if (tc.getParent() == parentID) {
97 auto* childObj = m_engine.getSceneManager()->GetScene(m_sceneName)->GetGameObjectByEntity(entity);
98 if (childObj) {
99 GatherHierarchy(childObj, outList);
100 }
101 }
102 });
103 }
104
105 public:
107 DeleteCommand(vex::Engine& engine, std::vector<vex::GameObject*> rootsToDelete)
108 : m_engine(engine)
109 {
110 m_sceneName = engine.getSceneManager()->getLastSceneName();
111
112 std::vector<vex::GameObject*> allObjects;
113 for (auto* root : rootsToDelete) {
114 GatherHierarchy(root, allObjects);
115 }
116
117 for (auto* obj : allObjects) {
118 SerializedObject data;
119 if (obj->HasComponent<vex::NameComponent>()) {
120 data.name = obj->GetComponent<vex::NameComponent>().name;
121 } else {
122 data.name = "Unnamed";
123 }
124 data.type = obj->getObjectType();
125 data.originalID = obj->GetEntity();
126
127 if (obj->HasComponent<vex::TransformComponent>()) {
128 data.originalParentID = obj->GetComponent<vex::TransformComponent>().getParent();
129 } else {
130 data.originalParentID = vex::NULL_ENTITY;
131 }
132
133 const auto& regNames = vex::ComponentRegistry::getInstance().getRegisteredNames();
134 for (const auto& compName : regNames) {
135 nlohmann::json json = vex::ComponentRegistry::getInstance().saveComponent(*obj, compName);
136 if (!json.is_null()) {
137 data.components[compName] = json;
138 }
139 }
140 m_serializedData.push_back(data);
141 }
142 }
143
145 void Execute() override {
146 if (m_runtimeIDs.empty()) return;
147
148 auto* scene = m_engine.getSceneManager()->GetScene(m_sceneName);
149 if (!scene) return;
150
151 m_engine.WaitForGpu();
152
153 for (vex::Entity entity : m_runtimeIDs) {
154 if (m_engine.getRegistry().has<vex::TransformComponent>(entity)) {
155 auto* obj = scene->GetGameObjectByEntity(entity);
156 if (obj) {
157 scene->DestroyGameObject(obj);
158 } else {
159 m_engine.getRegistry().destroy(entity);
160 }
161 }
162 }
163
164 m_runtimeIDs.clear();
165 m_engine.refreshForObject();
166 }
167
169 void Undo() override {
170 auto* scene = m_engine.getSceneManager()->GetScene(m_sceneName);
171 if (!scene) return;
172
173 std::unordered_map<vex::Entity, vex::Entity> oldToNewIDMap;
174 m_runtimeIDs.clear();
175
176 for (const auto& data : m_serializedData) {
177 vex::GameObject* newObj = vex::GameObjectFactory::getInstance().create(data.type, m_engine, data.name);
178 if (!newObj) continue;
179
180 for (const auto& [compName, jsonData] : data.components) {
181 vex::ComponentRegistry::getInstance().loadComponent(*newObj, compName, jsonData);
182 }
183
184 scene->AddEditorGameObject(newObj);
185
186 vex::Entity newID = newObj->GetEntity();
187 oldToNewIDMap[data.originalID] = newID;
188 m_runtimeIDs.push_back(newID);
189 }
190
191 auto& registry = m_engine.getRegistry();
192
193 for (const auto& data : m_serializedData) {
194 if (!oldToNewIDMap.contains(data.originalID)) continue;
195
196 vex::Entity newEntityID = oldToNewIDMap[data.originalID];
197
198 if (registry.has<vex::TransformComponent>(newEntityID)) {
199 auto& tc = registry.get<vex::TransformComponent>(newEntityID);
200 vex::Entity oldParent = data.originalParentID;
201
202 if (oldToNewIDMap.contains(oldParent)) {
203 tc.setParent(oldToNewIDMap[oldParent]);
204 } else {
205 tc.setParent(oldParent);
206 }
207 }
208 }
209
210 m_engine.refreshForObject();
211 }
212 };
213}
Contains basic components like transform, camera, name components..
Contains ComponentRegistry class used to have register of posible to create components....
This file defines the GameObject class.
This file defines SceneManager class.
void Execute() override
Executes the delete command.
void GatherHierarchy(vex::GameObject *obj, std::vector< vex::GameObject * > &outList)
Gather scene hierarhy for later rebuild.
void Undo() override
Undos the delete command with saved/serialized data.
DeleteCommand(vex::Engine &engine, std::vector< vex::GameObject * > rootsToDelete)
Serialized object data for deletion.
Class for interaction with engine systems.
Definition Engine.hpp:47
SceneManager * getSceneManager()
Returns pointer to SceneManager.
Definition Engine.cpp:102
GameObject * create(const std::string &type, Engine &engine, const std::string &name)
Create a GameObject instance of the specified type string.
static GameObjectFactory & getInstance()
Get the singleton instance of the GameObjectFactory.
Its base class for all game objects, eg. Player, Enemy, Weapon. Your Class needs to inherit from it.
vex::Entity GetEntity() const
Function that returns entity object, which is the entity associated with this GameObject....
void Undo() override
Undoes the transfom changes.
TransformCommand(vex::GameObject *obj, glm::vec3 oldP, glm::vec3 oldR, glm::vec3 oldS, glm::vec3 newP, glm::vec3 newR, glm::vec3 newS)
Constructor, saves old and new state.
void Execute() override
Does the transform changes.
Provides iteration over entities that have all specified component types.
Definition View.hpp:17
void each(Func func)
Iterates over all entities with the specified component types.
Definition View.hpp:40
uint32_t Entity
Type alias representing a unique entity identifier in the ECS system.
Definition Types.hpp:11
constexpr Entity NULL_ENTITY
Special entity value indicating an invalid or null entity.
Definition Types.hpp:15
Base Command Interface.
Struct that simply contains name of the entity. It is used to identify entity and needs to be unique.
Serialized object data for recreation on undo.
Struct containing transform data and methods.
void setLocalPosition(glm::vec3 newPosition)
Set the local position.
vex::Entity getParent() const
Get the parent entity.