diff --git a/Engine/Scripts/Volt-ScriptCore.dll b/Engine/Scripts/Volt-ScriptCore.dll index ec5b9e3ea..6c9a83603 100644 --- a/Engine/Scripts/Volt-ScriptCore.dll +++ b/Engine/Scripts/Volt-ScriptCore.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1180e5dd5e612b687bbba15f0506b40ccab9fbc8e957fcbd19691871231c5e21 -size 94720 +oid sha256:b0899b7951bbacd1b75e925724e70380263aa6858a1f350883bf00030ea70d3b +size 96256 diff --git a/Engine/Scripts/Volt-ScriptCore.pdb b/Engine/Scripts/Volt-ScriptCore.pdb index 245d276af..5ef834dfa 100644 --- a/Engine/Scripts/Volt-ScriptCore.pdb +++ b/Engine/Scripts/Volt-ScriptCore.pdb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e37d496947f36ac305ec4963c1e68ad3e568ede404666aa326e6fc3532695707 -size 37372 +oid sha256:565e99816017a4076c76e38c02ffeb51d21efe70dc0ce0421b6698e96acfec8f +size 37528 diff --git a/Engine/Volt-ScriptCore/Source/Volt/Amp/Amp.cs b/Engine/Volt-ScriptCore/Source/Volt/Amp/Amp.cs index 2079de658..8d78f186c 100644 --- a/Engine/Volt-ScriptCore/Source/Volt/Amp/Amp.cs +++ b/Engine/Volt-ScriptCore/Source/Volt/Amp/Amp.cs @@ -20,6 +20,7 @@ public static void StopAllEvents() public class AudioSourceComponent : Component { + public override string GUID { get => "{06A69F94-BB09-4A3A-AF17-C9DA7D552BFE}"; } #region Event public uint PlayEvent(string aEventName) diff --git a/Engine/Volt-ScriptCore/Source/Volt/Net/NetActorComponent.cs b/Engine/Volt-ScriptCore/Source/Volt/Net/NetActorComponent.cs index 4ef34b00a..9a0ff77ab 100644 --- a/Engine/Volt-ScriptCore/Source/Volt/Net/NetActorComponent.cs +++ b/Engine/Volt-ScriptCore/Source/Volt/Net/NetActorComponent.cs @@ -4,6 +4,7 @@ namespace Volt { public class NetActorComponent : Component { + public override string GUID { get => "{D5A9E480-C9D6-473C-B29E-9FE812320643}"; } } } diff --git a/Engine/Volt-ScriptCore/Source/Volt/Scene/Components.cs b/Engine/Volt-ScriptCore/Source/Volt/Scene/Components.cs index 9f027b7a3..b6e1aff95 100644 --- a/Engine/Volt-ScriptCore/Source/Volt/Scene/Components.cs +++ b/Engine/Volt-ScriptCore/Source/Volt/Scene/Components.cs @@ -11,7 +11,8 @@ public enum VideoStatus : uint public abstract class Component { public Entity entity { get; internal set; } - public virtual string GUID { get; set; } + // #TODO_Ivar: Create actual guid class instead and use to communicate components + public abstract string GUID { get; } } public class TransformComponent : Component diff --git a/Engine/Volt-ScriptCore/Source/Volt/Scene/LightComponents.cs b/Engine/Volt-ScriptCore/Source/Volt/Scene/LightComponents.cs index 970016c43..08425ce82 100644 --- a/Engine/Volt-ScriptCore/Source/Volt/Scene/LightComponents.cs +++ b/Engine/Volt-ScriptCore/Source/Volt/Scene/LightComponents.cs @@ -2,6 +2,7 @@ { public class SpotLightComponent : Component { + public override string GUID { get => "{D35F915F-53E5-4E15-AE5B-769F4D79B6F8}"; } public Vector3 color { get @@ -33,6 +34,8 @@ public float intensity public class PointLightComponent : Component { + public override string GUID { get => "{A30A8848-A30B-41DD-80F9-4E163C01ABC2}"; } + public Vector3 color { get diff --git a/Volt/Navigation/src/Navigation/Core/NavigationSystem.cpp b/Volt/Navigation/src/Navigation/Core/NavigationSystem.cpp index 9a8dc047e..8cc836bc4 100644 --- a/Volt/Navigation/src/Navigation/Core/NavigationSystem.cpp +++ b/Volt/Navigation/src/Navigation/Core/NavigationSystem.cpp @@ -37,76 +37,80 @@ namespace Volt bool NavigationSystem::OnAppUpdateEvent(Volt::AppUpdateEvent& e) { - VT_PROFILE_FUNCTION() - if (myNavMesh && myActiveScene && myActiveScene->IsPlaying()) + VT_PROFILE_FUNCTION(); + if (myNavMesh && myActiveScene && myActiveScene->IsPlaying()) + { + auto& crowd = myNavMesh->GetCrowd(); + if (!crowd) { - auto& crowd = myNavMesh->GetCrowd(); + return false; + } - auto& agentMap = crowd->GetAgentMap(); + auto& agentMap = crowd->GetAgentMap(); + { + VT_PROFILE_SCOPE("Remove old agents"); + + for (auto [entityId, agentId] : agentMap) { - VT_PROFILE_SCOPE("Remove old agents"); + auto entity = myActiveScene->GetEntityFromUUID(entityId); - for (auto [entityId, agentId] : agentMap) + if (!entity || !entity.HasComponent()) { - auto entity = myActiveScene->GetEntityFromUUID(entityId); - - if (!entity || !entity.HasComponent()) - { - crowd->RemoveAgent(entity); - } + crowd->RemoveAgent(entity); + } - if (myEntityIdToTargetPosMap.contains(entityId)) - { - myEntityIdToTargetPosMap.erase(entityId); - } + if (myEntityIdToTargetPosMap.contains(entityId)) + { + myEntityIdToTargetPosMap.erase(entityId); } } + } + + { + VT_PROFILE_SCOPE("Add new agents & disable movement on inactive agents"); + + auto& registry = myActiveScene->GetRegistry(); + auto view = registry.view(); + view.each([&](const entt::entity id, const Volt::NavAgentComponent& comp) { - VT_PROFILE_SCOPE("Add new agents & disable movement on inactive agents"); + auto entity = Volt::Entity(id, myActiveScene); - auto& registry = myActiveScene->GetRegistry(); + crowd->SetAgentPosition(entity, entity.GetPosition()); - auto view = registry.view(); - view.each([&](const entt::entity id, const Volt::NavAgentComponent& comp) + if (!crowd->GetAgentMap().contains(entity.GetID())) { - auto entity = Volt::Entity(id, myActiveScene); - - crowd->SetAgentPosition(entity, entity.GetPosition()); - - if (!crowd->GetAgentMap().contains(entity.GetID())) - { - crowd->AddAgent(entity); - crowd->UpdateAgentParams(entity); - } - else if (!comp.active) - { - PauseAgent(entity, e.GetTimestep()); - } - else if (comp.active) - { - UnpauseAgent(entity); - } - }); - } + crowd->AddAgent(entity); + crowd->UpdateAgentParams(entity); + } + else if (!comp.active) + { + PauseAgent(entity, e.GetTimestep()); + } + else if (comp.active) + { + UnpauseAgent(entity); + } + }); + } - { - VT_PROFILE_SCOPE("Detour crowd update"); - myNavMesh->Update(e.GetTimestep()); - } + { + VT_PROFILE_SCOPE("Detour crowd update"); + myNavMesh->Update(e.GetTimestep()); + } + { + VT_PROFILE_SCOPE("Update agent positions"); + for (auto [entityId, agentId] : agentMap) { - VT_PROFILE_SCOPE("Update agent positions"); - for (auto [entityId, agentId] : agentMap) + Volt::Entity entity = myActiveScene->GetEntityFromUUID(entityId); + if (entity.GetComponent().active) { - Volt::Entity entity = myActiveScene->GetEntityFromUUID(entityId); - if (entity.GetComponent().active) - { - SyncDetourPosition(entity, e.GetTimestep()); - } + SyncDetourPosition(entity, e.GetTimestep()); } } } + } return false; } @@ -220,7 +224,7 @@ namespace Volt VT_CORE_ERROR("Could not initialize agents because active scene is null"); return; } - + auto& registry = myActiveScene->GetRegistry(); auto view = registry.view(); view.each([&](const entt::entity id, const Volt::NavAgentComponent& comp) diff --git a/Volt/Nexus/src/Nexus/Core/Packet/Packet.hpp b/Volt/Nexus/src/Nexus/Core/Packet/Packet.hpp index cfe61fdb8..46f28a2c8 100644 --- a/Volt/Nexus/src/Nexus/Core/Packet/Packet.hpp +++ b/Volt/Nexus/src/Nexus/Core/Packet/Packet.hpp @@ -117,8 +117,12 @@ namespace Nexus } size_t i = packet.body.size(); - packet.body.resize(packet.body.size() + data.size()); + packet.body.resize(packet.body.size() + data.size() + sizeof(size_t)); + memcpy(packet.body.data() + i, data.data(), data.size()); + + const size_t strSize = data.size(); + memcpy(packet.body.data() + i + data.size(), &strSize, sizeof(size_t)); //packet << data.size(); return packet; } @@ -130,16 +134,22 @@ namespace Nexus } [[nodiscard]] std::string GetString(int len = 0) { - if (len == 0) len = (int32_t)body.size(); std::string data; - if (len > body.size()) + + size_t strSize = 0; + memcpy_s(&strSize, sizeof(size_t), body.data() + body.size() - sizeof(size_t), sizeof(size_t)); + + if (body.size() < strSize) { - // Log error return data; } - data.resize(len); - memcpy_s(data.data(), data.size(), body.data() + body.size() - len, len); - body.resize(body.size() - len); + + body.resize(body.size() - sizeof(size_t)); + + data.resize(strSize); + + memcpy_s(data.data(), data.size(), body.data() + body.size() - strSize, strSize); + body.resize(body.size() - strSize); return data; } }; diff --git a/Volt/Sandbox/src/Sandbox/AssetFileWatchers.cpp b/Volt/Sandbox/src/Sandbox/AssetFileWatchers.cpp index c950a7186..998e5dcc9 100644 --- a/Volt/Sandbox/src/Sandbox/AssetFileWatchers.cpp +++ b/Volt/Sandbox/src/Sandbox/AssetFileWatchers.cpp @@ -103,12 +103,6 @@ void Sandbox::CreateModifiedWatch() break; } }); - - myFileChangeQueue.emplace_back([&]() - { - auto assetBrowser = EditorLibrary::Get(); - assetBrowser->Reload(); - }); }); } @@ -135,12 +129,6 @@ void Sandbox::CreateDeleteWatch() } } }); - - myFileChangeQueue.emplace_back([&]() - { - auto assetBrowser = EditorLibrary::Get(); - assetBrowser->Reload(); - }); }); } @@ -149,12 +137,6 @@ void Sandbox::CreateAddWatch() myFileWatcher->AddCallback(efsw::Actions::Add, [&](const std::filesystem::path newPath, const std::filesystem::path oldPath) { std::scoped_lock lock(myFileWatcherMutex); - - myFileChangeQueue.emplace_back([&]() - { - auto assetBrowser = EditorLibrary::Get(); - assetBrowser->Reload(); - }); }); } @@ -174,11 +156,5 @@ void Sandbox::CreateMovedWatch() Volt::AssetManager::Get().MoveAssetInRegistry(oldPath, newPath); } }); - - myFileChangeQueue.emplace_back([&]() - { - auto assetBrowser = EditorLibrary::Get(); - //assetBrowser->Reload(); - }); }); } diff --git a/Volt/Sandbox/src/Sandbox/Sandbox.cpp b/Volt/Sandbox/src/Sandbox/Sandbox.cpp index e194e1431..b80cfc34c 100644 --- a/Volt/Sandbox/src/Sandbox/Sandbox.cpp +++ b/Volt/Sandbox/src/Sandbox/Sandbox.cpp @@ -231,7 +231,8 @@ void Sandbox::OnAttach() void Sandbox::CreateWatches() { myFileWatcher->AddWatch(Volt::ProjectManager::GetEngineDirectory()); - myFileWatcher->AddWatch(Volt::ProjectManager::GetProjectDirectory()); + myFileWatcher->AddWatch(Volt::ProjectManager::GetAssetsDirectory()); + myFileWatcher->AddWatch(Volt::ProjectManager::GetMonoBinariesDirectory()); CreateModifiedWatch(); CreateDeleteWatch(); @@ -465,18 +466,7 @@ void Sandbox::OnEvent(Volt::Event& e) return; } - switch (mySceneState) - { - case SceneState::Edit: - break; - case SceneState::Play: - myRuntimeScene->OnEvent(e); - break; - case SceneState::Pause: - break; - case SceneState::Simulating: - break; - } + myRuntimeScene->OnEvent(e); } void Sandbox::OnScenePlay() @@ -814,6 +804,11 @@ bool Sandbox::OnUpdateEvent(Volt::AppUpdateEvent& e) f(); } + if (!myFileChangeQueue.empty()) + { + EditorLibrary::Get()->Reload(); + } + myFileChangeQueue.clear(); return true; diff --git a/Volt/Sandbox/src/Sandbox/Utility/ComponentPropertyUtilities.cpp b/Volt/Sandbox/src/Sandbox/Utility/ComponentPropertyUtilities.cpp index 44b3ea032..ee424aadb 100644 --- a/Volt/Sandbox/src/Sandbox/Utility/ComponentPropertyUtilities.cpp +++ b/Volt/Sandbox/src/Sandbox/Utility/ComponentPropertyUtilities.cpp @@ -101,6 +101,7 @@ void ComponentPropertyUtility::Initialize() RegisterMonoPropertyType(s_monoPropertyFunctions); RegisterMonoPropertyType(s_monoPropertyFunctions); RegisterMonoPropertyType(s_monoPropertyFunctions); + RegisterMonoPropertyType(s_monoPropertyFunctions); RegisterMonoPropertyType(s_monoPropertyFunctions); } diff --git a/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetDirectoryProcessor.cpp b/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetDirectoryProcessor.cpp index 4ab6f9a68..41bccd9f3 100644 --- a/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetDirectoryProcessor.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetDirectoryProcessor.cpp @@ -57,6 +57,7 @@ Ref AssetDirectoryProcessor::ProcessDirectories(con Ref dirData = CreateRef(m_selectionManager.Get(), relPath); directoryItems[relPath] = dirData; directoryItems[relPath.parent_path()]->subDirectories.emplace_back(dirData); + dirData->parentDirectory = directoryItems[relPath.parent_path()].get(); } else { diff --git a/Volt/Sandbox/src/Sandbox/Window/SceneViewPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/SceneViewPanel.cpp index 85c082134..7bec6354c 100644 --- a/Volt/Sandbox/src/Sandbox/Window/SceneViewPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/SceneViewPanel.cpp @@ -1041,7 +1041,14 @@ void SceneViewPanel::DrawEntity(Volt::Entity entity, const std::string& filter) { for (const auto& child : children) { - DrawEntity(m_scene->GetEntityFromUUID(child), filter); + auto childEnt = m_scene->GetEntityFromUUID(child); + if (!childEnt) + { + // #TODO_Ivar: Maybe display invalid entity somehow? + continue; + } + + DrawEntity(childEnt, filter); } ImGui::TreePop(); diff --git a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp index d7926e8ca..3558f67f7 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp @@ -10,6 +10,7 @@ #include "Volt/Scene/Entity.h" #include "Volt/Scene/Reflection/ComponentReflection.h" #include "Volt/Scene/Reflection/ComponentRegistry.h" +#include "Volt/Asset/Prefab.h" #include "Volt/Scripting/Mono/MonoScriptClass.h" #include "Volt/Scripting/Mono/MonoScriptEngine.h" @@ -573,7 +574,7 @@ namespace Volt if (registry.any_of(id)) { - std::filesystem::path vpPath = (ProjectManager::GetDirectory() / metadata.filePath.parent_path() / "Layers" / ("ent_" + std::to_string((uint32_t)id) + ".entVp")); + std::filesystem::path vpPath = (ProjectManager::GetDirectory() / metadata.filePath.parent_path() / "Layers" / ("ent_" + std::to_string((uint32_t)registry.get(id).id) + ".entVp")); auto& vpComp = registry.get(id); // #TODO_Ivar: This is kind of questionable after TGA @@ -818,6 +819,24 @@ namespace Volt DeserializeMono(entity, scene, streamReader); } + if (scene->GetRegistry().any_of(entity)) + { + auto& prefabComp = scene->GetRegistry().get(entity); + + // We need to check that it's not the entity being referenced in the prefab, as this means we are loading the prefab + if (entity.GetID() != prefabComp.prefabEntity) + { + auto prefab = AssetManager::GetAsset(prefabComp.prefabAsset); + if (prefab && prefab->IsValid()) + { + if (prefab->GetVersion() > prefabComp.version) + { + prefab->UpdateEntityInScene(entity); + } + } + } + } + if (scene->GetRegistry().any_of(entity)) { std::filesystem::path vpPath = metadata.filePath.parent_path(); diff --git a/Volt/Volt/src/Volt/Asset/Prefab.cpp b/Volt/Volt/src/Volt/Asset/Prefab.cpp index 601efd903..36bdc3f00 100644 --- a/Volt/Volt/src/Volt/Asset/Prefab.cpp +++ b/Volt/Volt/src/Volt/Asset/Prefab.cpp @@ -30,7 +30,14 @@ namespace Volt return Entity::Null(); } - Entity newEntity = Entity::Duplicate(m_prefabScene->GetEntityFromUUID(m_rootEntityId), targetScene); + auto rootEntity = m_prefabScene->GetEntityFromUUID(m_rootEntityId); + if (!rootEntity) + { + VT_CORE_ERROR("[Prefab] Root Entity is not a valid entity!"); + return Entity::Null(); + } + + Entity newEntity = Entity::Duplicate(rootEntity, targetScene, Entity::Null(), EntityCopyFlags::SkipCommonData); if (targetScene->IsPlaying()) { InitializeComponents(newEntity); @@ -85,6 +92,8 @@ namespace Volt } } + UpdatePrefabVersion(m_prefabScene->GetEntityFromUUID(m_rootEntityId), m_version); + return updateSucceded; } @@ -340,6 +349,22 @@ namespace Volt } } + void Prefab::UpdatePrefabVersion(Entity entity, uint32_t targetVersion) + { + // We are not going to try and update a entity tree which root is not actually a prefab + if (!entity.HasComponent()) + { + return; + } + + entity.GetComponent().version = targetVersion; + + for (const auto& child : entity.GetChildren()) + { + UpdatePrefabVersion(child, targetVersion); + } + } + const bool Prefab::UpdateEntityInPrefabInternal(Entity srcEntity, EntityID sceneRootId, EntityID forcedPrefabEntity) { bool shouldAddEntity = !srcEntity.HasComponent(); @@ -398,7 +423,7 @@ namespace Volt auto prefabCommonComponent = targetEntity.GetComponent(); auto prefabComponent = targetEntity.GetComponent(); - Entity::Copy(srcEntity, targetEntity); + Entity::Copy(srcEntity, targetEntity, EntityCopyFlags::SkipID | EntityCopyFlags::SkipRelationships | EntityCopyFlags::SkipCommonData); targetEntity.GetComponent() = prefabRelationships; targetEntity.GetComponent() = prefabCommonComponent; @@ -442,7 +467,7 @@ namespace Volt auto sceneCommonComponent = sceneEntity.GetComponent(); const auto sceneRootId = sceneEntity.GetComponent().sceneRootEntity; - Entity::Copy(prefabEntity, sceneEntity); + Entity::Copy(prefabEntity, sceneEntity, EntityCopyFlags::SkipID | EntityCopyFlags::SkipCommonData | EntityCopyFlags::SkipRelationships); if (prefabEntity.GetID() == m_rootEntityId) { @@ -450,6 +475,7 @@ namespace Volt } sceneEntity.GetComponent().sceneRootEntity = sceneRootId; + sceneEntity.GetComponent().version = m_version; sceneEntity.GetComponent() = sceneRelationships; sceneEntity.GetComponent() = sceneCommonComponent; @@ -498,6 +524,8 @@ namespace Volt InitializeComponents(newEntity); } + UpdatePrefabVersion(newEntity, m_version); + targetScene->InvalidateEntityTransform(newEntity.GetID()); return newEntity; } diff --git a/Volt/Volt/src/Volt/Asset/Prefab.h b/Volt/Volt/src/Volt/Asset/Prefab.h index 8593848eb..c50cb4458 100644 --- a/Volt/Volt/src/Volt/Asset/Prefab.h +++ b/Volt/Volt/src/Volt/Asset/Prefab.h @@ -39,7 +39,7 @@ namespace Volt static AssetType GetStaticType() { return AssetType::Prefab; } AssetType GetType() override { return GetStaticType(); }; - uint32_t GetVersion() const override { return 1; } + uint32_t GetVersion() const override { return m_version; } private: friend class PrefabImporter; @@ -52,6 +52,7 @@ namespace Volt void CreatePrefab(Entity srcRootEntity); void AddEntityToPrefabRecursive(Entity entity, Entity parentPrefabEntity); void ValidatePrefabUpdate(Entity srcEntity); + void UpdatePrefabVersion(Entity entity, uint32_t targetVersion); const bool UpdateEntityInPrefabInternal(Entity srcEntity, EntityID rootSceneId, EntityID forcedPrefabEntity); void UpdateEntityInSceneInternal(Entity sceneEntity, EntityID forcedPrefabEntity); diff --git a/Volt/Volt/src/Volt/Core/Application.cpp b/Volt/Volt/src/Volt/Core/Application.cpp index f8c02babb..b49f3ce6b 100644 --- a/Volt/Volt/src/Volt/Core/Application.cpp +++ b/Volt/Volt/src/Volt/Core/Application.cpp @@ -298,6 +298,12 @@ namespace Volt m_window->Present(); + { + VT_PROFILE_SCOPE("Application::PostFrameUpdate"); + AppPostFrameUpdateEvent postFrameUpdateEvent{ m_currentDeltaTime * m_timeScale }; + OnEvent(postFrameUpdateEvent); + } + m_frameTimer.Accumulate(); } diff --git a/Volt/Volt/src/Volt/Events/ApplicationEvent.h b/Volt/Volt/src/Volt/Events/ApplicationEvent.h index 6104b8ed4..0af187f73 100644 --- a/Volt/Volt/src/Volt/Events/ApplicationEvent.h +++ b/Volt/Volt/src/Volt/Events/ApplicationEvent.h @@ -124,6 +124,22 @@ namespace Volt float m_timestep; }; + class AppPostFrameUpdateEvent : public Event + { + public: + AppPostFrameUpdateEvent(float timestep) + : m_timestep(timestep) + { } + + inline const float& GetTimestep() { return m_timestep; } + + EVENT_CLASS_TYPE(AppPostFrameUpdate); + EVENT_CLASS_CATEGORY(EventCategoryApplication); + + private: + float m_timestep; + }; + class AppRenderEvent : public Event { public: @@ -282,4 +298,4 @@ namespace Volt private: Volt::AssetHandle myHandle; }; -} \ No newline at end of file +} diff --git a/Volt/Volt/src/Volt/Events/Event.h b/Volt/Volt/src/Volt/Events/Event.h index 984b1341b..c510909a2 100644 --- a/Volt/Volt/src/Volt/Events/Event.h +++ b/Volt/Volt/src/Volt/Events/Event.h @@ -19,7 +19,7 @@ namespace Volt { None = 0, WindowClose, WindowResize, WindowFocus, WindowLostFocus, WindowMoved, WindowDragDrop, ViewportResize, WindowTitlebarHittest, - AppUpdate, AppRender, AppLog, AppImGuiUpdate, + AppUpdate, AppRender, AppLog, AppImGuiUpdate, AppPostFrameUpdate, KeyPressed, KeyReleased, KeyTyped, MouseButtonPressed, MouseButtonReleased, MouseMoved, MouseScrolled, MouseMovedViewport, diff --git a/Volt/Volt/src/Volt/Net/SceneInteraction/NetActorComponent.h b/Volt/Volt/src/Volt/Net/SceneInteraction/NetActorComponent.h index 6d811ce5e..4c0b6c2c6 100644 --- a/Volt/Volt/src/Volt/Net/SceneInteraction/NetActorComponent.h +++ b/Volt/Volt/src/Volt/Net/SceneInteraction/NetActorComponent.h @@ -26,5 +26,7 @@ namespace Volt reflect.AddMember(&NetActorComponent::repId, "repId", "Replication ID", "", Nexus::RandRepID()); reflect.AddMember(&NetActorComponent::clientId, "clientId", "Client ID", "", 0); } + + REGISTER_COMPONENT(NetActorComponent); }; } diff --git a/Volt/Volt/src/Volt/Net/Serialization/NetSerialization.cpp b/Volt/Volt/src/Volt/Net/Serialization/NetSerialization.cpp index 19ead8697..869af177f 100644 --- a/Volt/Volt/src/Volt/Net/Serialization/NetSerialization.cpp +++ b/Volt/Volt/src/Volt/Net/Serialization/NetSerialization.cpp @@ -232,9 +232,12 @@ Nexus::Packet& operator<(Nexus::Packet& packet, const Volt::RepVariableData& dat Nexus::Packet& operator>(Nexus::Packet& packet, Volt::RepVariableData& varData) { - auto& fieldType = varData.fieldType; - packet >> varData.repId >> fieldType.typeName; + std::string fieldTypeName; + + packet >> varData.repId >> fieldTypeName; + varData.fieldType = Volt::MonoTypeRegistry::GetTypeInfo(fieldTypeName); + auto& fieldType = varData.fieldType; if (fieldType.typeIndex == typeid(bool)) { diff --git a/Volt/Volt/src/Volt/Net/Server/NetServer.cpp b/Volt/Volt/src/Volt/Net/Server/NetServer.cpp index aa5ed694f..766970f97 100644 --- a/Volt/Volt/src/Volt/Net/Server/NetServer.cpp +++ b/Volt/Volt/src/Volt/Net/Server/NetServer.cpp @@ -34,7 +34,6 @@ namespace Volt { } -#pragma optimize("", off) void NetServer::BackendUpdate() { HandleIncomming(); @@ -88,7 +87,7 @@ namespace Volt m_reload = false; } } -#pragma optimize("", on) + void NetServer::Transmit(const Nexus::Packet& in_packet) { for (const auto& connection : m_connectionRegistry.GetClientIDs()) @@ -118,7 +117,7 @@ namespace Volt m_reload = true; } -#pragma optimize("", off) + void NetServer::OnConnect() { //CreateDebugEnemy(); @@ -140,7 +139,6 @@ namespace Volt confirmationPacket.id = Nexus::ePacketID::CONNECTION_CONFIRMED; m_relay.Transmit(confirmationPacket, m_connectionRegistry.GetSockAddr(newClientID)); } -#pragma optimize("", on) void NetServer::OnConnectionConfirmed() { diff --git a/Volt/Volt/src/Volt/Particles/ParticleSystem.cpp b/Volt/Volt/src/Volt/Particles/ParticleSystem.cpp index fcfd900e7..47395474b 100644 --- a/Volt/Volt/src/Volt/Particles/ParticleSystem.cpp +++ b/Volt/Volt/src/Volt/Particles/ParticleSystem.cpp @@ -98,6 +98,13 @@ void Volt::ParticleSystem::Update(entt::registry& registry, Weak scene, c VT_PROFILE_SCOPE("Update particle system"); Entity entity{ id, scene }; + if (!entity) + { + std::scoped_lock lock{ emittersToRemoveMutex }; + emittersToRemove.emplace_back(id); + return; + } + const auto forward = entity.GetForward(); std::vector& p_vec = particleStorage.particles; diff --git a/Volt/Volt/src/Volt/Project/ProjectManager.cpp b/Volt/Volt/src/Volt/Project/ProjectManager.cpp index 712f8baaa..840c6360d 100644 --- a/Volt/Volt/src/Volt/Project/ProjectManager.cpp +++ b/Volt/Volt/src/Volt/Project/ProjectManager.cpp @@ -144,6 +144,11 @@ namespace Volt return GetDirectory() / "Binaries" / "Project.dll"; } + const std::filesystem::path ProjectManager::GetMonoBinariesDirectory() + { + return GetDirectory() / "Binaries"; + } + const std::filesystem::path& ProjectManager::GetDirectory() { return m_currentProject->projectDirectory; diff --git a/Volt/Volt/src/Volt/Project/ProjectManager.h b/Volt/Volt/src/Volt/Project/ProjectManager.h index 46c74ca11..e5eef32bf 100644 --- a/Volt/Volt/src/Volt/Project/ProjectManager.h +++ b/Volt/Volt/src/Volt/Project/ProjectManager.h @@ -39,6 +39,7 @@ namespace Volt static const std::filesystem::path GetPathRelativeToProject(const std::filesystem::path& path); static const std::filesystem::path GetCachePath(); static const std::filesystem::path GetMonoAssemblyPath(); + static const std::filesystem::path GetMonoBinariesDirectory(); static const std::filesystem::path& GetDirectory(); static const bool IsCurrentProjectDeprecated(); diff --git a/Volt/Volt/src/Volt/Scene/Entity.cpp b/Volt/Volt/src/Volt/Scene/Entity.cpp index 11fee74e1..da1b37493 100644 --- a/Volt/Volt/src/Volt/Scene/Entity.cpp +++ b/Volt/Volt/src/Volt/Scene/Entity.cpp @@ -572,6 +572,10 @@ namespace Volt { continue; } + else if (componentDesc->GetGUID() == GetTypeGUID() && (copyFlags & EntityCopyFlags::SkipID) != EntityCopyFlags::None) + { + continue; + } CopyComponent(reinterpret_cast(storage.get(srcEntity)), componentData, 0, componentDesc); } @@ -579,13 +583,13 @@ namespace Volt CopyMonoScripts(srcEntity, dstEntity); } - Entity Entity::Duplicate(Entity srcEntity, Ref targetScene, Entity parent) + Entity Entity::Duplicate(Entity srcEntity, Ref targetScene, Entity parent, const EntityCopyFlags copyFlags) { auto scene = targetScene ? targetScene : srcEntity.GetScene().GetSharedPtr(); Entity newEntity = scene->CreateEntity(); - Copy(srcEntity, newEntity); + Copy(srcEntity, newEntity, EntityCopyFlags::SkipID | EntityCopyFlags::SkipRelationships | copyFlags); if (newEntity.HasComponent()) { @@ -683,6 +687,12 @@ namespace Volt continue; } + if (field.type.IsCustomMonoType()) + { + // #TODO_Ivar: Handle copying custom mono types + continue; + } + auto& srcField = srcFields.at(name); dstFields[name] = CreateRef(); diff --git a/Volt/Volt/src/Volt/Scene/Entity.h b/Volt/Volt/src/Volt/Scene/Entity.h index ab3596464..b859485b2 100644 --- a/Volt/Volt/src/Volt/Scene/Entity.h +++ b/Volt/Volt/src/Volt/Scene/Entity.h @@ -21,7 +21,8 @@ namespace Volt SkipRelationships = BIT(0), SkipPrefab = BIT(1), SkipTransform = BIT(2), - SkipCommonData = BIT(3) + SkipCommonData = BIT(3), + SkipID = BIT(4) }; VT_SETUP_ENUM_CLASS_OPERATORS(EntityCopyFlags); @@ -100,6 +101,7 @@ namespace Volt const bool IsValid() const; const EntityID GetID() const; + const entt::entity GetHandle() const { return m_handle; } template T& GetComponent(); template const T& GetComponent() const; @@ -126,7 +128,7 @@ namespace Volt static void Copy(Entity srcEntity, Entity dstEntity, const EntityCopyFlags copyFlags = EntityCopyFlags::SkipRelationships); // Duplicates an entire entity tree - static Entity Duplicate(Entity srcEntity, Ref targetScene = nullptr, Entity parent = Entity::Null()); + static Entity Duplicate(Entity srcEntity, Ref targetScene = nullptr, Entity parent = Entity::Null(), const EntityCopyFlags copyFlags = EntityCopyFlags::None); private: static void CopyComponent(const uint8_t* srcData, uint8_t* dstData, const size_t offset, const IComponentTypeDesc* compDesc); diff --git a/Volt/Volt/src/Volt/Scene/Scene.cpp b/Volt/Volt/src/Volt/Scene/Scene.cpp index fddd14b94..5266c006c 100644 --- a/Volt/Volt/src/Volt/Scene/Scene.cpp +++ b/Volt/Volt/src/Volt/Scene/Scene.cpp @@ -81,6 +81,9 @@ namespace Volt { VT_PROFILE_SCOPE((std::string("Scene::OnEvent: ") + std::string(e.GetName())).c_str()); + EventDispatcher dispatcher{ e }; + dispatcher.Dispatch(VT_BIND_EVENT_FN(Scene::PostFrameUpdateEvent)); + if (!m_isPlaying) { return; @@ -458,8 +461,8 @@ namespace Volt void Scene::RemoveEntity(Entity entity) { - RemoveEntityInternal(entity, false); - SortScene(); + std::scoped_lock lock{ m_removeEntityMutex }; + m_entityRemoveQueue.push_back(entity.GetID()); } void Scene::ParentEntity(Entity parent, Entity child) @@ -822,7 +825,7 @@ namespace Volt TQS resultTransform{}; for (const auto& ent : std::ranges::reverse_view(hierarchy)) { - const auto& transComp = m_registry.get((entt::entity)ent); + const auto& transComp = m_registry.get(ent.GetHandle()); resultTransform.position = resultTransform.position + resultTransform.rotation * transComp.position; resultTransform.rotation = resultTransform.rotation * transComp.rotation; @@ -985,11 +988,29 @@ namespace Volt m_registry.destroy(entity); } + void Scene::ExecuteEntityRemoveQueue() + { + std::scoped_lock lock{ m_removeEntityMutex }; + for (const auto& entityId : m_entityRemoveQueue) + { + Entity entity = GetEntityFromUUID(entityId); + RemoveEntityInternal(entity, false); + } + + SortScene(); + } + void Scene::AddLayer(const std::string& layerName, uint32_t layerId) { m_sceneLayers.emplace_back(layerId, layerName); } + bool Scene::PostFrameUpdateEvent(const AppPostFrameUpdateEvent& e) + { + ExecuteEntityRemoveQueue(); + return false; + } + void Scene::SetLayers(const std::vector& sceneLayers) { m_sceneLayers = sceneLayers; diff --git a/Volt/Volt/src/Volt/Scene/Scene.h b/Volt/Volt/src/Volt/Scene/Scene.h index 5cab88369..25fde43ba 100644 --- a/Volt/Volt/src/Volt/Scene/Scene.h +++ b/Volt/Volt/src/Volt/Scene/Scene.h @@ -32,6 +32,8 @@ namespace Volt class Entity; + class AppPostFrameUpdateEvent; + struct SceneEnvironment { Ref irradianceMap; @@ -96,6 +98,7 @@ namespace Volt void FixedUpdate(float aDeltaTime); void UpdateEditor(float aDeltaTime); void UpdateSimulation(float aDeltaTime); + void OnEvent(Event& e); void SortScene(); @@ -189,9 +192,12 @@ namespace Volt void ConvertToLocalSpace(Entity entity); void RemoveEntityInternal(Entity entity, bool removingParent); + void ExecuteEntityRemoveQueue(); void AddLayer(const std::string& layerName, uint32_t layerId); + bool PostFrameUpdateEvent(const AppPostFrameUpdateEvent& e); + const glm::mat4 GetWorldTransform(Entity entity) const; const std::vector FlattenEntityHeirarchy(Entity entity); @@ -228,6 +234,9 @@ namespace Volt std::vector m_sceneLayers; + std::mutex m_removeEntityMutex; + std::vector m_entityRemoveQueue; + mutable std::unordered_map m_cachedEntityTransforms; mutable std::shared_mutex m_cachedEntityTransformMutex; diff --git a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptClass.cpp b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptClass.cpp index 91a959dad..bf4f8fe24 100644 --- a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptClass.cpp +++ b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptClass.cpp @@ -67,8 +67,14 @@ namespace Volt MonoType* fieldType = mono_field_get_type(field); const char* typeName = mono_type_get_name(fieldType); + const auto& monoTypeInfo = MonoTypeRegistry::GetTypeInfo(typeName); + if (!monoTypeInfo.IsValid()) + { + continue; + } + MonoScriptField scriptField{}; - scriptField.type = MonoTypeRegistry::GetTypeInfo(typeName); + scriptField.type = monoTypeInfo; scriptField.fieldPtr = field; scriptField.fieldAccessability = accessibility; diff --git a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptGlue.cpp b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptGlue.cpp index 147ec5bb0..f41ff759a 100644 --- a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptGlue.cpp +++ b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptGlue.cpp @@ -1073,6 +1073,11 @@ namespace Volt return nullptr; } + if (!entity.GetParent()) + { + return nullptr; + } + auto monoEntity = MonoScriptEngine::GetEntityFromId(entity.GetParent().GetID()); if (!monoEntity) @@ -3199,7 +3204,7 @@ namespace Volt MonoScriptEngine::GetSceneContext()->GetVision().SetActiveCamera(MonoScriptEngine::GetSceneContext()->GetEntityFromUUID(entityId)); } - inline static EntityID Vision_GetActiveCamera() + inline static uint32_t Vision_GetActiveCamera() { const Volt::Entity ent = MonoScriptEngine::GetSceneContext()->GetVision().GetActiveCamera(); if (ent) @@ -3207,7 +3212,7 @@ namespace Volt return ent.GetID(); } - return Entity::NullID(); + return 0; } inline static void Vision_DoCameraShake(EntityID entityId, Volt::CameraShakeSettings* shakeSettings) diff --git a/Volt/Volt/src/Volt/Scripting/Mono/MonoTypeRegistry.h b/Volt/Volt/src/Volt/Scripting/Mono/MonoTypeRegistry.h index 0c391489a..dcd7f0c7e 100644 --- a/Volt/Volt/src/Volt/Scripting/Mono/MonoTypeRegistry.h +++ b/Volt/Volt/src/Volt/Scripting/Mono/MonoTypeRegistry.h @@ -42,6 +42,7 @@ namespace Volt [[nodiscard]] inline const bool IsString() const { return typeIndex == typeid(std::string); } [[nodiscard]] inline const bool IsEnum() const { return (typeFlags & MonoTypeFlags::Enum) != MonoTypeFlags::None; } [[nodiscard]] inline const bool IsCustomMonoType() const { return typeIndex == typeid(CustomMonoType); } + [[nodiscard]] inline const bool IsValid() const { return typeSize != 0; } }; class MonoTypeRegistry diff --git a/Volt/Volt/src/Volt/Utility/UIUtility.cpp b/Volt/Volt/src/Volt/Utility/UIUtility.cpp index 3df419876..41e35415c 100644 --- a/Volt/Volt/src/Volt/Utility/UIUtility.cpp +++ b/Volt/Volt/src/Volt/Utility/UIUtility.cpp @@ -1499,6 +1499,27 @@ bool UI::Property(const std::string& text, glm::ivec4& value, uint32_t min, uint return changed; } +bool UI::Property(const std::string& text, glm::quat& value, const std::string& toolTip) +{ + bool changed = false; + + BeginPropertyRow(); + + ImGui::TextUnformatted(text.c_str()); + SimpleToolTip(toolTip); + + ImGui::TableNextColumn(); + std::string id = "##" + std::to_string(s_stackId++); + + constexpr float min = -1.f; + constexpr float max = 1.f; + + changed = DragScalarN(id.c_str(), ImGuiDataType_Float, glm::value_ptr(value), 4, 1.f, &min, &max); + EndPropertyRow(); + + return changed; +} + bool UI::PropertyDragFloat(const std::string& text, float& value, float increment, float min, float max, const std::string& toolTip) { bool changed = false; diff --git a/Volt/Volt/src/Volt/Utility/UIUtility.h b/Volt/Volt/src/Volt/Utility/UIUtility.h index 54c87917c..388030493 100644 --- a/Volt/Volt/src/Volt/Utility/UIUtility.h +++ b/Volt/Volt/src/Volt/Utility/UIUtility.h @@ -305,6 +305,8 @@ class UI static bool Property(const std::string& text, glm::ivec3& value, uint32_t min = 0, uint32_t max = 0, const std::string& toolTip = ""); static bool Property(const std::string& text, glm::ivec4& value, uint32_t min = 0, uint32_t max = 0, const std::string& toolTip = ""); + static bool Property(const std::string& text, glm::quat& value, const std::string& toolTip = ""); + static bool Property(const std::string& text, const std::string& value, bool readOnly = false, const std::string& toolTip = ""); static bool Property(const std::string& text, std::string& value, bool readOnly = false, const std::string& toolTip = ""); static bool Property(const std::string& text, std::filesystem::path& path, const std::string& toolTip = "");