VEX Engine
Retro looking game engine made in vulkan mostly because i wanted to understand it better.
Loading...
Searching...
No Matches
SceneManager.cpp
4#include "components/GameComponents/CharacterComponent.hpp"
6#include "components/GameComponents/EngineUtility.hpp"
7#include "components/GameComponents/UtilityComponents.hpp"
16#include "components/Environment.hpp"
18#include "backends/vulkan/MeshManager.hpp"
20#include <memory>
21#include <nlohmann/json.hpp>
22#include <cstdint>
23#include <fstream>
24#include <filesystem>
25
26namespace vex {
27
28 void to_json(nlohmann::json& j, const TransformComponent& t) {
29 j = nlohmann::json{
30 {"position", t.getLocalPosition()},
31 {"rotation", t.getLocalRotation()},
32 {"scale", t.getLocalScale()}
33 };
34 }
35
36 void from_json(const nlohmann::json& j, TransformComponent& t) {
37 if(j.contains("position")) t.setLocalPosition(j["position"]);
38 if(j.contains("rotation")) t.setLocalRotation(j["rotation"]);
39 if(j.contains("scale")) t.setLocalScale(j["scale"]);
40 }
41
42
43 void to_json(nlohmann::json& j, const MeshComponent& m) {
44 j["path"] = m.meshData.meshPath;
45 j["renderType"] = (int)m.renderType;
46 j["color"] = m.color;
47 j["textureOverrides"] = m.textureOverrides;
48 }
49
50 void from_json(const nlohmann::json& j, MeshComponent& m) {
51 if (j.contains("path")) {
52 std::string path = j["path"];
53 m.meshData.meshPath = path;
54 }
55 if (j.contains("renderType")) m.renderType = (RenderType)j["renderType"];
56 if (j.contains("color")) m.color = j["color"];
57 if (j.contains("textureOverrides")) m.textureOverrides = j["textureOverrides"];
58 }
59
60
61 //REGISTER_COMPONENT(MeshComponent, meshData, renderType, color);
62
63 #if DEBUG
64 template<>
65 void vex::GenericComponentInspector<vex::PhysicsComponent>(GameObject& obj) {
66 std::string name = typeid(vex::PhysicsComponent).name();
67 size_t lastColon = name.rfind("::");
68 size_t lastBracket = name.find(']');
69 std::string extracted = (lastColon != std::string::npos)
70 ? name.substr(lastColon + 2, (lastBracket != std::string::npos ? lastBracket : name.length()) - (lastColon + 2))
71 : name;
72
73 ImGui::PushID(name.c_str());
74 if (obj.HasComponent<vex::PhysicsComponent>()) {
75 if (ImGui::CollapsingHeader("PhysicsComponent", ImGuiTreeNodeFlags_DefaultOpen)) {
76 auto& pc = obj.GetComponent<vex::PhysicsComponent>();
77 bool changed = false;
78
79 if (ImReflect::Input("Shape", pc.shape).get<vex::ShapeType>().is_changed()) changed = true;
80
81 if (pc.shape == ShapeType::BOX){
82 changed |= ImGui::DragFloat3("Extents", &pc.boxHalfExtents.x);
83 } else if (pc.shape == ShapeType::ROUNDED_BOX){
84 changed |= ImGui::DragFloat3("Extents", &pc.boxHalfExtents.x);
85 changed |= ImGui::DragFloat("Radius", &pc.roundedRadius);
86 } else if (pc.shape == ShapeType::SPHERE) {
87 changed |= ImGui::DragFloat("Radius", &pc.sphereRadius);
88 } else if (pc.shape == ShapeType::CAPSULE){
89 changed |= ImGui::DragFloat2("Radius", &pc.capsuleRadius);
90 changed |= ImGui::DragFloat2("Height", &pc.capsuleHeight);
91 } else if (pc.shape == ShapeType::CYLINDER){
92 changed |= ImGui::DragFloat2("Radius", &pc.cylinderRadius);
93 changed |= ImGui::DragFloat2("Height", &pc.cylinderHeight);
94 }
95
96 if (ImReflect::Input("BodyType", pc.bodyType).get<vex::BodyType>().is_changed()) changed = true;
97 if (ImReflect::Input("Mass", pc.mass).get<float>().is_changed()) changed = true;
98 if (ImReflect::Input("Friction", pc.friction).get<float>().is_changed()) changed = true;
99 if (ImReflect::Input("Bounciness", pc.bounce).get<float>().is_changed()) changed = true;
100 if (ImReflect::Input("Linear Damping", pc.linearDamping).get<float>().is_changed()) changed = true;
101 if (ImReflect::Input("Angular Damping", pc.angularDamping).get<float>().is_changed()) changed = true;
102 if (ImReflect::Input("Sensor", pc.isSensor).get<bool>().is_changed()) changed = true;
103 if (ImReflect::Input("Allow Sleeping", pc.allowSleeping).get<bool>().is_changed()) changed = true;
104 if (ImReflect::Input("Draw Debug", pc.debugDraw).get<bool>().is_changed()) changed = true;
105
106 pc.updated = changed;
107
108 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.47f, 0.05f, 0.05f, 1.0f));
109 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.71f, 0.10f, 0.10f, 1.0f));
110 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.30f, 0.03f, 0.03f, 1.0f));
111 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.94f, 0.85f, 0.85f, 1.0f)); // White Text
112
113 if (ImGui::Button("Remove")) {
114 obj.GetEngine().getRegistry().remove<vex::PhysicsComponent>(obj.GetEntity());
115 }
116
117 ImGui::PopStyleColor(4);
118 }
119 }
120 ImGui::PopID();
121 }
122 #endif
123
124
125
126 #if DEBUG
127 template<>
128 void vex::GenericComponentInspector<vex::TransformComponent>(GameObject& obj) {
129 std::string name = typeid(vex::TransformComponent).name();
130 size_t lastColon = name.rfind("::");
131 size_t lastBracket = name.find(']');
132 std::string extracted = (lastColon != std::string::npos)
133 ? name.substr(lastColon + 2, (lastBracket != std::string::npos ? lastBracket : name.length()) - (lastColon + 2))
134 : name;
135
136 ImGui::PushID(name.c_str());
137 if (obj.HasComponent<vex::TransformComponent>()) {
138 if (ImGui::CollapsingHeader("TransformComponent", ImGuiTreeNodeFlags_DefaultOpen)) {
139 auto& tc = obj.GetComponent<vex::TransformComponent>();
140
141 if(( tc.rotation.x == 0 && tc.rotation.y == 0 && tc.rotation.z == 0 )&& (tc.getLocalRotation().x != 0 || tc.getLocalRotation().y != 0 || tc.getLocalRotation().z != 0)){
142 tc.rotation = tc.getLocalRotation();
143 }
144
145 ImGui::DragFloat3("Position", &tc.position.x);
146 ImGui::DragFloat3("Rotation", &tc.rotation.x);
147 ImGui::DragFloat3("Scale", &tc.scale.x);
148
149 tc.convertRot();
150
151 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.47f, 0.05f, 0.05f, 1.0f));
152 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.71f, 0.10f, 0.10f, 1.0f));
153 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.30f, 0.03f, 0.03f, 1.0f));
154 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.94f, 0.85f, 0.85f, 1.0f));
155
156 if (ImGui::Button("Remove")) {
157 obj.GetEngine().getRegistry().remove<vex::PhysicsComponent>(obj.GetEntity());
158 }
159
160 ImGui::PopStyleColor(4);
161 }
162 }
163 ImGui::PopID();
164 }
165 #endif
166}
167
168
169REGISTER_COMPONENT_CUSTOM(vex::TransformComponent, position, rotation, scale);
170REGISTER_COMPONENT_CUSTOM(vex::MeshComponent, meshData, renderType, color, textureOverrides);
171
172REGISTER_COMPONENT(vex::CameraComponent, fov, nearPlane, farPlane);
173REGISTER_COMPONENT(vex::LightComponent, color, intensity, radius);
174REGISTER_COMPONENT(vex::FogComponent, color, density, start, end);
175REGISTER_COMPONENT(vex::CharacterComponent, standingHeight, standingRadius, mass, maxSlopeAngle);
176REGISTER_COMPONENT(vex::AudioSourceComponent, audioFilePath, loop, is3D, autoPlay, volume, pitch, distance);
177
179REGISTER_COMPONENT(vex::OscillatorComponent, axis, amplitude, frequency, timeOffset);
180REGISTER_COMPONENT(vex::TweenComponent, targetLocalOffset, duration, pingPong);
181REGISTER_COMPONENT(vex::BillboardComponent, texturePath, size, color, isTransparent, isUnlit);
182REGISTER_COMPONENT(vex::ParticleEmitterComponent, texturePath, isTransparent, isUnlit, active, spawnRate, spawnTimer, gravity, initialVelocity, velocityVariation, particleLife, particleLifeVariation, startSize, endSize, startColor, endColor);
183
184//REGISTER_COMPONENT(vex::PhysicsComponent, shape, mass, friction, bounce, linearDamping, angularDamping, allowSleeping);
185
187 shape,
188 bodyType,
189 isSensor,
190 allowSleeping,
191 debugDraw,
192
193 mass,
194 friction,
195 bounce,
196 linearDamping,
197 angularDamping,
198
199 boxHalfExtents,
200 roundedRadius,
201 sphereRadius,
202 capsuleRadius,
203 capsuleHeight,
204 cylinderRadius,
205 cylinderHeight
206);
207
208namespace vex {
209
215
216 void SceneManager::loadScene(const std::string& path, Engine& engine) {
217 if (m_isUpdating) {
218 m_pendingActions.push_back([this, path, &engine]() {
219 clearScenes(engine);
220 loadSceneWithoutClearing(path, engine);
221 });
222 return;
223 }
224
225 clearScenes(engine);
226 loadSceneWithoutClearing(path, engine);
227 }
228
229void SceneManager::unloadScene(const std::string& path) {
230 m_scenes.erase(path);
231}
232
233void SceneManager::loadSceneWithoutClearing(const std::string& path, Engine& engine) {
234 lastSceneName = path;
235 m_scenes.emplace(path, std::make_shared<Scene>(path, engine));
236 m_scenes[path]->sceneBegin();
237}
238
241 m_scenes.clear();
242
243 auto& registry = engine.getRegistry();
244 std::vector<vex::Entity> toDestroy;
245
246 vex::View<NameComponent>(registry).each([&](vex::Entity entity, NameComponent& comp) {
247 if (!registry.has<PersistentTag>(entity)) {
248 toDestroy.push_back(entity);
249 }
250 });
251
252 for (auto entity : toDestroy) {
253 registry.destroy(entity);
254 }
255
257}
258
259void SceneManager::scenesUpdate(float deltaTime){
260 m_isUpdating = true;
261 for (auto& scene : m_scenes) {
262 scene.second->sceneUpdate(deltaTime);
263 }
264 m_isUpdating = false;
265
266 if (!m_pendingActions.empty()) {
267 for (auto& action : m_pendingActions) {
268 action();
269 }
270 m_pendingActions.clear();
271 }
272}
273
274std::vector<std::string> SceneManager::GetAllSceneNames() const {
275 std::vector<std::string> names;
276 names.reserve(m_scenes.size());
277
278 for (const auto& [name, scene] : m_scenes) {
279 names.push_back(name);
280 }
281
282 return names;
283}
284}
Defines the AudioSourceComponent struct.
Contains basic components like transform, camera, name components..
Simple 2D quad rendered in 3d space, great for placeholders or visualising invisible objects.
This file defines in engine CameraObject class.
Contains ComponentRegistry class used to have register of posible to create components....
#define REGISTER_COMPONENT_CUSTOM(Type,...)
Same macro just skips json registration for more complex components, it requires manual registration.
#define REGISTER_COMPONENT(Type,...)
Macro used to register GameComponents in ComponentRegistry. It allows to add component from scene fil...
This file defines in engine FogObject class.
This file defines GameObjectFactory class used to auto register GameObjects.
#define REGISTER_GAME_OBJECT(ClassName)
Macro for automatic GameObject registration, you should call it at the bottom of your class implement...
This file defines interface Class for vulkan backend.
This file defines in engine LightObject class.
This file defines functions for creating model objects and mesh components.
Particle emitter component.
This file defines PhysicsSystem class.
This file defines SceneManager class.
This file defines VirtualFileSystem and VPKStream classes.
Basic camera object class. it only contains transform and camera components.
Class for interaction with engine systems.
Definition Engine.hpp:47
Interface * getInterface()
Returns Interface, used internally.
Definition Engine.cpp:106
vex::Registry & getRegistry()
Returns a reference to vex::Registry.
Definition Engine.hpp:147
premade FogObject class.
Definition FogObject.hpp:13
Its base class for all game objects, eg. Player, Enemy, Weapon. Your Class needs to inherit from it.
void WaitForGPUToFinish()
Helper function to wait for GPU to finish.
MeshManager & getMeshManager()
Getter for MeshManager.
Definition Interface.hpp:71
premade LightObject class.
void clearState()
Clears the state of the mesh manager, resetting model IDs and clearing the mesh map.
ModelObject class represents a model object in the engine. Thanks to engine separation from the backe...
void unloadScene(const std::string &path)
Unloads a specific scene from memory.
void loadScene(const std::string &path, Engine &engine)
Unloads all current scenes and loads a new one from a file.
void loadSceneWithoutClearing(const std::string &path, Engine &engine)
Loads a scene from a file additively without clearing existing scenes.
void scenesUpdate(float deltaTime)
Updates all currently loaded scenes.
void clearScenes(Engine &engine)
Function to clear the current scene.
std::vector< std::string > GetAllSceneNames() const
Retrieves the names of all currently loaded scenes.
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
RenderType
Enum class for different types of rendering. It internally switches used pipeline.
uint32_t Entity
Type alias representing a unique entity identifier in the ECS system.
Definition Types.hpp:11
BodyType
Enumeration of available body types for physics components.
ShapeType
Enumeration of available shape types for physics components.
A component for rendering a 2D quad that always faces the camera.
Struct that contains camera properties. Used by build in CameraObject, but needed for any custom one ...
Character component for player or NPC characters.
Struct containing fog properties.
Destroys the entity after a set amount of time. Useful for temporary effects.
Struct containing light properties.
Struct containing raw meshData, mesh id, texture paths and material properties. It just template and ...
Struct that simply contains name of the entity. It is used to identify entity and needs to be unique.
Moves an entity back and forth using a sine wave without physics overhead.
Component that emits and manages a system of particles.
Tag for entities that should persist across scene changes. Like editor camera.
Structure representing a physics component.
Struct containing transform data and methods.
Smoothly interpolates an entity's local position over time.