diff --git a/Engine/Sandbox.exe b/Engine/Sandbox.exe index 0cb47b51a..d4df06dc6 100644 --- a/Engine/Sandbox.exe +++ b/Engine/Sandbox.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:246b9bd20117ab738194c1a43af7aa95a8bcbd32eaa0febe6413dde04037c06f -size 43718144 +oid sha256:a71b7accdc9ee881c480d8a8d46d49bfb5164ffcf7979d4292daaed6edf3f27a +size 44261376 diff --git a/Engine/Scripts/Volt-ScriptCore.dll b/Engine/Scripts/Volt-ScriptCore.dll index 6c9a83603..8dc43082a 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:b0899b7951bbacd1b75e925724e70380263aa6858a1f350883bf00030ea70d3b -size 96256 +oid sha256:06969d2c7423ddfa8fdf9c3d688f290f593c382025ed6b6c25c462ad870a86e0 +size 103424 diff --git a/Engine/Scripts/Volt-ScriptCore.pdb b/Engine/Scripts/Volt-ScriptCore.pdb index 5ef834dfa..87656b884 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:565e99816017a4076c76e38c02ffeb51d21efe70dc0ce0421b6698e96acfec8f -size 37528 +oid sha256:00ff54b867fdb5fff297c9888139b4723e216e93e9000a436b3c4d3216b7dd1e +size 48024 diff --git a/Engine/Volt-ScriptCore/Source/Volt/Scene/Entity.cs b/Engine/Volt-ScriptCore/Source/Volt/Scene/Entity.cs index 2abd6dfc6..c2fb92851 100644 --- a/Engine/Volt-ScriptCore/Source/Volt/Scene/Entity.cs +++ b/Engine/Volt-ScriptCore/Source/Volt/Scene/Entity.cs @@ -121,7 +121,14 @@ public Entity parent set { - GetComponent().parent = value; + if (value == null) + { + InternalCalls.RelationshipComponent_SetParent(this.Id, 0); + } + else + { + GetComponent().parent = value; + } } } diff --git a/Volt/GraphKey/src/GraphKey/Nodes/Animation/SequenceNodes.cpp b/Volt/GraphKey/src/GraphKey/Nodes/Animation/SequenceNodes.cpp index d7a80d305..36a9f3c22 100644 --- a/Volt/GraphKey/src/GraphKey/Nodes/Animation/SequenceNodes.cpp +++ b/Volt/GraphKey/src/GraphKey/Nodes/Animation/SequenceNodes.cpp @@ -94,11 +94,11 @@ namespace GraphKey //const float localTime = Volt::AnimationManager::globalClock - animGraph->GetStartTime(); const uint32_t currentFrame = anim->GetFrameFromStartTime(animGraph->GetStartTime(), speed); - /* ANIMATION EVENT STUFF - const int32_t animationIndex = character->GetAnimationIndexFromHandle(animHandle); - if (myGraph->GetEntity() != Volt::Entity::NullID() && Volt::SceneManager::GetActiveScene() && animationIndex != -1 && character->HasAnimationEvents((uint32_t)animationIndex)) + + if (myGraph->GetEntity() != Volt::Entity::NullID() && Volt::SceneManager::GetActiveScene() && anim->HasEvents()) { - const auto& animEvents = character->GetAnimationEvents((uint32_t)animationIndex); + const auto& animEvents = anim->GetEvents(); + for (const auto& event : animEvents) { if (event.frame == currentFrame && (int32_t)currentFrame != myLastFrame) @@ -123,7 +123,7 @@ namespace GraphKey } } } - }*/ + } myLastFrame = (int32_t)currentFrame; diff --git a/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.cpp b/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.cpp index e0b398f53..99b1a226a 100644 --- a/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.cpp +++ b/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.cpp @@ -17,11 +17,15 @@ #include #include +#include +#include +#include +#include #include #include -enum class PreV113PropertyType : uint32_t +enum class PreV013PropertyType : uint32_t { Bool = 0, Int = 1, @@ -57,7 +61,7 @@ struct TypeIndexContainer std::type_index typeIndex = typeid(void); }; -static std::unordered_map s_preV113PropTypeToTypeIndexMap; +static std::unordered_map s_preV113PropTypeToTypeIndexMap; static std::unordered_map> s_arrayDeserializers; static std::unordered_map> s_componentMemberRemap; @@ -72,34 +76,40 @@ void RegisterArrayDeserializationFunction() }; } +template +void AddComponentMemberRemap(const std::string& oldName, const std::string& newName) +{ + s_componentMemberRemap[Volt::GetTypeGUID()][oldName] = newName; +} + ProjectUpgradeModal::ProjectUpgradeModal(const std::string& strId) : Modal(strId) { if (!s_initialize) { - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Bool].typeIndex = std::type_index{ typeid(bool) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Int].typeIndex = std::type_index{ typeid(int32_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::UInt].typeIndex = std::type_index{ typeid(uint32_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Short].typeIndex = std::type_index{ typeid(int16_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::UShort].typeIndex = std::type_index{ typeid(uint16_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Char].typeIndex = std::type_index{ typeid(int8_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::UChar].typeIndex = std::type_index{ typeid(uint8_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Float].typeIndex = std::type_index{ typeid(float) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Double].typeIndex = std::type_index{ typeid(double) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Vector2].typeIndex = std::type_index{ typeid(glm::vec2) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Vector3].typeIndex = std::type_index{ typeid(glm::vec3) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Vector4].typeIndex = std::type_index{ typeid(glm::vec4) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::String].typeIndex = std::type_index{ typeid(std::string) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Int64].typeIndex = std::type_index{ typeid(int64_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::UInt64].typeIndex = std::type_index{ typeid(uint64_t) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::AssetHandle].typeIndex = std::type_index{ typeid(Volt::AssetHandle) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Color3].typeIndex = std::type_index{ typeid(glm::vec3) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Color4].typeIndex = std::type_index{ typeid(glm::vec4) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Directory].typeIndex = std::type_index{ typeid(std::filesystem::path) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Path].typeIndex = std::type_index{ typeid(std::filesystem::path) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::EntityId].typeIndex = std::type_index{ typeid(entt::entity) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::GUID].typeIndex = std::type_index{ typeid(VoltGUID) }; - s_preV113PropTypeToTypeIndexMap[PreV113PropertyType::Quaternion].typeIndex = std::type_index{ typeid(glm::quat) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Bool].typeIndex = std::type_index{ typeid(bool) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Int].typeIndex = std::type_index{ typeid(int32_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::UInt].typeIndex = std::type_index{ typeid(uint32_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Short].typeIndex = std::type_index{ typeid(int16_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::UShort].typeIndex = std::type_index{ typeid(uint16_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Char].typeIndex = std::type_index{ typeid(int8_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::UChar].typeIndex = std::type_index{ typeid(uint8_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Float].typeIndex = std::type_index{ typeid(float) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Double].typeIndex = std::type_index{ typeid(double) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Vector2].typeIndex = std::type_index{ typeid(glm::vec2) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Vector3].typeIndex = std::type_index{ typeid(glm::vec3) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Vector4].typeIndex = std::type_index{ typeid(glm::vec4) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::String].typeIndex = std::type_index{ typeid(std::string) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Int64].typeIndex = std::type_index{ typeid(int64_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::UInt64].typeIndex = std::type_index{ typeid(uint64_t) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::AssetHandle].typeIndex = std::type_index{ typeid(Volt::AssetHandle) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Color3].typeIndex = std::type_index{ typeid(glm::vec3) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Color4].typeIndex = std::type_index{ typeid(glm::vec4) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Directory].typeIndex = std::type_index{ typeid(std::filesystem::path) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Path].typeIndex = std::type_index{ typeid(std::filesystem::path) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::EntityId].typeIndex = std::type_index{ typeid(Volt::EntityID) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::GUID].typeIndex = std::type_index{ typeid(VoltGUID) }; + s_preV113PropTypeToTypeIndexMap[PreV013PropertyType::Quaternion].typeIndex = std::type_index{ typeid(glm::quat) }; RegisterArrayDeserializationFunction(); RegisterArrayDeserializationFunction(); @@ -131,16 +141,66 @@ ProjectUpgradeModal::ProjectUpgradeModal(const std::string& strId) RegisterArrayDeserializationFunction(); RegisterArrayDeserializationFunction(); - RegisterArrayDeserializationFunction(); + RegisterArrayDeserializationFunction(); RegisterArrayDeserializationFunction(); // Member remapping { - s_componentMemberRemap[Volt::ComponentRegistry::GetGUIDFromTypeName(entt::type_name())]["Mesh"] = "handle"; - s_componentMemberRemap[Volt::ComponentRegistry::GetGUIDFromTypeName(entt::type_name())]["Character"] = "animatedCharacter"; - s_componentMemberRemap[Volt::ComponentRegistry::GetGUIDFromTypeName(entt::type_name())]["Material"] = "materialHandle"; - s_componentMemberRemap[Volt::ComponentRegistry::GetGUIDFromTypeName(entt::type_name())]["Override Skin"] = "skin"; - s_componentMemberRemap[Volt::ComponentRegistry::GetGUIDFromTypeName(entt::type_name())]["Material"] = "decalMaterial"; + AddComponentMemberRemap("Mesh", "handle"); + AddComponentMemberRemap("Character", "animatedCharacter"); + AddComponentMemberRemap("Material", "materialHandle"); + AddComponentMemberRemap("Override Skin", "skin"); + AddComponentMemberRemap("Material", "decalMaterial"); + + // Vision components + { + AddComponentMemberRemap("Camera", "triggerCam"); + AddComponentMemberRemap("Force Camera", "forceActiveCam"); + + AddComponentMemberRemap("Blend Time", "blendTime"); + AddComponentMemberRemap("Field Of View", "fieldOfView"); + AddComponentMemberRemap("Ignored Layers", "layerMasks"); + AddComponentMemberRemap("Camera Type", "cameraType"); + AddComponentMemberRemap("Blend Type", "blendType"); + AddComponentMemberRemap("Damping", "damping"); + AddComponentMemberRemap("Offset", "offset"); + AddComponentMemberRemap("Follow", "followId"); + AddComponentMemberRemap("LookAt", "lookAtId"); + AddComponentMemberRemap("Collision Focus Point", "collisionRayPoint"); + AddComponentMemberRemap("Focal Distance", "focalDistance"); + AddComponentMemberRemap("Mouse Sensitivity", "mouseSensitivity"); + AddComponentMemberRemap("Collision Sphere Radius", "collisionRadius"); + AddComponentMemberRemap("Collision", "isColliding"); + AddComponentMemberRemap("Is Default", "isDefault"); + AddComponentMemberRemap("X FollowLock", "xFollowLock"); + AddComponentMemberRemap("Y FollowLock", "yFollowLock"); + AddComponentMemberRemap("Z FollowLock", "zFollowLock"); + AddComponentMemberRemap("X ShouldDamp", "xShouldDamp"); + AddComponentMemberRemap("Y ShouldDamp", "yShouldDamp"); + AddComponentMemberRemap("Z ShouldDamp", "zShouldDamp"); + AddComponentMemberRemap("Additive Blend", "additiveBlend"); + } + + // NetActorComponent + { + AddComponentMemberRemap("Condition", "condition"); + AddComponentMemberRemap("Update Position", "updateTransformPos"); + AddComponentMemberRemap("Update Rotation", "updateTransformRot"); + AddComponentMemberRemap("Update Scale", "updateTransformScale"); + AddComponentMemberRemap("RepId", "repId"); + AddComponentMemberRemap("cID", "clientId"); + } + + // GameModeComponent + { + AddComponentMemberRemap("PlayerPrefab", "prefabHandle"); + AddComponentMemberRemap("EnemyPrefab", "enemy"); + } + + // AudioListenerComponent + { + AddComponentMemberRemap("Default", "default"); + } } s_initialize = true; @@ -203,8 +263,8 @@ void ProjectUpgradeModal::UpgradeCurrentProject() if (projectVersion.GetPatch() < 3 && projectVersion.GetMinor() < 2 && projectVersion.GetMajor() == 0) { - ConvertPrefabsToV113(); - ConvertScenesToV113(); + ConvertPrefabsToV013(); + ConvertScenesToV013(); } Volt::ProjectManager::OnProjectUpgraded(); @@ -626,7 +686,7 @@ void ProjectUpgradeModal::ConvertAnimationGraphsToV0_1_2() } } -void ProjectUpgradeModal::ConvertPrefabsToV113() +void ProjectUpgradeModal::ConvertPrefabsToV013() { auto& project = Volt::ProjectManager::GetProject(); const std::filesystem::path assetsPath = project.projectDirectory / project.assetsDirectory; @@ -642,11 +702,11 @@ void ProjectUpgradeModal::ConvertPrefabsToV113() for (const auto& prefabFilePath : prefabFilePaths) { - ConvertPreV113Prefab(prefabFilePath); + ConvertPreV013Prefab(prefabFilePath); } } -void ProjectUpgradeModal::ConvertScenesToV113() +void ProjectUpgradeModal::ConvertScenesToV013() { // We only need to convert the layer files, and not the scene files @@ -715,7 +775,7 @@ void ProjectUpgradeModal::ConvertScenesToV113() } } -void ProjectUpgradeModal::ConvertPreV113Prefab(const std::filesystem::path& filePath) +void ProjectUpgradeModal::ConvertPreV013Prefab(const std::filesystem::path& filePath) { Volt::YAMLFileStreamReader streamReader{}; if (!streamReader.OpenFile(filePath)) @@ -736,12 +796,12 @@ void ProjectUpgradeModal::ConvertPreV113Prefab(const std::filesystem::path& file streamReader.ForEach("entities", [&]() { Volt::EntityID entityId = streamReader.ReadKey("id", Volt::Entity::NullID()); - if (IsPreV113EntityNull(entityId)) + if (IsPreV013EntityNull(entityId)) { return; } - DeserializePreV113Entity(prefabScene, streamReader, entityRemapping, true); + DeserializePreV013Entity(prefabScene, streamReader, entityRemapping, true); }); } streamReader.ExitScope(); @@ -784,13 +844,13 @@ void ProjectUpgradeModal::DeserializePreV113SceneLayer(Ref scene, V streamReader.ForEach("Entities", [&]() { - DeserializePreV113Entity(scene, streamReader, entityRemapping, false); + DeserializePreV013Entity(scene, streamReader, entityRemapping, false); }); } streamReader.ExitScope(); } -void ProjectUpgradeModal::DeserializePreV113Entity(Ref scene, Volt::YAMLFileStreamReader& streamReader, std::map& entityRemapping, bool isPrefabEntity) +void ProjectUpgradeModal::DeserializePreV013Entity(Ref scene, Volt::YAMLFileStreamReader& streamReader, std::map& entityRemapping, bool isPrefabEntity) { if (!isPrefabEntity) { @@ -799,7 +859,7 @@ void ProjectUpgradeModal::DeserializePreV113Entity(Ref scene, Volt: Volt::EntityID originalEntityId = streamReader.ReadKey("id", Volt::Entity::NullID()); - if (IsPreV113EntityNull(originalEntityId)) + if (IsPreV013EntityNull(originalEntityId)) { return; } @@ -946,12 +1006,12 @@ void ProjectUpgradeModal::DeserializePreV113Component(uint8_t* componentData, co return; } - const PreV113PropertyType oldType = static_cast(streamReader.ReadKey("type", 0u)); + const PreV013PropertyType oldType = static_cast(streamReader.ReadKey("type", 0u)); - if (oldType == PreV113PropertyType::Vector && componentMember->typeDesc != nullptr) + if (oldType == PreV013PropertyType::Vector && componentMember->typeDesc != nullptr) { const Volt::IArrayTypeDesc* arrayTypeDesc = reinterpret_cast(componentMember->typeDesc); - const PreV113PropertyType vectorType = static_cast(streamReader.ReadKey("vectorType", 0u)); + const PreV013PropertyType vectorType = static_cast(streamReader.ReadKey("vectorType", 0u)); const std::type_index vectorValueType = s_preV113PropTypeToTypeIndexMap.at(vectorType).typeIndex; void* arrayPtr = &componentData[componentMember->offset]; @@ -984,7 +1044,7 @@ void ProjectUpgradeModal::DeserializePreV113Component(uint8_t* componentData, co return; } - else if (oldType == PreV113PropertyType::Enum) + else if (oldType == PreV013PropertyType::Enum) { typeDeserializers.at(typeid(int32_t))(streamReader, componentData, componentMember->offset); return; @@ -1242,7 +1302,7 @@ void ProjectUpgradeModal::ValidateSceneConversionArray(Ref scene, c } } -const bool ProjectUpgradeModal::IsPreV113EntityNull(Volt::EntityID entityId) +const bool ProjectUpgradeModal::IsPreV013EntityNull(Volt::EntityID entityId) { return entityId == Volt::Entity::NullID(); } diff --git a/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.h b/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.h index 4e1d95a44..1eb2b4c9b 100644 --- a/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.h +++ b/Volt/Sandbox/src/Sandbox/Modals/ProjectUpgradeModal.h @@ -34,13 +34,13 @@ class ProjectUpgradeModal : public Modal void ConvertAnimationGraphsToV0_1_2(); void ConvertMetaFilesToV011(); - void ConvertPrefabsToV113(); - void ConvertScenesToV113(); + void ConvertPrefabsToV013(); + void ConvertScenesToV013(); - void ConvertPreV113Prefab(const std::filesystem::path& filePath); + void ConvertPreV013Prefab(const std::filesystem::path& filePath); void DeserializePreV113SceneLayer(Ref scene, Volt::SceneLayer& sceneLayer, const std::filesystem::path& layerPath, std::map& entityRemapping); - void DeserializePreV113Entity(Ref scene, Volt::YAMLFileStreamReader& streamReader, std::map& entityRemapping, bool isPrefabEntity); + void DeserializePreV013Entity(Ref scene, Volt::YAMLFileStreamReader& streamReader, std::map& entityRemapping, bool isPrefabEntity); void DeserializePreV113Component(uint8_t* componentData, const Volt::IComponentTypeDesc* componentDesc, Volt::YAMLFileStreamReader& streamReader); void DeserializePreV113MonoScripts(Ref scene, const Volt::EntityID entityId, Volt::YAMLFileStreamReader& streamReader); @@ -50,7 +50,7 @@ class ProjectUpgradeModal : public Modal void ValidateSceneConversion(Ref scene); void ValidateSceneConversionArray(Ref scene, const Volt::ComponentMember& componentMember, uint8_t* componentData); - const bool IsPreV113EntityNull(Volt::EntityID entityId); + const bool IsPreV013EntityNull(Volt::EntityID entityId); void ValidateEntityValidity(Volt::EntityID* entityId); const Volt::ComponentMember* TryGetComponentMemberFromName(const std::string& memberName, const Volt::IComponentTypeDesc* componentDesc); diff --git a/Volt/Sandbox/src/Sandbox/Sandbox.cpp b/Volt/Sandbox/src/Sandbox/Sandbox.cpp index b80cfc34c..a2e1b06d2 100644 --- a/Volt/Sandbox/src/Sandbox/Sandbox.cpp +++ b/Volt/Sandbox/src/Sandbox/Sandbox.cpp @@ -42,6 +42,8 @@ #include "Sandbox/Window/BehaviourGraph/BehaviorPanel.h" #include "Sandbox/Window/SceneSettingsPanel.h" #include "Sandbox/Window/WorldEnginePanel.h" +#include "Sandbox/Window/SkeletonEditorPanel.h" +#include "Sandbox/Window/AnimationEditorPanel.h" #include "Sandbox/VertexPainting/VertexPainterPanel.h" #include "Sandbox/Utility/EditorResources.h" @@ -162,6 +164,8 @@ void Sandbox::OnAttach() myAssetBrowserPanel = EditorLibrary::Register("", myRuntimeScene, "##Main"); EditorLibrary::RegisterWithType("Animation", Volt::AssetType::AnimatedCharacter); + EditorLibrary::RegisterWithType("Animation", Volt::AssetType::Skeleton); + EditorLibrary::RegisterWithType("Animation", Volt::AssetType::Animation); EditorLibrary::RegisterWithType("", Volt::AssetType::Material, myRuntimeScene); EditorLibrary::RegisterWithType("", Volt::AssetType::ParticlePreset); EditorLibrary::RegisterWithType("Animation", Volt::AssetType::AnimationGraph, myRuntimeScene); @@ -588,7 +592,13 @@ void Sandbox::NewScene() Volt::AssetManager::Get().Unload(myRuntimeScene->handle); } + if (myRuntimeScene) + { + myRuntimeScene->ShutdownEngineScripts(); + } + myRuntimeScene = Volt::Scene::CreateDefaultScene("New Scene", true); + myRuntimeScene->InitializeEngineScripts(); SetupNewSceneData(); } @@ -606,6 +616,11 @@ void Sandbox::OpenScene(const std::filesystem::path& path) const auto& metadata = Volt::AssetManager::GetMetadataFromHandle(myRuntimeScene->handle); + if (myRuntimeScene) + { + myRuntimeScene->ShutdownEngineScripts(); + } + if (metadata.filePath == path) { Volt::AssetManager::Get().ReloadAsset(myRuntimeScene->handle); @@ -616,6 +631,7 @@ void Sandbox::OpenScene(const std::filesystem::path& path) } myRuntimeScene = Volt::AssetManager::GetAsset(path); + myRuntimeScene->InitializeEngineScripts(); SetupNewSceneData(); } @@ -876,52 +892,6 @@ bool Sandbox::OnImGuiUpdateEvent(Volt::AppImGuiUpdateEvent& e) RenderProgressBar(buildProgess); } - if (ImGui::Begin("Conversion Window")) - { - if (ImGui::Button("Convert Scene to M")) - { - Volt::Entity mainMenuEntity = myRuntimeScene->GetEntityWithName("PF_MainMenu"); - - myRuntimeScene->ForEachWithComponents([&](const entt::entity id, Volt::TransformComponent& transComp, const Volt::MeshComponent& meshComp) - { - Volt::Entity entity{ id, myRuntimeScene }; - entity.SetScale(entity.GetScale() * 0.01f); - }); - - myRuntimeScene->ForEachWithComponents([&](const entt::entity id, Volt::TransformComponent& transComp) - { - Volt::Entity entity{ id, myRuntimeScene }; - - if (mainMenuEntity) - { - if (myRuntimeScene->IsRelatedTo(mainMenuEntity, entity)) - { - return; - } - } - - if (entity == mainMenuEntity) - { - return; - } - - entity.SetLocalPosition(entity.GetLocalPosition() * 0.01f); - }); - - myRuntimeScene->ForEachWithComponents([&](const entt::entity id, Volt::PointLightComponent& comp) - { - comp.radius *= 0.01f; - }); - - myRuntimeScene->ForEachWithComponents([&](const entt::entity id, Volt::SpotLightComponent& comp) - { - comp.range *= 0.01f; - }); - } - - ImGui::End(); - } - return false; } diff --git a/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.cpp new file mode 100644 index 000000000..ae74bf244 --- /dev/null +++ b/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.cpp @@ -0,0 +1,196 @@ +#include "sbpch.h" +#include "AnimationEditorPanel.h" + +#include +#include +#include + +AnimationEditorPanel::AnimationEditorPanel() + : EditorWindow("Animation Editor", false) +{ +} + +void AnimationEditorPanel::UpdateMainContent() +{ + if (!m_animation) + { + return; + } + + const auto duration = m_animation->GetDuration(); + const int32_t stepCount = (int32_t)m_animation->GetFrameCount(); + + if (ImGui::Button("Save")) + { + Volt::AssetManager::SaveAsset(m_animation); + } + + if (ImGui::BeginTable("timelineTable", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp)) + { + ImGui::TableNextColumn(); + if (ImGui::BeginChild("eventsChild", { ImGui::GetColumnWidth(), ImGui::GetContentRegionAvail().y }, true)) + { + UI::Header("Created Events"); + ImGui::Separator(); + if (m_animation->HasEvents()) + { + const auto& events = m_animation->GetEvents(); + for (int index = 0; index < events.size(); index++) + { + const auto id = UI::GetID(); + bool selected = false; + + ImGui::Selectable(std::format("{0}: ", events[index].name).c_str(), &selected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(150, 25)); + ImGui::SameLine(); + ImGui::DragInt(std::format("-##rem{0}", id).c_str(), (int*)&events[index].frame); + + std::string popupName = "eventPopup" + std::to_string(index); + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) + { + ImGui::OpenPopup(popupName.c_str()); + } + + std::string rightClickId = "eventRightClick" + std::to_string(index); + if (ImGui::BeginPopupContextItem(rightClickId.c_str(), ImGuiPopupFlags_MouseButtonRight)) + { + if (ImGui::MenuItem("Remove")) + { + m_animation->RemoveEvent(events[index].name, events[index].frame); + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + break; + } + ImGui::EndPopup(); + } + + } + } + + ImGui::EndChild(); + } + + ImGui::TableNextColumn(); + if (ImGui::BeginChild("keyframeChild", ImGui::GetContentRegionAvail())) + { + if (ImGui::BeginChild("timeChild", { ImGui::GetContentRegionAvail().x, 35.f }, false, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) + { + ImGui::TextUnformatted("0.00"); + ImGui::SameLine(); + + auto drawList = ImGui::GetWindowDrawList(); + ImVec2 windowPos = ImGui::GetWindowPos(); + ImVec2 windowSize = ImGui::GetWindowSize(); + ImGuiIO& io = ImGui::GetIO(); + + drawList->AddRectFilled(windowPos, windowPos + windowSize, IM_COL32(50, 50, 50, 255)); + + UI::ScopedColor color{ ImGuiCol_Button, { 1.f, 1.f, 1.f, 1.f } }; + { + constexpr float padding = 3.f; + UI::ScopedStyleFloat2 itemPadding{ ImGuiStyleVar_ItemSpacing, { 3.f, 0.f } }; + + const float stepSize = windowSize.x / stepCount; + for (int32_t i = 0; i < stepCount; i++) + { + //ImGui::Button(("K##" + std::to_string(i)).c_str(), { stepSize, 20.f }); + ImVec2 keyMinPos = ImVec2(windowPos.x + (stepSize * i) + padding, windowPos.y); + ImVec2 keyMaxPos = ImVec2(windowPos.x + (stepSize * (i + 1)) - padding, windowPos.y + windowSize.y); + + if (m_selectedKeyFrame == i) + { + drawList->AddRectFilled(keyMinPos, keyMaxPos, IM_COL32(100, 100, 100, 255)); + } + else + { + drawList->AddRectFilled(keyMinPos, keyMaxPos, IM_COL32(255, 255, 255, 255)); + } + + ImGui::ItemAdd(ImRect(keyMinPos, keyMaxPos), i); + + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) + { + m_selectedKeyFrame = i; + } + + if (ImGui::IsItemHovered()) + { + drawList->AddText(io.MousePos + ImVec2(0, -20), IM_COL32(255, 100, 100, 255), std::to_string(i).c_str()); + } + + if (ImGui::BeginPopupContextItem(("item##" + std::to_string(i)).c_str(), ImGuiPopupFlags_MouseButtonRight)) + { + if (ImGui::MenuItem("Add Event")) + { + UI::OpenModal("Create Animation Event"); + m_addAnimEventData = {}; + m_addAnimEventData.frame = i; + } + + ImGui::EndPopup(); + } + + ImGui::SameLine(); + } + } + + ImGui::Text("%.2f", duration); + + ImGui::EndChild(); + } + + ImGui::EndChild(); + } + + ImGui::EndTable(); + } + + AddAnimationEventModal(); +} + +void AnimationEditorPanel::OpenAsset(Ref asset) +{ + if (m_animation) + { + Volt::AssetManager::SaveAsset(m_animation); + } + + m_animation = std::reinterpret_pointer_cast(asset); +} + +void AnimationEditorPanel::OnOpen() +{ +} + +void AnimationEditorPanel::OnClose() +{ + m_animation = nullptr; +} + +void AnimationEditorPanel::AddAnimationEventModal() +{ + if (UI::BeginModal("Create Animation Event", ImGuiWindowFlags_AlwaysAutoResize)) + { + UI::PushID(); + if (UI::BeginProperties("animEvent")) + { + UI::Property("Name", m_addAnimEventData.name); + UI::EndProperties(); + } + UI::PopID(); + + if (ImGui::Button("Cancel")) + { + ImGui::CloseCurrentPopup(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Add")) + { + m_animation->AddEvent(m_addAnimEventData.name, m_addAnimEventData.frame); + ImGui::CloseCurrentPopup(); + } + + UI::EndModal(); + } +} diff --git a/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.h b/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.h new file mode 100644 index 000000000..90a7370c2 --- /dev/null +++ b/Volt/Sandbox/src/Sandbox/Window/AnimationEditorPanel.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Sandbox/Window/EditorWindow.h" + +namespace Volt +{ + class Animation; +} + +class AnimationEditorPanel : public EditorWindow +{ +public: + AnimationEditorPanel(); + ~AnimationEditorPanel() override = default; + + void UpdateMainContent() override; + void OpenAsset(Ref asset) override; + + void OnOpen() override; + void OnClose() override; + +private: + struct AddAnimEventData + { + uint32_t frame; + std::string name; + }; + + void AddAnimationEventModal(); + + Ref m_animation; + int32_t m_selectedKeyFrame = -1; + AddAnimEventData m_addAnimEventData{}; +}; diff --git a/Volt/Sandbox/src/Sandbox/Window/AnimationGraph/AnimationGraphPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/AnimationGraph/AnimationGraphPanel.cpp index 8eedb473c..6dd5b60c0 100644 --- a/Volt/Sandbox/src/Sandbox/Window/AnimationGraph/AnimationGraphPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/AnimationGraph/AnimationGraphPanel.cpp @@ -676,6 +676,12 @@ void AnimationGraphPanel::DrawStateMachineNodes() ed::PushStyleVar(ed::StyleVar_PinArrowSize, 10.f); ed::PushStyleVar(ed::StyleVar_PinArrowWidth, 10.0f); ed::PushStyleVar(ed::StyleVar_PinCorners, ImDrawFlags_RoundCornersBottom); + + if (state->bottomPinId == Volt::UUID(0)) + { + VT_DEBUGBREAK(); + } + ed::BeginPin(ed::PinId(state->bottomPinId), ed::PinKind::Output); ed::PinPivotRect(outputsRect.GetTL(), outputsRect.GetBR()); ed::PinRect(outputsRect.GetTL(), outputsRect.GetBR()); diff --git a/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetBrowserPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetBrowserPanel.cpp index 322d9908d..e2fb08497 100644 --- a/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetBrowserPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/AssetBrowser/AssetBrowserPanel.cpp @@ -71,17 +71,21 @@ AssetBrowserPanel::AssetBrowserPanel(Ref& aScene, const std::string myPreviewRenderer = CreateRef(); } + if (!Volt::ProjectManager::GetProject().isDeprecated) { - AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; - myDirectories[Volt::ProjectManager::GetAssetsDirectory()] = processor.ProcessDirectories(Volt::ProjectManager::GetAssetsDirectory(), myMeshImportData, myMeshToImport); - } + { + AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; + myDirectories[Volt::ProjectManager::GetAssetsDirectory()] = processor.ProcessDirectories(Volt::ProjectManager::GetAssetsDirectory(), myMeshImportData, myMeshToImport); + } - { - AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; - myDirectories[FileSystem::GetEnginePath()] = processor.ProcessDirectories(FileSystem::GetEnginePath(), myMeshImportData, myMeshToImport); + { + AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; + myDirectories[FileSystem::GetEnginePath()] = processor.ProcessDirectories(FileSystem::GetEnginePath(), myMeshImportData, myMeshToImport); + } + + myAssetsDirectory = myDirectories[Volt::ProjectManager::GetAssetsDirectory()].get(); } - myAssetsDirectory = myDirectories[Volt::ProjectManager::GetAssetsDirectory()].get(); myCurrentDirectory = myAssetsDirectory; myDirectoryButtons.emplace_back(myCurrentDirectory); @@ -425,6 +429,11 @@ bool AssetBrowserPanel::OnRenderEvent(Volt::AppRenderEvent& e) return false; } + if (!myCurrentDirectory) + { + return false; + } + for (const auto& asset : myCurrentDirectory->assets) { switch (asset->type) @@ -1039,10 +1048,11 @@ void AssetBrowserPanel::Reload() ClearAssetPreviewsInCurrentDirectory(); - //myDirectories[Volt::ProjectManager::GetAssetsDirectory()] = ProcessDirectory(Volt::ProjectManager::GetAssetsDirectory(), nullptr); - - AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; - myDirectories[Volt::ProjectManager::GetAssetsDirectory()] = processor.ProcessDirectories(Volt::ProjectManager::GetAssetsDirectory(), myMeshImportData, myMeshToImport); + if (!Volt::ProjectManager::GetProject().isDeprecated) + { + AssetDirectoryProcessor processor{ mySelectionManager, myAssetMask }; + myDirectories[Volt::ProjectManager::GetAssetsDirectory()] = processor.ProcessDirectories(Volt::ProjectManager::GetAssetsDirectory(), myMeshImportData, myMeshToImport); + } myAssetsDirectory = myDirectories[Volt::ProjectManager::GetAssetsDirectory()].get(); diff --git a/Volt/Sandbox/src/Sandbox/Window/CharacterEditorPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/CharacterEditorPanel.cpp index 2ce1acf46..279909e9a 100644 --- a/Volt/Sandbox/src/Sandbox/Window/CharacterEditorPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/CharacterEditorPanel.cpp @@ -125,7 +125,7 @@ void CharacterEditorPanel::OpenAsset(Ref asset) { if (myCurrentCharacter) { - Volt::AssetManager::Get().SaveAsset(asset); + Volt::AssetManager::Get().SaveAsset(myCurrentCharacter); } myCharacterEntity.GetComponent().animatedCharacter = asset->handle; @@ -613,7 +613,7 @@ void CharacterEditorPanel::UpdateAnimationTimelinePanel() const auto id = UI::GetID(); bool selected = false; - ImGui::Selectable(std::format("{0}: ", events[index].name).c_str(), &selected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(100, 25)); + ImGui::Selectable(std::format("{0}: ", events[index].name).c_str(), &selected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(150, 25)); ImGui::SameLine(); ImGui::DragInt(std::format("-##rem{0}", id).c_str(), (int*)&events[index].frame); @@ -756,8 +756,8 @@ void CharacterEditorPanel::UpdateJointAttachmentViewPanel() if (ImGui::BeginTable("AttachmentTable", 3, ImGuiTableFlags_BordersInnerH, ImGui::GetContentRegionAvail())) { - ImGui::TableSetupColumn("Attachment Name"); ImGui::TableSetupColumn("Joint"); + ImGui::TableSetupColumn("Attachment Name"); ImGui::TableHeadersRow(); @@ -794,6 +794,7 @@ void CharacterEditorPanel::UpdateJointAttachmentViewPanel() ImGui::Text("OFFSET"); UI::Property("Pos", attachment.positionOffset); + UI::Property("Rot", attachment.rotationOffset); UI::EndProperties(); ImGui::EndPopup(); diff --git a/Volt/Sandbox/src/Sandbox/Window/PropertiesPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/PropertiesPanel.cpp index 209a761fa..358cb97bf 100644 --- a/Volt/Sandbox/src/Sandbox/Window/PropertiesPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/PropertiesPanel.cpp @@ -456,7 +456,7 @@ void PropertiesPanel::AddMonoScriptPopup() if (!entity.HasComponent()) { - entity.AddComponent(id); + entity.AddComponent(); } auto& comp = entity.GetComponent(); diff --git a/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.cpp new file mode 100644 index 000000000..c81869c26 --- /dev/null +++ b/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.cpp @@ -0,0 +1,184 @@ +#include "sbpch.h" +#include "SkeletonEditorPanel.h" + +#include "Sandbox/Utility/EditorUtilities.h" +#include "Sandbox/Utility/Theme.h" + +#include +#include + +SkeletonEditorPanel::SkeletonEditorPanel() + : EditorWindow("Skeleton Editor", false) +{ +} + +void SkeletonEditorPanel::UpdateMainContent() +{ + UI::Header("Joint Attachments"); + ImGui::Separator(); + + if (!m_skeleton) + { + return; + } + + if (ImGui::Button("Save")) + { + Volt::AssetManager::SaveAsset(m_skeleton); + } + + if (ImGui::Button("Add")) + { + UI::OpenPopup("addJointAttachmentSkeleton"); + m_jointSearchQuery = ""; + m_activateJointSearch = true; + } + + auto& jointAttachments = const_cast&>(m_skeleton->GetJointAttachments()); + const auto totalWidth = ImGui::GetContentRegionAvail().x; + + if (ImGui::BeginTable("AttachmentTable", 3, ImGuiTableFlags_BordersInnerH, ImGui::GetContentRegionAvail())) + { + ImGui::TableSetupColumn("Joint"); + ImGui::TableSetupColumn("Attachment Name"); + + ImGui::TableHeadersRow(); + + int32_t indexToRemove = -1; + for (int32_t index = 0; auto& attachment : jointAttachments) + { + ImGui::TableNextColumn(); + + auto jointName = m_skeleton->GetNameFromJointIndex(attachment.jointIndex); + + ImGui::PushItemWidth(totalWidth - 11.f); + const std::string jntId = "##" + std::to_string(UI::GetID()); + + ImGui::InputTextString(jntId.c_str(), &jointName, ImGuiInputTextFlags_ReadOnly); + ImGui::PopItemWidth(); + + ImGui::TableNextColumn(); + + ImGui::PushItemWidth(totalWidth - 11.f); + + const std::string attId = "##" + std::to_string(UI::GetID()); + ImGui::InputTextString(attId.c_str(), &attachment.name); + + std::string popupName = "offsetRightclick" + std::to_string(index); + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) + { + ImGui::OpenPopup(popupName.c_str()); + } + + std::string rightClickId = "offsetRightclick" + std::to_string(index); + if (ImGui::BeginPopupContextItem(rightClickId.c_str(), ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::SetWindowSize({ 100.f, 100.f }); + + UI::BeginProperties("OFFSET"); + ImGui::Text("OFFSET"); + + UI::Property("Pos", attachment.positionOffset); + UI::Property("Rot", attachment.rotationOffset); + + UI::EndProperties(); + ImGui::EndPopup(); + } + + ImGui::PopItemWidth(); + + ImGui::TableNextColumn(); + if (ImGui::Button((std::string("-##") + std::to_string(index)).c_str(), { 22.f, 22.f })) + { + indexToRemove = index; + } + + index++; + } + + if (indexToRemove > -1) + { + jointAttachments.erase(jointAttachments.begin() + indexToRemove); + } + + ImGui::EndTable(); + } + + AddJointAttachmentPopup(); +} + +void SkeletonEditorPanel::OpenAsset(Ref asset) +{ + if (m_skeleton) + { + Volt::AssetManager::SaveAsset(std::reinterpret_pointer_cast(m_skeleton)); + } + + m_skeleton = std::reinterpret_pointer_cast(asset); +} + +void SkeletonEditorPanel::OnOpen() +{ +} + +void SkeletonEditorPanel::OnClose() +{ + m_skeleton = nullptr; +} + +void SkeletonEditorPanel::AddJointAttachmentPopup() +{ + ImGui::SetNextWindowSize({ 250.f, 500.f }); + + if (UI::BeginPopup("addJointAttachmentSkeleton", ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) + { + std::vector jointNames; + for (const auto& joint : m_skeleton->GetJoints()) + { + jointNames.emplace_back(joint.name); + } + + // Search bar + { + bool t; + EditorUtils::SearchBar(m_jointSearchQuery, t, m_activateJointSearch); + if (m_activateJointSearch) + { + m_activateJointSearch = false; + } + } + + if (!m_jointSearchQuery.empty()) + { + jointNames = UI::GetEntriesMatchingQuery(m_jointSearchQuery, jointNames); + } + + // List child + { + auto& jointAttachments = const_cast&>(m_skeleton->GetJointAttachments()); + + UI::ScopedColor background{ ImGuiCol_ChildBg, EditorTheme::DarkGreyBackground }; + ImGui::BeginChild("scrolling", ImGui::GetContentRegionAvail()); + + for (const auto& name : jointNames) + { + const std::string id = name + "##" + std::to_string(UI::GetID()); + + UI::ShiftCursor(4.f, 0.f); + UI::RenderMatchingTextBackground(m_jointSearchQuery, name, EditorTheme::MatchingTextBackground); + if (ImGui::MenuItem(id.c_str())) + { + auto& newAttachment = jointAttachments.emplace_back(); + newAttachment.name = "New Attachment"; + newAttachment.jointIndex = m_skeleton->GetJointIndexFromName(name); + + ImGui::CloseCurrentPopup(); + } + } + + ImGui::EndChild(); + } + + UI::EndPopup(); + } +} diff --git a/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.h b/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.h new file mode 100644 index 000000000..eba8cfe07 --- /dev/null +++ b/Volt/Sandbox/src/Sandbox/Window/SkeletonEditorPanel.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Sandbox/Window/EditorWindow.h" + +namespace Volt +{ + class Skeleton; +} + +class SkeletonEditorPanel : public EditorWindow +{ +public: + SkeletonEditorPanel(); + ~SkeletonEditorPanel() override = default; + + void UpdateMainContent() override; + void OpenAsset(Ref asset) override; + + void OnOpen() override; + void OnClose() override; + +private: + void AddJointAttachmentPopup(); + + Ref m_skeleton; + + bool m_activateJointSearch = false; + std::string m_jointSearchQuery; +}; diff --git a/Volt/Volt/src/Volt/Animation/AnimationController.cpp b/Volt/Volt/src/Volt/Animation/AnimationController.cpp index 24ec388b0..770415bde 100644 --- a/Volt/Volt/src/Volt/Animation/AnimationController.cpp +++ b/Volt/Volt/src/Volt/Animation/AnimationController.cpp @@ -56,12 +56,12 @@ namespace Volt } - /* { + { VT_PROFILE_SCOPE("Joint Attachments"); for (const auto& [attachmentId, attachedEntities] : myAttachedEntities) { - auto attachment = character->GetJointAttachmentFromID(attachmentId); + auto attachment = skeleton->GetJointAttachmentFromID(attachmentId); if (attachment.jointIndex == -1) { continue; @@ -79,36 +79,41 @@ namespace Volt for (auto ent : attachedEntities) { + if (!ent) + { + continue; + } + ent.SetLocalPosition(resultPos); ent.SetLocalRotation(resultRot); ent.SetLocalScale(currentTRS.scale); } } - }*/ + } return result; } void AnimationController::AttachEntity(const std::string& attachment, Entity entity) { - /*const auto character = AssetManager::GetAsset(myGraph->GetCharacterHandle()); + const auto skeleton = AssetManager::GetAsset(myGraph->GetSkeletonHandle()); - if (!character || !character->IsValid()) + if (!skeleton || !skeleton->IsValid()) { return; } - if (!character->HasJointAttachment(attachment)) + if (!skeleton->HasJointAttachment(attachment)) { return; } - myAttachedEntities[character->GetJointAttachmentFromName(attachment).id].emplace_back(entity);*/ + myAttachedEntities[skeleton->GetJointAttachmentFromName(attachment).id].emplace_back(entity); } void AnimationController::DetachEntity(Entity entity) { - /*for (auto& [attachmentName, attachedEntities] : myAttachedEntities) + for (auto& [attachmentName, attachedEntities] : myAttachedEntities) { auto it = std::find(attachedEntities.begin(), attachedEntities.end(), entity); if (it != attachedEntities.end()) @@ -116,7 +121,7 @@ namespace Volt attachedEntities.erase(it); return; } - }*/ + } } void AnimationController::OnEvent(Event& e) diff --git a/Volt/Volt/src/Volt/Animation/AnimationStateMachine.cpp b/Volt/Volt/src/Volt/Animation/AnimationStateMachine.cpp index 430bca12d..b76551758 100644 --- a/Volt/Volt/src/Volt/Animation/AnimationStateMachine.cpp +++ b/Volt/Volt/src/Volt/Animation/AnimationStateMachine.cpp @@ -85,7 +85,7 @@ namespace Volt const auto& currState = myStates.at(myCurrentState); - VT_WARN("{}", currState->name); + //VT_WARN("{}", currState->name); for (const auto& id : currState->transitions) { diff --git a/Volt/Volt/src/Volt/Asset/Animation/Animation.cpp b/Volt/Volt/src/Volt/Asset/Animation/Animation.cpp index f0677d05b..7475c505a 100644 --- a/Volt/Volt/src/Volt/Asset/Animation/Animation.cpp +++ b/Volt/Volt/src/Volt/Asset/Animation/Animation.cpp @@ -12,9 +12,9 @@ namespace Volt VT_PROFILE_FUNCTION(); const float localTime = AnimationManager::globalClock - aStartTime; - const float normalizedTime = localTime / myDuration; + const float normalizedTime = localTime / m_duration; - const int32_t frameCount = (int32_t)myFrames.size(); + const int32_t frameCount = (int32_t)m_frames.size(); int32_t currentFrameIndex = frameCount - std::abs((int32_t)(std::floor(normalizedTime * (float)frameCount)) % (2 * frameCount) - frameCount); currentFrameIndex = std::clamp(currentFrameIndex, 0, frameCount - 1); @@ -41,12 +41,12 @@ namespace Volt return {}; } - const float animDelta = 1.f / (float)myFramesPerSecond; + const float animDelta = 1.f / (float)m_framesPerSecond; const float frameTime = localTime / animDelta; const float deltaTime = frameTime - (float)currentFrameIndex; - const Pose& currentFrame = myFrames.at(currentFrameIndex); - const Pose& nextFrame = myFrames.at(nextFrameIndex); + const Pose& currentFrame = m_frames.at(currentFrameIndex); + const Pose& nextFrame = m_frames.at(nextFrameIndex); const auto& joints = aSkeleton->GetJoints(); const auto& invBindPoses = aSkeleton->GetInverseBindPose(); @@ -100,7 +100,7 @@ namespace Volt return {}; } - const Pose& currentFrame = myFrames.at(frameIndex); + const Pose& currentFrame = m_frames.at(frameIndex); const auto& joints = aSkeleton->GetJoints(); const auto& invBindPoses = aSkeleton->GetInverseBindPose(); @@ -142,12 +142,12 @@ namespace Volt { VT_PROFILE_FUNCTION(); - const float finalDuration = myDuration / speed; + const float finalDuration = m_duration / speed; const float localTime = AnimationManager::globalClock - aStartTime; const float normalizedTime = localTime / finalDuration; - const int32_t frameCount = (int32_t)myFrames.size(); + const int32_t frameCount = (int32_t)m_frames.size(); int32_t currentFrameIndex = (int32_t)(std::floor(normalizedTime * (float)frameCount)) % frameCount; if (normalizedTime > 1.f && !looping) @@ -176,8 +176,8 @@ namespace Volt std::vector result; result.resize(aSkeleton->GetJointCount(), TRS{}); - const Pose& currentFrame = myFrames.at(currentFrameIndex); - const Pose& nextFrame = myFrames.at(nextFrameIndex); + const Pose& currentFrame = m_frames.at(currentFrameIndex); + const Pose& nextFrame = m_frames.at(nextFrameIndex); const auto& joints = aSkeleton->GetJoints(); @@ -203,9 +203,9 @@ namespace Volt const bool Animation::IsAtEnd(float startTime, float speed) { const float localTime = AnimationManager::globalClock - startTime; - const float normalizedTime = localTime / (myDuration / speed); + const float normalizedTime = localTime / (m_duration / speed); - const int32_t frameCount = (int32_t)myFrames.size(); + const int32_t frameCount = (int32_t)m_frames.size(); const int32_t currentFrameIndex = (int32_t)(std::floor(normalizedTime * (float)frameCount)) % frameCount; int32_t nextFrameIndex = currentFrameIndex + 1; @@ -221,11 +221,11 @@ namespace Volt const bool Animation::HasPassedTime(float startTime, float speed, float time) { const float localTime = AnimationManager::globalClock - startTime; - const float normalizedTime = localTime / (myDuration / speed); + const float normalizedTime = localTime / (m_duration / speed); - const float normalizedWantedTime = time / (myDuration / speed); + const float normalizedWantedTime = time / (m_duration / speed); - const int32_t frameCount = (int32_t)myFrames.size(); + const int32_t frameCount = (int32_t)m_frames.size(); const int32_t currentFrameIndex = (int32_t)(std::floor(normalizedTime * (float)frameCount)) % frameCount; const int32_t wantedFrame = (int32_t)(std::floor(normalizedWantedTime * (float)frameCount)) % frameCount; @@ -243,9 +243,9 @@ namespace Volt const uint32_t Animation::GetFrameFromStartTime(float startTime, float speed) { const float localTime = AnimationManager::globalClock - startTime; - const float normalizedTime = localTime / (myDuration / speed); + const float normalizedTime = localTime / (m_duration / speed); - const int32_t frameCount = (int32_t)myFrames.size(); + const int32_t frameCount = (int32_t)m_frames.size(); const int32_t currentFrameIndex = (int32_t)(std::floor(normalizedTime * (float)frameCount)) % frameCount; return currentFrameIndex; } @@ -253,7 +253,7 @@ namespace Volt const float Animation::GetNormalizedCurrentTimeFromStartTime(float startTime, float speed, bool looping) { const float localTime = AnimationManager::globalClock - startTime; - const float normalizedTime = localTime / (myDuration / speed); + const float normalizedTime = localTime / (m_duration / speed); if (looping) { @@ -266,11 +266,29 @@ namespace Volt //return 0.0f; } + void Animation::AddEvent(const std::string& eventName, uint32_t frame) + { + m_events.emplace_back(frame, eventName); + } + + void Animation::RemoveEvent(const std::string& eventName, uint32_t frame) + { + auto it = std::find_if(m_events.begin(), m_events.end(), [eventName](const auto& event) + { + return event.name == eventName; + }); + + if (it != m_events.end()) + { + m_events.erase(it); + } + } + const Animation::PoseData Animation::GetFrameDataFromAnimation(Animation& animation, const float aNormalizedTime) { PoseData animData{}; - const size_t frameCount = animation.myFrames.size(); + const size_t frameCount = animation.m_frames.size(); animData.currentFrameIndex = (size_t)std::floorf((float)frameCount * aNormalizedTime); animData.nextFrameIndex = animData.currentFrameIndex + 1; @@ -285,8 +303,8 @@ namespace Volt animData.currentFrameIndex = frameCount - 1; } - const float localTime = animation.myDuration * aNormalizedTime; - const float animDelta = 1.f / (float)animation.myFramesPerSecond; + const float localTime = animation.m_duration * aNormalizedTime; + const float animDelta = 1.f / (float)animation.m_framesPerSecond; const float frameTime = localTime / animDelta; animData.deltaTime = frameTime - (float)animData.currentFrameIndex; diff --git a/Volt/Volt/src/Volt/Asset/Animation/Animation.h b/Volt/Volt/src/Volt/Asset/Animation/Animation.h index f093d351d..47fed2528 100644 --- a/Volt/Volt/src/Volt/Asset/Animation/Animation.h +++ b/Volt/Volt/src/Volt/Asset/Animation/Animation.h @@ -49,6 +49,12 @@ namespace Volt } }; + struct Event + { + uint32_t frame; + std::string name; + }; + const std::vector Sample(float aStartTime, Ref aSkeleton, bool looping); const std::vector Sample(uint32_t frameIndex, Ref aSkeleton); @@ -59,9 +65,14 @@ namespace Volt const uint32_t GetFrameFromStartTime(float startTime, float speed); const float GetNormalizedCurrentTimeFromStartTime(float startTime, float speed, bool looping); - inline const float GetDuration() const { return myDuration; } - inline const size_t GetFrameCount() const { return myFrames.size(); } - inline const uint32_t GetFramesPerSecond() const { return myFramesPerSecond; } + inline const float GetDuration() const { return m_duration; } + inline const size_t GetFrameCount() const { return m_frames.size(); } + inline const uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + void AddEvent(const std::string& eventName, uint32_t frame); + void RemoveEvent(const std::string& eventName, uint32_t frame); + inline const bool HasEvents() const { return !m_events.empty(); } + inline const std::vector& GetEvents() const { return m_events; } static AssetType GetStaticType() { return AssetType::Animation; } AssetType GetType() override { return GetStaticType(); }; @@ -81,9 +92,10 @@ namespace Volt friend class AnimationImporter; friend class AnimationSerializer; - std::vector myFrames; + std::vector m_frames; + std::vector m_events; - uint32_t myFramesPerSecond = 0; - float myDuration = 0.f; + uint32_t m_framesPerSecond = 0; + float m_duration = 0.f; }; } diff --git a/Volt/Volt/src/Volt/Asset/Animation/Skeleton.cpp b/Volt/Volt/src/Volt/Asset/Animation/Skeleton.cpp index 455e13eab..06a237506 100644 --- a/Volt/Volt/src/Volt/Asset/Animation/Skeleton.cpp +++ b/Volt/Volt/src/Volt/Asset/Animation/Skeleton.cpp @@ -5,29 +5,68 @@ namespace Volt { + const Skeleton::JointAttachment& Skeleton::GetJointAttachmentFromName(std::string_view name) const + { + for (const auto& attachment : m_jointAttachments) + { + if (attachment.name == name) + { + return attachment; + } + } + + static Skeleton::JointAttachment nullAttachment; + return nullAttachment; + } + const Skeleton::JointAttachment& Skeleton::GetJointAttachmentFromID(const UUID& id) const + { + for (const auto& attachment : m_jointAttachments) + { + if (attachment.id == id) + { + return attachment; + } + } + + static Skeleton::JointAttachment nullAttachment; + return nullAttachment; + } + + bool Skeleton::HasJointAttachment(std::string_view name) const + { + for (const auto& attachment : m_jointAttachments) + { + if (attachment.name == name) + { + return true; + } + } + return false; + } + const bool Skeleton::JointIsDecendantOf(int32_t jointIndex, int32_t parentIndex) const { - if (jointIndex < 0 || jointIndex >= (int32_t)myJoints.size()) + if (jointIndex < 0 || jointIndex >= (int32_t)m_joints.size()) { return false; } - if (myJoints.at(jointIndex).parentIndex == parentIndex) + if (m_joints.at(jointIndex).parentIndex == parentIndex) { return true; } - return JointIsDecendantOf(myJoints.at(jointIndex).parentIndex, parentIndex); + return JointIsDecendantOf(m_joints.at(jointIndex).parentIndex, parentIndex); } const int32_t Skeleton::GetJointIndexFromName(const std::string& str) { - if (myJointNameToIndex.contains(str)) + if (m_jointNameToIndex.contains(str)) { - return static_cast(myJointNameToIndex.at(str)); + return static_cast(m_jointNameToIndex.at(str)); } - for (int32_t i = 0; const auto & joint : myJoints) + for (int32_t i = 0; const auto & joint : m_joints) { if (joint.name == str) { @@ -41,12 +80,12 @@ namespace Volt const std::string Skeleton::GetNameFromJointIndex(int32_t index) { - if (index >= (int32_t)myJoints.size()) + if (index >= (int32_t)m_joints.size()) { VT_CORE_ERROR("Index is greater than joint count!"); return ""; } - return myJoints.at(index).name; + return m_joints.at(index).name; } } diff --git a/Volt/Volt/src/Volt/Asset/Animation/Skeleton.h b/Volt/Volt/src/Volt/Asset/Animation/Skeleton.h index 0e2330be1..cf65c5a48 100644 --- a/Volt/Volt/src/Volt/Asset/Animation/Skeleton.h +++ b/Volt/Volt/src/Volt/Asset/Animation/Skeleton.h @@ -28,17 +28,52 @@ namespace Volt } }; + struct JointAttachment + { + std::string name; + int32_t jointIndex = -1; + UUID id = 0; + + glm::vec3 positionOffset = 0.f; + glm::quat rotationOffset = { 1.f, 0.f, 0.f, 0.f }; + + inline const bool IsValid() const { return id != 0; } + + static void Serialize(BinaryStreamWriter& streamWriter, const JointAttachment& data) + { + streamWriter.Write(data.name); + streamWriter.Write(data.jointIndex); + streamWriter.Write(data.id); + streamWriter.Write(data.positionOffset); + streamWriter.Write(data.rotationOffset); + } + + static void Deserialize(BinaryStreamReader& streamReader, JointAttachment& outData) + { + streamReader.Read(outData.name); + streamReader.Read(outData.jointIndex); + streamReader.Read(outData.id); + streamReader.Read(outData.positionOffset); + streamReader.Read(outData.rotationOffset); + } + }; + Skeleton() = default; ~Skeleton() override { - myJoints.clear(); - myInverseBindPose.clear(); + m_joints.clear(); + m_inverseBindPose.clear(); } - inline const size_t GetJointCount() const { return myJoints.size(); } - inline const std::vector& GetInverseBindPose() const { return myInverseBindPose; } - inline const std::vector& GetRestPose() const { return myRestPose; } - inline const std::vector& GetJoints() const { return myJoints; } + inline const size_t GetJointCount() const { return m_joints.size(); } + inline const std::vector& GetInverseBindPose() const { return m_inverseBindPose; } + inline const std::vector& GetRestPose() const { return m_restPose; } + inline const std::vector& GetJoints() const { return m_joints; } + inline const std::vector& GetJointAttachments() const { return m_jointAttachments; } + + const JointAttachment& GetJointAttachmentFromName(std::string_view name) const; + const JointAttachment& GetJointAttachmentFromID(const UUID& id) const; + bool HasJointAttachment(std::string_view name) const; const bool JointIsDecendantOf(int32_t jointIndex, int32_t parentIndex) const; @@ -54,12 +89,13 @@ namespace Volt friend class SkeletonImporter; friend class SkeletonSerializer; - std::vector myJoints; - std::vector myRestPose; - std::vector myInverseBindPose; + std::vector m_joints; + std::vector m_jointAttachments; + std::vector m_restPose; + std::vector m_inverseBindPose; - std::unordered_map myJointNameToIndex; + std::unordered_map m_jointNameToIndex; - std::string myName = "Skeleton"; + std::string m_name = "Skeleton"; }; } diff --git a/Volt/Volt/src/Volt/Asset/AssetManager.cpp b/Volt/Volt/src/Volt/Asset/AssetManager.cpp index 15487c00e..17c744518 100644 --- a/Volt/Volt/src/Volt/Asset/AssetManager.cpp +++ b/Volt/Volt/src/Volt/Asset/AssetManager.cpp @@ -195,17 +195,19 @@ namespace Volt AssetMetadata& metadata = GetMetadataFromHandleMutable(assetHandle); if (!metadata.IsValid()) { + VT_CORE_ERROR("[AssetManager] Trying to load asset which has invalid metadata!"); + asset->SetFlag(AssetFlag::Invalid, true); return; } if (!m_assetImporters.contains(metadata.type)) { VT_CORE_WARN("[AssetManager] No importer for asset found!"); + asset->SetFlag(AssetFlag::Invalid, true); return; } m_assetImporters.at(metadata.type)->Load(metadata, asset); - if (!asset) { return; } #ifdef VT_DEBUG VT_CORE_TRACE("[AssetManager] Loaded asset {0} with handle {1}!", metadata.filePath, assetHandle); @@ -1025,6 +1027,7 @@ namespace Volt if (!metadata.IsValid()) { + asset->SetFlag(AssetFlag::Invalid, true); return; } @@ -1040,18 +1043,19 @@ namespace Volt threadPool.SubmitTask([this, metadata](AssetHandle handle) { - if (!m_assetImporters.contains(metadata.type)) - { - VT_CORE_ERROR("No importer for asset found!"); - return; - } - Ref asset; { ReadLock lock{ m_assetCacheMutex }; asset = m_assetCache.at(handle); } + if (!m_assetImporters.contains(metadata.type)) + { + VT_CORE_ERROR("No importer for asset found!"); + asset->SetFlag(AssetFlag::Invalid, true); + return; + } + m_assetImporters.at(metadata.type)->Load(metadata, asset); if (handle != Asset::Null()) { diff --git a/Volt/Volt/src/Volt/Asset/Importers/AnimationImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/AnimationImporter.cpp index aa19a952f..3aab8c8de 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/AnimationImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/AnimationImporter.cpp @@ -8,6 +8,17 @@ namespace Volt { + struct AnimEventsHeader + { + uint32_t eventCount; + }; + + struct AnimEventHeader + { + uint32_t totalSize; + uint32_t stringSize; + }; + bool AnimationImporter::Load(const AssetMetadata& metadata, Ref& asset) const { asset = CreateRef(); @@ -58,9 +69,30 @@ namespace Volt offset += header.perFrameTransformCount * sizeof(Animation::TRS); } - animation->myFrames = frames; - animation->myDuration = header.duration; - animation->myFramesPerSecond = header.framesPerSecond; + if (offset + sizeof(AnimEventsHeader) < totalData.size()) + { + AnimEventsHeader eventsHeader = *(AnimEventsHeader*)&totalData[offset]; + offset += sizeof(AnimEventsHeader); + + for (uint32_t i = 0; i < eventsHeader.eventCount; i++) + { + AnimEventHeader eHeader = *(AnimEventHeader*)&totalData[offset]; + offset += sizeof(AnimEventHeader); + + auto& animEvent = animation->m_events.emplace_back(); + animEvent.name.resize(eHeader.stringSize); + + animEvent.frame = *(uint32_t*)&totalData[offset]; + offset += sizeof(uint32_t); + + memcpy_s(animEvent.name.data(), eHeader.stringSize, &totalData[offset], eHeader.stringSize); + offset += eHeader.stringSize; + } + } + + animation->m_frames = frames; + animation->m_duration = header.duration; + animation->m_framesPerSecond = header.framesPerSecond; return true; } @@ -71,10 +103,13 @@ namespace Volt std::vector outData; AnimationHeader header{}; - header.perFrameTransformCount = (uint32_t)animation->myFrames.front().localTRS.size(); - header.frameCount = (uint32_t)animation->myFrames.size(); - header.duration = animation->myDuration; - header.framesPerSecond = animation->myFramesPerSecond; + header.perFrameTransformCount = (uint32_t)animation->m_frames.front().localTRS.size(); + header.frameCount = (uint32_t)animation->m_frames.size(); + header.duration = animation->m_duration; + header.framesPerSecond = animation->m_framesPerSecond; + + AnimEventsHeader eventsHeader{}; + eventsHeader.eventCount = static_cast(animation->m_events.size()); outData.resize(sizeof(AnimationHeader) + header.frameCount * header.perFrameTransformCount * sizeof(Animation::TRS)); @@ -83,12 +118,35 @@ namespace Volt offset += sizeof(AnimationHeader); // Copy matrices per frame - for (const auto& frame : animation->myFrames) + for (const auto& frame : animation->m_frames) { memcpy_s(&outData[offset], header.perFrameTransformCount * sizeof(Animation::TRS), frame.localTRS.data(), header.perFrameTransformCount * sizeof(Animation::TRS)); offset += header.perFrameTransformCount * sizeof(Animation::TRS); } + outData.resize(outData.size() + sizeof(AnimEventsHeader)); + + memcpy_s(&outData[offset], sizeof(AnimEventsHeader), &eventsHeader, sizeof(AnimEventsHeader)); + offset += sizeof(AnimEventsHeader); + + for (const auto& animEvent : animation->m_events) + { + AnimEventHeader eHeader{}; + eHeader.stringSize = static_cast(animEvent.name.size()); + eHeader.totalSize = eHeader.stringSize + sizeof(animEvent.frame); + + outData.resize(outData.size() + eHeader.totalSize + sizeof(AnimEventHeader)); + + memcpy_s(&outData[offset], sizeof(AnimEventHeader), &eHeader, sizeof(AnimEventHeader)); + offset += sizeof(AnimEventHeader); + + memcpy_s(&outData[offset], sizeof(uint32_t), &animEvent.frame, sizeof(uint32_t)); + offset += sizeof(uint32_t); + + memcpy_s(&outData[offset], eHeader.stringSize, animEvent.name.data(), animEvent.name.size()); + offset += animEvent.name.size(); + } + std::ofstream fout(AssetManager::GetFilesystemPath(metadata.filePath), std::ios::binary | std::ios::out); fout.write((char*)outData.data(), outData.size()); fout.close(); diff --git a/Volt/Volt/src/Volt/Asset/Importers/FbxImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/FbxImporter.cpp index 5d3ef801d..d3fc5b4f8 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/FbxImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/FbxImporter.cpp @@ -118,9 +118,9 @@ namespace Volt return false; } - dstSkeleton.myJoints.resize(tgaMesh.Skeleton.Bones.size()); - dstSkeleton.myInverseBindPose.resize(tgaMesh.Skeleton.Bones.size()); - dstSkeleton.myRestPose.resize(tgaMesh.Skeleton.Bones.size()); + dstSkeleton.m_joints.resize(tgaMesh.Skeleton.Bones.size()); + dstSkeleton.m_inverseBindPose.resize(tgaMesh.Skeleton.Bones.size()); + dstSkeleton.m_restPose.resize(tgaMesh.Skeleton.Bones.size()); ProcessSkeleton(dstSkeleton, tgaMesh.Skeleton.Bones, 0); @@ -147,13 +147,13 @@ namespace Volt return false; } - dstAnimation.myFramesPerSecond = static_cast(tgaAnimation.FramesPerSecond); - dstAnimation.myDuration = static_cast(tgaAnimation.Duration); + dstAnimation.m_framesPerSecond = static_cast(tgaAnimation.FramesPerSecond); + dstAnimation.m_duration = static_cast(tgaAnimation.Duration); for (const auto& tgaFrame : tgaAnimation.Frames) { - auto& newFrame = dstAnimation.myFrames.emplace_back(); - newFrame.localTRS.resize(targetSkeleton->myJoints.size()); + auto& newFrame = dstAnimation.m_frames.emplace_back(); + newFrame.localTRS.resize(targetSkeleton->m_joints.size()); for (const auto& [jointName, localTQS] : tgaFrame.LocalTQS) { @@ -269,19 +269,19 @@ namespace Volt { const auto& currentJoint = bones.at(currentIndex); - skeleton.myJoints[currentIndex].name = currentJoint.Name; - skeleton.myJoints[currentIndex].parentIndex = currentJoint.ParentIdx; - skeleton.myInverseBindPose[currentIndex] = glm::transpose(*reinterpret_cast(currentJoint.BindPoseInverse.Data)); - skeleton.myJointNameToIndex[currentJoint.Name] = static_cast(currentIndex); + skeleton.m_joints[currentIndex].name = currentJoint.Name; + skeleton.m_joints[currentIndex].parentIndex = currentJoint.ParentIdx; + skeleton.m_inverseBindPose[currentIndex] = glm::transpose(*reinterpret_cast(currentJoint.BindPoseInverse.Data)); + skeleton.m_jointNameToIndex[currentJoint.Name] = static_cast(currentIndex); - skeleton.myRestPose[currentIndex].position = { currentJoint.restPosition[0], currentJoint.restPosition[1], currentJoint.restPosition[2] }; + skeleton.m_restPose[currentIndex].position = { currentJoint.restPosition[0], currentJoint.restPosition[1], currentJoint.restPosition[2] }; - skeleton.myRestPose[currentIndex].rotation.x = currentJoint.restRotation[0]; - skeleton.myRestPose[currentIndex].rotation.y = currentJoint.restRotation[1]; - skeleton.myRestPose[currentIndex].rotation.z = currentJoint.restRotation[2]; - skeleton.myRestPose[currentIndex].rotation.w = currentJoint.restRotation[3]; + skeleton.m_restPose[currentIndex].rotation.x = currentJoint.restRotation[0]; + skeleton.m_restPose[currentIndex].rotation.y = currentJoint.restRotation[1]; + skeleton.m_restPose[currentIndex].rotation.z = currentJoint.restRotation[2]; + skeleton.m_restPose[currentIndex].rotation.w = currentJoint.restRotation[3]; - skeleton.myRestPose[currentIndex].scale = { currentJoint.restScale[0], currentJoint.restScale[1], currentJoint.restScale[2] }; + skeleton.m_restPose[currentIndex].scale = { currentJoint.restScale[0], currentJoint.restScale[1], currentJoint.restScale[2] }; for (const auto& child : currentJoint.Children) { diff --git a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp index e0fc82e75..1f6373b04 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp @@ -28,8 +28,6 @@ namespace Volt const auto filePath = AssetManager::GetFilesystemPath(metadata.filePath); - Ref prefabScene = CreateRef(); - YAMLFileStreamReader streamReader{}; if (!streamReader.OpenFile(filePath)) { @@ -38,6 +36,8 @@ namespace Volt return false; } + Ref prefabScene = CreateRef(); + streamReader.EnterScope("Prefab"); { prefab->m_version = streamReader.ReadKey("version", uint32_t(0)); diff --git a/Volt/Volt/src/Volt/Asset/Importers/SkeletonImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/SkeletonImporter.cpp index 5d924236d..fc892e13a 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/SkeletonImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/SkeletonImporter.cpp @@ -61,25 +61,39 @@ namespace Volt return false; } - VT_DESERIALIZE_PROPERTY(name, skeleton->myName, skeletonNode, std::string("Null")); + VT_DESERIALIZE_PROPERTY(name, skeleton->m_name, skeletonNode, std::string("Null")); YAML::Node jointsNode = skeletonNode["joints"]; if (jointsNode) { for (const auto& jointNode : jointsNode) { - auto& joint = skeleton->myJoints.emplace_back(); + auto& joint = skeleton->m_joints.emplace_back(); VT_DESERIALIZE_PROPERTY(parentIndex, joint.parentIndex, jointNode, -1); VT_DESERIALIZE_PROPERTY(name, joint.name, jointNode, std::string("Null")); } } + YAML::Node jointAttachmentsNode = skeletonNode["jointAttachments"]; + if (jointAttachmentsNode) + { + for (const auto& attachmentNode : jointAttachmentsNode) + { + auto& attachment = skeleton->m_jointAttachments.emplace_back(); + VT_DESERIALIZE_PROPERTY(name, attachment.name, attachmentNode, std::string("")); + VT_DESERIALIZE_PROPERTY(jointIndex, attachment.jointIndex, attachmentNode, int32_t(-1)); + VT_DESERIALIZE_PROPERTY(id, attachment.id, attachmentNode, UUID(0)); + VT_DESERIALIZE_PROPERTY(positionOffset, attachment.positionOffset, attachmentNode, glm::vec3(0.f)); + VT_DESERIALIZE_PROPERTY(rotationOffset, attachment.rotationOffset, attachmentNode, glm::quat(1.f, 0.f, 0.f, 0.f)); + } + } + YAML::Node invBindPosesNode = skeletonNode["inverseBindPoses"]; if (invBindPosesNode) { for (const auto& invBindPoseNode : invBindPosesNode) { - VT_DESERIALIZE_PROPERTY(invBindPose, skeleton->myInverseBindPose.emplace_back(), invBindPoseNode, glm::mat4(1.f)); + VT_DESERIALIZE_PROPERTY(invBindPose, skeleton->m_inverseBindPose.emplace_back(), invBindPoseNode, glm::mat4(1.f)); } } @@ -88,7 +102,7 @@ namespace Volt { for (const auto& transform : restPoseNode) { - auto& trs = skeleton->myRestPose.emplace_back(); + auto& trs = skeleton->m_restPose.emplace_back(); VT_DESERIALIZE_PROPERTY(position, trs.position, transform, glm::vec3{ 0.f }); VT_DESERIALIZE_PROPERTY(rotation, trs.rotation, transform, glm::quat{}); VT_DESERIALIZE_PROPERTY(scale, trs.scale, transform, glm::vec3{ 1.f }); @@ -107,10 +121,10 @@ namespace Volt out << YAML::Key << "Skeleton" << YAML::Value; { out << YAML::BeginMap; - VT_SERIALIZE_PROPERTY(name, skeleton->myName, out); + VT_SERIALIZE_PROPERTY(name, skeleton->m_name, out); out << YAML::Key << "joints" << YAML::BeginSeq; - for (const auto& joint : skeleton->myJoints) + for (const auto& joint : skeleton->m_joints) { out << YAML::BeginMap; VT_SERIALIZE_PROPERTY(parentIndex, joint.parentIndex, out); @@ -119,8 +133,21 @@ namespace Volt } out << YAML::EndSeq; + out << YAML::Key << "jointAttachments" << YAML::BeginSeq; + for (const auto& attachment : skeleton->m_jointAttachments) + { + out << YAML::BeginMap; + VT_SERIALIZE_PROPERTY(name, attachment.name, out); + VT_SERIALIZE_PROPERTY(jointIndex, attachment.jointIndex, out); + VT_SERIALIZE_PROPERTY(id, attachment.id, out); + VT_SERIALIZE_PROPERTY(positionOffset, attachment.positionOffset, out); + VT_SERIALIZE_PROPERTY(rotationOffset, attachment.rotationOffset, out); + out << YAML::EndMap; + } + out << YAML::EndSeq; + out << YAML::Key << "inverseBindPoses" << YAML::BeginSeq; - for (const auto& invBindPose : skeleton->myInverseBindPose) + for (const auto& invBindPose : skeleton->m_inverseBindPose) { out << YAML::BeginMap; VT_SERIALIZE_PROPERTY(invBindPose, invBindPose, out); @@ -129,7 +156,7 @@ namespace Volt out << YAML::EndSeq; out << YAML::Key << "restPose" << YAML::BeginSeq; - for (const auto& restPose : skeleton->myRestPose) + for (const auto& restPose : skeleton->m_restPose) { out << YAML::BeginMap; VT_SERIALIZE_PROPERTY(position, restPose.position, out); diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/AnimationSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/AnimationSerializer.cpp index 62195a4c9..2fd461ebc 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/AnimationSerializer.cpp +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/AnimationSerializer.cpp @@ -34,9 +34,9 @@ namespace Volt BinaryStreamWriter streamWriter{}; AnimationSerializationData serializationData{}; - serializationData.duration = animation->myDuration; - serializationData.framesPerSecond = animation->myFramesPerSecond; - serializationData.frames = animation->myFrames; + serializationData.duration = animation->m_duration; + serializationData.framesPerSecond = animation->m_framesPerSecond; + serializationData.frames = animation->m_frames; const size_t compressedDataOffset = AssetSerializer::WriteMetadata(metadata, asset->GetVersion(), streamWriter); streamWriter.Write(serializationData); @@ -73,9 +73,9 @@ namespace Volt Ref animation = std::reinterpret_pointer_cast(destinationAsset); - animation->myDuration = serializationData.duration; - animation->myFramesPerSecond = serializationData.framesPerSecond; - animation->myFrames = serializationData.frames; + animation->m_duration = serializationData.duration; + animation->m_framesPerSecond = serializationData.framesPerSecond; + animation->m_frames = serializationData.frames; return true; } diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SkeletonSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/SkeletonSerializer.cpp index 75891bef6..a7a5ac46f 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/SkeletonSerializer.cpp +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SkeletonSerializer.cpp @@ -10,6 +10,7 @@ namespace Volt { std::string name; std::vector joints; + std::vector jointAttachments; std::vector inverseBindPose; std::vector restPose; @@ -17,6 +18,7 @@ namespace Volt { streamWriter.Write(data.name); streamWriter.Write(data.joints); + streamWriter.Write(data.jointAttachments); streamWriter.Write(data.inverseBindPose); streamWriter.WriteRaw(data.restPose); } @@ -25,6 +27,7 @@ namespace Volt { streamReader.Read(outData.name); streamReader.Read(outData.joints); + streamReader.Read(outData.jointAttachments); streamReader.Read(outData.inverseBindPose); streamReader.ReadRaw(outData.restPose); } @@ -36,10 +39,11 @@ namespace Volt BinaryStreamWriter streamWriter{}; SkeletonSerializationData serializationData{}; - serializationData.name = skeleton->myName; - serializationData.joints = skeleton->myJoints; - serializationData.inverseBindPose = skeleton->myInverseBindPose; - serializationData.restPose = skeleton->myRestPose; + serializationData.name = skeleton->m_name; + serializationData.joints = skeleton->m_joints; + serializationData.jointAttachments = skeleton->m_jointAttachments; + serializationData.inverseBindPose = skeleton->m_inverseBindPose; + serializationData.restPose = skeleton->m_restPose; const size_t compressedDataOffset = AssetSerializer::WriteMetadata(metadata, asset->GetVersion(), streamWriter); streamWriter.Write(serializationData); @@ -76,10 +80,11 @@ namespace Volt Ref skeleton = std::reinterpret_pointer_cast(destinationAsset); - skeleton->myName = serializationData.name; - skeleton->myJoints = serializationData.joints; - skeleton->myInverseBindPose = serializationData.inverseBindPose; - skeleton->myRestPose = serializationData.restPose; + skeleton->m_name = serializationData.name; + skeleton->m_joints = serializationData.joints; + skeleton->m_jointAttachments = serializationData.jointAttachments; + skeleton->m_inverseBindPose = serializationData.inverseBindPose; + skeleton->m_restPose = serializationData.restPose; return true; } diff --git a/Volt/Volt/src/Volt/Audio/AudioSystem.cpp b/Volt/Volt/src/Volt/Audio/AudioSystem.cpp index 9f7a5777d..4aeb9ae23 100644 --- a/Volt/Volt/src/Volt/Audio/AudioSystem.cpp +++ b/Volt/Volt/src/Volt/Audio/AudioSystem.cpp @@ -6,6 +6,7 @@ #include "Volt/Scene/Entity.h" #include +#include #include #include @@ -27,11 +28,11 @@ void Volt::AudioSystem::RuntimeStart(entt::registry& registry, Weak scene // Listeners { - auto view = registry.view(); - view.each([&](entt::entity id, AudioListenerComponent& audioListenerComp) + auto view = registry.view(); + view.each([&](entt::entity id, AudioListenerComponent& audioListenerComp, const IDComponent& idComponent) { Volt::Entity entity({ id, scene }); - Amp::WwiseAudioManager::RegisterListener(static_cast(id), entity.GetTag().c_str(), audioListenerComp.isDefault); + Amp::WwiseAudioManager::RegisterListener(idComponent.id, entity.GetTag().c_str(), audioListenerComp.isDefault); }); } } diff --git a/Volt/Volt/src/Volt/Components/AudioComponents.h b/Volt/Volt/src/Volt/Components/AudioComponents.h index 2af1498e5..f5ff907bd 100644 --- a/Volt/Volt/src/Volt/Components/AudioComponents.h +++ b/Volt/Volt/src/Volt/Components/AudioComponents.h @@ -25,7 +25,7 @@ namespace Volt { bool isDefault = true; - void OnCreate(entt::entity entityID) + void OnCreate(EntityID entityID) { m_id = entityID; Amp::WwiseAudioManager::RegisterListener(static_cast(m_id), std::to_string(static_cast(m_id)).c_str(), isDefault); @@ -41,19 +41,21 @@ namespace Volt REGISTER_COMPONENT(AudioListenerComponent); private: - entt::entity m_id = entt::null; + EntityID m_id = Entity::NullID(); }; struct AudioSourceComponent { - void OnCreate(entt::entity entityID) + void OnCreate(EntityID entityID) { Amp::WwiseAudioManager::CreateAudioObject(static_cast(entityID), "SpawnedObj"); + m_id = entityID; } void OnStart(Volt::Entity entity) { - Amp::WwiseAudioManager::CreateAudioObject(entity, entity.GetTag().c_str()); + Amp::WwiseAudioManager::CreateAudioObject(entity.GetID(), entity.GetTag().c_str()); + m_id = entity.GetID(); } bool PlayOneshotEvent(const char* aEventName, const glm::vec3& aPosition, const glm::vec3& aForward, const glm::vec3& aUp) @@ -117,7 +119,7 @@ namespace Volt REGISTER_COMPONENT(AudioSourceComponent); private: - entt::entity m_id = entt::null; + EntityID m_id = Entity::NullID(); }; } diff --git a/Volt/Volt/src/Volt/Components/PhysicsComponents.h b/Volt/Volt/src/Volt/Components/PhysicsComponents.h index 37325e67d..6abad1e8f 100644 --- a/Volt/Volt/src/Volt/Components/PhysicsComponents.h +++ b/Volt/Volt/src/Volt/Components/PhysicsComponents.h @@ -20,11 +20,15 @@ namespace Volt uint32_t layer = 0; bool hasGravity = true; - inline CharacterControllerComponent(ClimbingMode aClimbingMode = ClimbingMode::Normal, float aSlopeLimit = 20.f, float aInvisibleWallHeight = 200.f, float aMaxJumpHeight = 100.f, - float aContactOffset = 1.f, float aStepOffset = 10.f, float aDensity = 1.f, uint32_t aLayer = 0, bool aHasGravity = true) + inline CharacterControllerComponent() = default; + + inline CharacterControllerComponent(ClimbingMode aClimbingMode, float aSlopeLimit, float aInvisibleWallHeight, float aMaxJumpHeight, + float aContactOffset, float aStepOffset, float aDensity, uint32_t aLayer, bool aHasGravity) : climbingMode(aClimbingMode), slopeLimit(aSlopeLimit), invisibleWallHeight(aInvisibleWallHeight), maxJumpHeight(aMaxJumpHeight), contactOffset(aContactOffset), stepOffset(aStepOffset), density(aDensity), layer(aLayer), hasGravity(aHasGravity) - { } + { + layer = aLayer; + } static void ReflectType(TypeDesc& reflect) { diff --git a/Volt/Volt/src/Volt/Net/SceneInteraction/GameModeComponent.h b/Volt/Volt/src/Volt/Net/SceneInteraction/GameModeComponent.h index a395f220c..664c3aec1 100644 --- a/Volt/Volt/src/Volt/Net/SceneInteraction/GameModeComponent.h +++ b/Volt/Volt/src/Volt/Net/SceneInteraction/GameModeComponent.h @@ -14,7 +14,7 @@ namespace Volt { reflect.SetGUID("{639786CE-6DE3-4D57-8A00-2C5A0934830A}"_guid); reflect.SetLabel("Game Mode Component"); - reflect.AddMember(&GameModeComponent::prefabHandle, "prefabHandle", "Prefab", "", Asset::Null(), AssetType::Prefab); + reflect.AddMember(&GameModeComponent::prefabHandle, "prefabHandle", "Player", "", Asset::Null(), AssetType::Prefab); reflect.AddMember(&GameModeComponent::enemy, "enemy", "Enemy", "", Asset::Null(), AssetType::Prefab); } diff --git a/Volt/Volt/src/Volt/Physics/PhysicsControllerActor.cpp b/Volt/Volt/src/Volt/Physics/PhysicsControllerActor.cpp index 3a429b37c..936559df6 100644 --- a/Volt/Volt/src/Volt/Physics/PhysicsControllerActor.cpp +++ b/Volt/Volt/src/Volt/Physics/PhysicsControllerActor.cpp @@ -19,7 +19,6 @@ namespace Volt PhysicsControllerActor::PhysicsControllerActor(Entity entity) : PhysicsActorBase(entity), myGravity(glm::length(Physics::GetSettings().gravity)) { - myControllerData = myEntity.GetComponent(); } PhysicsControllerActor::~PhysicsControllerActor() @@ -222,6 +221,7 @@ namespace Volt void PhysicsControllerActor::CreateController(physx::PxControllerManager* controllerManager) { + myControllerData = myEntity.GetComponent(); if (myEntity.HasComponent()) { auto& capsuleCollider = myEntity.GetComponent(); diff --git a/Volt/Volt/src/Volt/Physics/PhysicsScene.cpp b/Volt/Volt/src/Volt/Physics/PhysicsScene.cpp index 8ce052002..09b89390e 100644 --- a/Volt/Volt/src/Volt/Physics/PhysicsScene.cpp +++ b/Volt/Volt/src/Volt/Physics/PhysicsScene.cpp @@ -132,12 +132,9 @@ namespace Volt Ref PhysicsScene::GetActor(Entity entity) { - for (const auto& actor : myPhysicsActors) + if (m_physicsActorFromEntityIDMap.contains(entity.GetHandle())) { - if (actor->GetEntity().GetID() == entity.GetID()) - { - return actor; - } + return m_physicsActorFromEntityIDMap.at(entity.GetHandle()); } return nullptr; @@ -145,12 +142,9 @@ namespace Volt const Ref PhysicsScene::GetActor(Entity entity) const { - for (const auto& actor : myPhysicsActors) + if (m_physicsActorFromEntityIDMap.contains(entity.GetHandle())) { - if (actor->GetEntity().GetID() == entity.GetID()) - { - return actor; - } + return m_physicsActorFromEntityIDMap.at(entity.GetHandle()); } return nullptr; @@ -158,12 +152,9 @@ namespace Volt Ref PhysicsScene::GetControllerActor(Entity entity) { - for (const auto& actor : myControllerActors) + if (m_physicsControllerActorFromEntityIDMap.contains(entity.GetHandle())) { - if (actor->GetEntity().GetID() == entity.GetID()) - { - return actor; - } + return m_physicsControllerActorFromEntityIDMap.at(entity.GetHandle()); } return nullptr; @@ -171,12 +162,9 @@ namespace Volt const Ref PhysicsScene::GetControllerActor(Entity entity) const { - for (const auto& actor : myControllerActors) + if (m_physicsControllerActorFromEntityIDMap.contains(entity.GetHandle())) { - if (actor->GetEntity().GetID() == entity.GetID()) - { - return actor; - } + return m_physicsControllerActorFromEntityIDMap.at(entity.GetHandle()); } return nullptr; @@ -187,6 +175,8 @@ namespace Volt Ref actor = CreateRef(entity); myPhysicsActors.emplace_back(actor); + m_physicsActorFromEntityIDMap[entity.GetHandle()] = actor; + auto func = [&, addedEntity = entity]() { auto addedActor = GetActor(addedEntity); @@ -232,21 +222,29 @@ namespace Volt func(); } - auto it = std::find_if(myPhysicsActors.begin(), myPhysicsActors.end(), [actor](const Ref& a) + auto actorEntityHandle = actor->GetEntity().GetHandle(); + + auto it = std::find_if(myPhysicsActors.begin(), myPhysicsActors.end(), [actorEntityHandle](const Ref& a) { - return actor->GetEntity().GetID() == a->GetEntity().GetID(); + return a->GetEntity().GetHandle() == actorEntityHandle; }); if (it != myPhysicsActors.end()) { myPhysicsActors.erase(it); } + + if (m_physicsActorFromEntityIDMap.contains(actorEntityHandle)) + { + m_physicsActorFromEntityIDMap.erase(actorEntityHandle); + } } Ref PhysicsScene::CreateControllerActor(Entity entity) { Ref actor = CreateRef(entity); myControllerActors.emplace_back(actor); + m_physicsControllerActorFromEntityIDMap[entity.GetHandle()] = actor; auto func = [&, addedEntity = entity]() { @@ -269,17 +267,22 @@ namespace Volt void PhysicsScene::RemoveControllerActor(Ref controllerActor) { - auto it = std::find_if(myControllerActors.begin(), myControllerActors.end(), [&, controllerActor](const auto& lhs) + auto actorEntityHandle = controllerActor->GetEntity().GetHandle(); + + auto it = std::find_if(myControllerActors.begin(), myControllerActors.end(), [actorEntityHandle](const auto& lhs) { - return lhs->GetEntity().GetID() == controllerActor->GetEntity().GetID(); + return lhs->GetEntity().GetHandle() == actorEntityHandle; }); - if (it == myControllerActors.end()) + if (it != myControllerActors.end()) { - return; + myControllerActors.erase(it); } - myControllerActors.erase(it); + if (m_physicsControllerActorFromEntityIDMap.contains(actorEntityHandle)) + { + m_physicsControllerActorFromEntityIDMap.erase(actorEntityHandle); + } } bool PhysicsScene::Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* outHit) diff --git a/Volt/Volt/src/Volt/Physics/PhysicsScene.h b/Volt/Volt/src/Volt/Physics/PhysicsScene.h index 4234b391f..80d095c77 100644 --- a/Volt/Volt/src/Volt/Physics/PhysicsScene.h +++ b/Volt/Volt/src/Volt/Physics/PhysicsScene.h @@ -71,6 +71,9 @@ namespace Volt std::vector> myPhysicsActors; std::vector> myControllerActors; + std::unordered_map> m_physicsActorFromEntityIDMap; + std::unordered_map> m_physicsControllerActorFromEntityIDMap; + std::vector> myFunctionQueue; Scene* myEntityScene; diff --git a/Volt/Volt/src/Volt/Scene/Entity.h b/Volt/Volt/src/Volt/Scene/Entity.h index b859485b2..4076ed611 100644 --- a/Volt/Volt/src/Volt/Scene/Entity.h +++ b/Volt/Volt/src/Volt/Scene/Entity.h @@ -183,7 +183,7 @@ namespace Volt { auto scenePtr = GetScene(); auto& registry = scenePtr->GetRegistry(); - return registry.emplace(m_handle); + return registry.emplace(m_handle, std::forward(args)...); } template diff --git a/Volt/Volt/src/Volt/Scene/Scene.cpp b/Volt/Volt/src/Volt/Scene/Scene.cpp index 5266c006c..0fe41221c 100644 --- a/Volt/Volt/src/Volt/Scene/Scene.cpp +++ b/Volt/Volt/src/Volt/Scene/Scene.cpp @@ -462,7 +462,9 @@ namespace Volt void Scene::RemoveEntity(Entity entity) { std::scoped_lock lock{ m_removeEntityMutex }; - m_entityRemoveQueue.push_back(entity.GetID()); + RemoveEntityInternal(entity, false); + SortScene(); + //m_entityRemoveQueue.push_back(entity.GetID()); } void Scene::ParentEntity(Entity parent, Entity child) @@ -1121,7 +1123,9 @@ namespace Volt } AudioSourceComponent& comp = registry.get(id); - comp.OnCreate(id); + const IDComponent& idComp = registry.get(id); + + comp.OnCreate(idComp.id); } void Scene::AudioListenerComponent_OnCreate(entt::registry& registry, entt::entity id) @@ -1132,7 +1136,8 @@ namespace Volt } AudioListenerComponent& comp = registry.get(id); - comp.OnCreate(id); + const IDComponent& idComp = registry.get(id); + comp.OnCreate(idComp.id); } void Scene::CameraComponent_OnCreate(entt::registry& registry, entt::entity id) diff --git a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptEngine.cpp b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptEngine.cpp index 78663e399..66cd5e177 100644 --- a/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptEngine.cpp +++ b/Volt/Volt/src/Volt/Scripting/Mono/MonoScriptEngine.cpp @@ -516,6 +516,11 @@ namespace Volt if (fieldInstance->field.type.IsEntity()) { EntityID fieldEnt = *fieldInstance->data.As(); + if (fieldEnt == Entity::NullID()) + { + continue; + } + auto fieldEntInstance = GetOrCreateMonoEntity(fieldEnt); auto instanceObject = MonoGCManager::GetObjectFromHandle(instance->GetHandle()); diff --git a/Volt/Volt/vendor/imgui-node-editor/imgui_node_editor.cpp b/Volt/Volt/vendor/imgui-node-editor/imgui_node_editor.cpp index f6ea263af..4fda7a767 100644 --- a/Volt/Volt/vendor/imgui-node-editor/imgui_node_editor.cpp +++ b/Volt/Volt/vendor/imgui-node-editor/imgui_node_editor.cpp @@ -2090,7 +2090,9 @@ ed::Control ed::EditorContext::BuildControl(bool allowOffscreen) auto emitInteractiveArea = [](ObjectId id, const ImRect& rect) { char idString[33] = { 0 }; // itoa can output 33 bytes maximum - snprintf(idString, 32, "%p", id.AsPointer()); + void* ptr = id.AsPointer(); + + snprintf(idString, 32, "%p", ptr); ImGui::SetCursorScreenPos(rect.Min); // debug