diff --git a/CMakeLists.txt b/CMakeLists.txt index 723d56b..3ffc3fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.28) # DevTools -project(devtools VERSION 0.1.15 +project(devtools VERSION 0.1.16 DESCRIPTION "Sonic Frontiers DevTools" LANGUAGES CXX) diff --git a/rangers-sdk b/rangers-sdk index e595a0d..00c1285 160000 --- a/rangers-sdk +++ b/rangers-sdk @@ -1 +1 @@ -Subproject commit e595a0d26d112041fff3269493b52bde8c02ffa1 +Subproject commit 00c1285ea9af5d816ef3150e54d33e2b03714360 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c8400f..5c3f7ea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(devtools ui/core-services/GraphicsContextInspector.cpp ui/core-services/MemoryInspector.cpp ui/Desktop.cpp + ui/game-modes/GameModeInspector.cpp ui/game-services/GameServiceInspector.cpp ui/operation-modes/LevelEditor/LevelEditor.cpp ui/operation-modes/LevelEditor/ObjectDataInspector.cpp @@ -33,6 +34,7 @@ target_sources(devtools ui/operation-modes/ObjectInspection/ObjectInspection.cpp ui/operation-modes/ObjectInspection/ObjectInspector.cpp ui/operation-modes/ObjectInspection/ObjectList.cpp + ui/operation-modes/SurfRideEditor/SurfRideEditor.cpp ui/operation-modes/OperationMode.cpp ui/resources/editors/ResEffectEditor.cpp ui/resources/editors/ResObjectWorldEditor.cpp @@ -76,6 +78,7 @@ target_sources(devtools ui/Desktop.h ui/fonts/FiraCode.h ui/fonts/Inter.h + ui/game-modes/GameModeInspector.h ui/game-services/GameServiceInspector.h ui/operation-modes/LevelEditor/LevelEditor.h ui/operation-modes/LevelEditor/ObjectDataInspector.h @@ -84,6 +87,7 @@ target_sources(devtools ui/operation-modes/ObjectInspection/ObjectInspection.h ui/operation-modes/ObjectInspection/ObjectInspector.h ui/operation-modes/ObjectInspection/ObjectList.h + ui/operation-modes/SurfRideEditor/SurfRideEditor.h ui/operation-modes/OperationMode.h ui/resources/editors/ResEffectEditor.h ui/resources/editors/ResObjectWorldEditor.h diff --git a/src/ui/Desktop.cpp b/src/ui/Desktop.cpp index 0744b80..863efcb 100644 --- a/src/ui/Desktop.cpp +++ b/src/ui/Desktop.cpp @@ -108,8 +108,10 @@ void Desktop::HandleMousePicking() auto cameraMatrix{ camera->viewportData.projMatrix * camera->viewportData.viewMatrix }; auto inverseCameraMatrix{ cameraMatrix.inverse() }; auto* ivp = ImGui::GetMainViewport(); - auto topLeft = ImGui::GetMousePos() - ImGui::GetMouseDragDelta(); - auto botRight = ImGui::GetMousePos(); + auto mouseStart = ImGui::GetMousePos() - ImGui::GetMouseDragDelta(); + auto mouseEnd = ImGui::GetMousePos(); + auto topLeft = ImVec2{ std::fminf(mouseStart.x, mouseEnd.x), std::fminf(mouseStart.y, mouseEnd.y) }; + auto botRight = ImVec2{ std::fmaxf(mouseStart.x, mouseEnd.x), std::fmaxf(mouseStart.y, mouseEnd.y) }; ImGui::SetNextWindowSize(ivp->Size); ImGui::SetNextWindowPos(ivp->Pos); diff --git a/src/ui/ToolBar.cpp b/src/ui/ToolBar.cpp index 78df049..f8d6c6f 100644 --- a/src/ui/ToolBar.cpp +++ b/src/ui/ToolBar.cpp @@ -3,6 +3,7 @@ #include "Desktop.h" #include "SettingsManager.h" #include "resources/ResourceBrowser.h" +#include "game-modes/GameModeInspector.h" #include "game-services/GameServiceInspector.h" #include "core-services/GameUpdaterInspector.h" #include "core-services/GraphicsContextInspector.h" @@ -52,6 +53,8 @@ void ToolBar::Render() { new (Desktop::instance->GetAllocator()) CameraManagerInspector(Desktop::instance->GetAllocator()); if (ImGui::MenuItem("Memory")) new (Desktop::instance->GetAllocator()) MemoryInspector(Desktop::instance->GetAllocator()); + if (ImGui::MenuItem("GameMode")) + new (Desktop::instance->GetAllocator()) GameModeInspector(Desktop::instance->GetAllocator()); ImGui::EndMenu(); } @@ -94,7 +97,7 @@ void ToolBar::Render() { ImGui::SetItemTooltip("Pauses (almost) every object layer. (Hotkey: F4)"); ImGui::SameLine(); - gameUpdater.flags.m_dummy = static_cast(gameUpdaterFlags); + gameUpdater.flags.m_dummy = gameUpdaterFlags; if (ImGui::Button("Step frame")) gameUpdater.flags.set(GameUpdater::Flags::DEBUG_STEP_FRAME); diff --git a/src/ui/common/ReflectionEditor.cpp b/src/ui/common/ReflectionEditor.cpp index 1a9fe13..d1c4ead 100644 --- a/src/ui/common/ReflectionEditor.cpp +++ b/src/ui/common/ReflectionEditor.cpp @@ -263,10 +263,10 @@ void ReflectionEditor::RenderPrimitiveEditor(const char* name, void* obj, const RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_U32, 1); break; case RflClassMember::TYPE_SINT64: - RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_S64, 1); + RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_S64, 1); break; case RflClassMember::TYPE_UINT64: - RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_U64, 1); + RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_U64, 1); break; case RflClassMember::TYPE_FLOAT: RenderScalarRflParamEditor(name, obj, member, ImGuiDataType_Float, 1); diff --git a/src/ui/common/ReflectionEditor.h b/src/ui/common/ReflectionEditor.h index c6b7e81..0e6a299 100644 --- a/src/ui/common/ReflectionEditor.h +++ b/src/ui/common/ReflectionEditor.h @@ -25,11 +25,19 @@ class ReflectionEditor { }; template<> class range_info { public: - static constexpr const char* name = "RangeSInt32"; + static constexpr const char* name = "RangeSint32"; }; template<> class range_info { public: - static constexpr const char* name = "RangeUInt32"; + static constexpr const char* name = "RangeUint32"; + }; + template<> class range_info { + public: + static constexpr const char* name = "RangeSint64"; + }; + template<> class range_info { + public: + static constexpr const char* name = "RangeUint64"; }; template<> class range_info { public: diff --git a/src/ui/common/SimpleWidgets.h b/src/ui/common/SimpleWidgets.h index 55936be..8cdef73 100644 --- a/src/ui/common/SimpleWidgets.h +++ b/src/ui/common/SimpleWidgets.h @@ -20,16 +20,16 @@ void InputText(const char* label, hh::needle::intrusive_ptr -void CheckboxFlags(const char* label, csl::ut::Bitset* v, T value) { - ImGui::CheckboxFlags(label, reinterpret_cast*>(&v->m_dummy), static_cast>(1) << static_cast>(value)); +template +void CheckboxFlags(const char* label, csl::ut::Bitset* v, T value) { + ImGui::CheckboxFlags(label, &v->m_dummy, static_cast(1) << static_cast(value)); } -template -void CheckboxFlagsLT32(const char* label, csl::ut::Bitset* v, T value) { - int v2 = static_cast>(v->m_dummy); - ImGui::CheckboxFlags(label, &v2, static_cast>(1) << static_cast>(value)); - *v = static_cast(static_cast>(v2)); +template +void CheckboxFlagsLT32(const char* label, csl::ut::Bitset* v, T value) { + int v2 = v->m_dummy; + ImGui::CheckboxFlags(label, &v2, static_cast(1) << static_cast(value)); + *v = static_cast(v2); } template diff --git a/src/ui/core-services/GameUpdaterInspector.cpp b/src/ui/core-services/GameUpdaterInspector.cpp index 517dbb7..aff286a 100644 --- a/src/ui/core-services/GameUpdaterInspector.cpp +++ b/src/ui/core-services/GameUpdaterInspector.cpp @@ -5,46 +5,62 @@ GameUpdaterInspector::GameUpdaterInspector(csl::fnd::IAllocator* allocator) : St SetTitle("GameUpdater"); } +void GameUpdaterInspector::PreRender() +{ + ImGui::SetNextWindowSize(ImVec2(800, 920), ImGuiCond_Once); +} + void GameUpdaterInspector::RenderContents() { auto& gameUpdater = hh::game::GameApplication::GetInstance()->GetGameUpdater(); - //unsigned int flags = static_cast(gameUpdater.flags.m_dummy); - //ImGui::CheckboxFlags("Unknown pause", &flags, 1); - //ImGui::CheckboxFlags("Full pause", &flags, 2); - //ImGui::CheckboxFlags("flag 2", &flags, 4); - //ImGui::CheckboxFlags("flag 3", &flags, 8); - //ImGui::CheckboxFlags("Step single frame", &flags, 16); - //ImGui::CheckboxFlags("Object pause", &flags, 32); - //ImGui::CheckboxFlags("flag 6", &flags, 64); - //ImGui::CheckboxFlags("flag 7", &flags, 128); - //gameUpdater.flags.m_dummy = static_cast(flags); - - //ImGui::Text("unk7.unk1.unk1: %x", gameUpdater.unk7.unk1.unk1); - //ImGui::Text("unk7.unk1.unk2: %x", gameUpdater.unk7.unk1.unk2); - //ImGui::Text("unk7.unk2.unk1: %x", gameUpdater.unk7.unk2.unk1); - //ImGui::Text("unk7.unk2.unk2: %x", gameUpdater.unk7.unk2.unk2); - - ImGui::Text("layers active during normal operation: %x", gameUpdater.layersActiveDuringNormalOperation); - ImGui::Text("layers active during ingame pause: %x", gameUpdater.layersActiveDuringIngamePause); - ImGui::Text("layers active during debug pause: %x", gameUpdater.layersActiveDuringDebugPause); - ImGui::Text("layers active during object pause: %x", gameUpdater.layersActiveDuringObjectPause); - - //ImGui::DragFloat("unkFloat5", &gameUpdater.unk5); - //ImGui::DragFloat("unkFloat6", &gameUpdater.unk6); - - //for (int i = 0; i < 32; i++) { - // char name[100]; - // snprintf(name, sizeof(name), "unk float for layer %d", i); - // ImGui::DragFloat(name, &gameUpdater.maybeFrameTimes[i]); - //} - - for (int i = 0; i < 32; i++) { - ImGui::Text("updateInfo for layer %d: deltaTime (s): %f, total time (ms): %d, unk2: %x, unk3: %x", i, gameUpdater.updateInfos[i].deltaTime, gameUpdater.updateInfos[i].currentFrame, gameUpdater.updateInfos[i].unk2, gameUpdater.updateInfos[i].unk3); - } + auto* gameManager = hh::game::GameManager::GetInstance(); - //float deltaTimes[32]; + ImGui::DragFloat("FPS", (*reinterpret_cast(0x143D907A0) + 5)); + ImGui::DragFloat("Timescale", &gameUpdater.timeScale, 0.01f); - //for (int i = 0; i < 32; i++) { - // deltaTimes[i] = gameUpdater.unk8[i].deltaTime; - //} + ImGui::SeparatorText("Per-layer information"); + if (ImGui::BeginTable("Layer information", 10, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollX)) { + ImGui::TableSetupColumn("Layer id"); + ImGui::TableSetupColumn("Normal operation"); + ImGui::TableSetupColumn("Ingame pause"); + ImGui::TableSetupColumn("Debug pause"); + ImGui::TableSetupColumn("Object pause"); + ImGui::TableSetupColumn("Timescale"); + ImGui::TableSetupColumn("DeltaTime"); + ImGui::TableSetupColumn("Current frame"); + ImGui::TableSetupColumn("Unk2"); + ImGui::TableSetupColumn("Unk3"); + ImGui::TableHeadersRow(); + + for (size_t i = 0; i < 32; i++) { + char name[20]; + snprintf(name, sizeof(name), "Layer %zd", i); + + ImGui::PushID(i); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%zd", i); + ImGui::TableNextColumn(); + ImGui::CheckboxFlags("##layersActiveDuringNormalOperation", &gameUpdater.layersActiveDuringNormalOperation, 1 << i); + ImGui::TableNextColumn(); + ImGui::CheckboxFlags("##layersActiveDuringIngamePause", &gameUpdater.layersActiveDuringIngamePause, 1 << i); + ImGui::TableNextColumn(); + ImGui::CheckboxFlags("##layersActiveDuringDebugPause", &gameUpdater.layersActiveDuringDebugPause, 1 << i); + ImGui::TableNextColumn(); + ImGui::CheckboxFlags("##layersActiveDuringObjectPause", &gameUpdater.layersActiveDuringObjectPause, 1 << i); + ImGui::TableNextColumn(); + ImGui::DragFloat("##layerTimeScale", &gameUpdater.layerTimeScale[i], 0.01f); + ImGui::TableNextColumn(); + ImGui::Text("%f", gameUpdater.updateInfos[i].deltaTime); + ImGui::TableNextColumn(); + ImGui::Text("%d", gameUpdater.updateInfos[i].currentFrame); + ImGui::TableNextColumn(); + ImGui::Text("%d", gameUpdater.updateInfos[i].unk2); + ImGui::TableNextColumn(); + ImGui::Text("%x", gameUpdater.updateInfos[i].unk3); + ImGui::PopID(); + } + + ImGui::EndTable(); + } } diff --git a/src/ui/core-services/GameUpdaterInspector.h b/src/ui/core-services/GameUpdaterInspector.h index e96991a..98db805 100644 --- a/src/ui/core-services/GameUpdaterInspector.h +++ b/src/ui/core-services/GameUpdaterInspector.h @@ -5,6 +5,6 @@ class GameUpdaterInspector : public StandaloneWindow { public: GameUpdaterInspector(csl::fnd::IAllocator* allocator); - //virtual void PreRender() override; + virtual void PreRender() override; virtual void RenderContents() override; }; diff --git a/src/ui/game-modes/GameModeInspector.cpp b/src/ui/game-modes/GameModeInspector.cpp new file mode 100644 index 0000000..54a5a01 --- /dev/null +++ b/src/ui/game-modes/GameModeInspector.cpp @@ -0,0 +1,94 @@ +#include "GameModeInspector.h" +#include +#include +#include +#include +#include + +using namespace hh::game; + +GameModeInspector::GameModeInspector(csl::fnd::IAllocator* allocator) : StandaloneWindow{ allocator } { + SetTitle("GameMode inspector"); +} + +void GameModeInspector::RenderContents() { + auto* seqExt = static_cast(app::MyApplication::GetInstance())->GetExtension(); + if (!seqExt) + return; + + auto* gameMode = seqExt->GetCurrentGameMode(); + if (!gameMode) + return; + + ImGui::SeparatorText("Extensions"); + for (auto* extension : gameMode->extensions) { + if (extension->GetNameHash() == 0x42983F51) { + auto* ext = static_cast(extension); + + if (ImGui::CollapsingHeader("Layer Status")) { + size_t i; + ImGui::SeparatorText("Active layers during normal operation override stack"); + i = 0; + for (auto& d : ext->layersActiveDuringNormalOperation) { + if (ImGui::TreeNodeEx(&d, ImGuiTreeNodeFlags_None, "Stack item %d", i++)) { + for (size_t j = 0; j < 32; j++) { + char name[20]; + snprintf(name, sizeof(name), "Layer %zd", j); + + ImGui::CheckboxFlags(name, &d.unk3, 1 << j); + } + ImGui::TreePop(); + } + } + + ImGui::SeparatorText("Active layers during ingame pause override stack"); + i = 0; + for (auto& d : ext->layersActiveDuringIngamePause) { + if (ImGui::TreeNodeEx(&d, ImGuiTreeNodeFlags_None, "Stack item %d", i++)) { + for (size_t j = 0; j < 32; j++) { + char name[20]; + snprintf(name, sizeof(name), "Layer %zd", j); + + ImGui::CheckboxFlags(name, &d.unk3, 1 << j); + } + ImGui::TreePop(); + } + } + + ImGui::SeparatorText("Global timescale interpolator stack"); + ImGui::DragFloat("Timescale", &ext->globalInterpolator.timeScale); + i = 0; + for (auto& d : ext->globalInterpolator.unk1) { + if (ImGui::TreeNodeEx(&d, ImGuiTreeNodeFlags_None, "Interpolator %d", i++)) { + ImGui::DragFloat("Timescale", &d.timeScale, 0.01f); + ImGui::DragFloat("Current delta", &d.currentDelta, 0.01f); + ImGui::DragFloat("Increment per second", &d.incrementPerSecond, 0.01f); + ImGui::Text("Delegate count: %zd", d.unk3.functors.size()); + ImGui::TreePop(); + } + } + + ImGui::SeparatorText("Per-layer timescale interpolator stacks"); + i = 0; + for (auto& interpolator : ext->timeScaleInterpolators) { + if (ImGui::TreeNodeEx(&interpolator, ImGuiTreeNodeFlags_None, "Layer %d", i++)) { + ImGui::DragFloat("Timescale", &interpolator.timeScale); + + size_t j = 0; + for (auto& d : interpolator.unk1) { + if (ImGui::TreeNodeEx(&d, ImGuiTreeNodeFlags_None, "Interpolator %d", j++)) { + ImGui::DragFloat("Timescale", &d.timeScale, 0.01f); + ImGui::DragFloat("Current delta", &d.currentDelta, 0.01f); + ImGui::DragFloat("Increment per second", &d.incrementPerSecond, 0.01f); + ImGui::Text("Delegate count: %zd", d.unk3.functors.size()); + ImGui::TreePop(); + } + } + + ImGui::TreePop(); + } + } + } + } + } +} diff --git a/src/ui/game-modes/GameModeInspector.h b/src/ui/game-modes/GameModeInspector.h new file mode 100644 index 0000000..33356d3 --- /dev/null +++ b/src/ui/game-modes/GameModeInspector.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +class GameModeInspector : public StandaloneWindow +{ +public: + GameModeInspector(csl::fnd::IAllocator* allocator); + virtual void RenderContents() override; +}; diff --git a/src/ui/game-services/GameServiceInspector.cpp b/src/ui/game-services/GameServiceInspector.cpp index 7c48dc9..80df91a 100644 --- a/src/ui/game-services/GameServiceInspector.cpp +++ b/src/ui/game-services/GameServiceInspector.cpp @@ -83,7 +83,7 @@ void GameServiceInspector::RenderObjectWorldInspector(hh::game::ObjectWorld& obj ImGui::CheckboxFlags("Started", &flags, 1 << static_cast(WorldObjectStatus::Flag::STARTED)); ImGui::CheckboxFlags("No restart", &flags, 1 << static_cast(WorldObjectStatus::Flag::NO_RESTART)); - status.flags.m_dummy = static_cast(flags); + status.flags.m_dummy = flags; ImGui::InputInt("Spawn priority", &status.spawnPriority); diff --git a/src/ui/operation-modes/ObjectInspection/ObjectInspector.cpp b/src/ui/operation-modes/ObjectInspection/ObjectInspector.cpp index 0030e44..028b3e4 100644 --- a/src/ui/operation-modes/ObjectInspection/ObjectInspector.cpp +++ b/src/ui/operation-modes/ObjectInspection/ObjectInspector.cpp @@ -30,9 +30,10 @@ void ObjectInspector::Render() { auto focusedObject = objectInspection.focusedObjects[0]; ImGui::Text("Object name: %s", focusedObject->name.c_str()); ImGui::Text("Layer: %d", focusedObject->layer); + ImGui::Text("Class: %s", focusedObject->objectClass->name); ImGui::Separator(); if (ImGui::BeginTabBar("Inspector types")) { - if (ImGui::BeginTabItem("Components")) { + if (ImGui::BeginTabItem("Properties")) { if (ImGui::BeginChild("Content")) { for (auto* component : focusedObject->components) { ImGui::PushID(component); @@ -40,8 +41,101 @@ void ObjectInspector::Render() { char title[200]; snprintf(title, 200, "%s (%s)", component->pStaticClass->pName, component->pStaticClass->dynamicName); - if (ImGui::CollapsingHeader(title)) { + if (ImGui::CollapsingHeader(title)) RenderComponentInspector(*component); + + ImGui::PopID(); + } + } + ImGui::EndChild(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Update configuration")) { + if (ImGui::BeginChild("Content")) { + ImGui::Text("GameObject requested update phases:"); + ImGui::BeginGroup(); + CheckboxFlagsLT32("PreAnim", &focusedObject->forcedUpdateFlags, UpdatingPhase::PRE_ANIM); + if (ImGui::IsItemEdited()) + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::PRE_ANIM); + ImGui::SameLine(); + CheckboxFlagsLT32("PostAnim", &focusedObject->forcedUpdateFlags, UpdatingPhase::POST_ANIM); + if (ImGui::IsItemEdited()) + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::POST_ANIM); + ImGui::SameLine(); + CheckboxFlagsLT32("Final", &focusedObject->forcedUpdateFlags, UpdatingPhase::FINAL); + if (ImGui::IsItemEdited()) + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::FINAL); + ImGui::EndGroup(); + ImGui::Text("Real update phases due to components:"); + ImGui::BeginDisabled(); + CheckboxFlagsLT32("PreAnim", &focusedObject->updateFlags, UpdatingPhase::PRE_ANIM); + ImGui::SameLine(); + CheckboxFlagsLT32("PostAnim", &focusedObject->updateFlags, UpdatingPhase::POST_ANIM); + ImGui::SameLine(); + CheckboxFlagsLT32("Final", &focusedObject->updateFlags, UpdatingPhase::FINAL); + ImGui::EndDisabled(); + ImGui::SeparatorText("Component update configuration"); + for (auto* component : focusedObject->components) { + ImGui::PushID(component); + + char title[200]; + snprintf(title, 200, "%s (%s)", component->pStaticClass->pName, component->pStaticClass->dynamicName); + + if (ImGui::CollapsingHeader(title)) { + ImGui::Text("Update phases"); + //ImGui::BeginDisabled(); + ImGui::BeginGroup(); + CheckboxFlagsLT32("PreAnim", &component->updateFlags, UpdatingPhase::PRE_ANIM); + if (ImGui::IsItemDeactivatedAfterEdit()) { + if (component->updateFlags.test(UpdatingPhase::PRE_ANIM)) { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::PRE_ANIM)].find(component); + if (it == -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::PRE_ANIM)].push_back(component); + } + else { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::PRE_ANIM)].find(component); + if (it != -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::PRE_ANIM)].remove(it); + } + focusedObject->UNSAFE_SetComponentLengths(UpdatingPhase::PRE_ANIM); + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::PRE_ANIM); + } + ImGui::SameLine(); + CheckboxFlagsLT32("PostAnim", &component->updateFlags, UpdatingPhase::POST_ANIM); + if (ImGui::IsItemDeactivatedAfterEdit()) { + if (component->updateFlags.test(UpdatingPhase::POST_ANIM)) { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::POST_ANIM)].find(component); + if (it == -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::POST_ANIM)].push_back(component); + } + else { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::POST_ANIM)].find(component); + if (it != -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::POST_ANIM)].remove(it); + } + focusedObject->UNSAFE_SetComponentLengths(UpdatingPhase::POST_ANIM); + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::POST_ANIM); + } + ImGui::SameLine(); + CheckboxFlagsLT32("Final", &component->updateFlags, UpdatingPhase::FINAL); + if (ImGui::IsItemDeactivatedAfterEdit()) { + if (component->updateFlags.test(UpdatingPhase::FINAL)) { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::FINAL)].find(component); + if (it == -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::FINAL)].push_back(component); + } + else { + auto it = focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::FINAL)].find(component); + if (it != -1) + focusedObject->componentsByUpdatingPhase[static_cast(UpdatingPhase::FINAL)].remove(it); + } + focusedObject->UNSAFE_SetComponentLengths(UpdatingPhase::FINAL); + focusedObject->UNSAFE_SetUpdateFlags(UpdatingPhase::FINAL); + } + ImGui::EndGroup(); + //ImGui::EndDisabled(); + ImGui::Text("Update priorities:"); + ImGui::InputScalarN("PreAnim, PostAnim, Final", ImGuiDataType_U8, component->updatePriorityByPhase, 3); } ImGui::PopID(); diff --git a/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.cpp b/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.cpp new file mode 100644 index 0000000..24043e2 --- /dev/null +++ b/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.cpp @@ -0,0 +1,14 @@ +#include "SurfRideEditor.h" + +SurfRideEditor::SurfRideEditor(csl::fnd::IAllocator* allocator) : OperationMode{ allocator } +{ + +} + +SurfRideEditor::~SurfRideEditor() +{ +} + +void SurfRideEditor::Render() +{ +} diff --git a/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.h b/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.h new file mode 100644 index 0000000..6fea585 --- /dev/null +++ b/src/ui/operation-modes/SurfRideEditor/SurfRideEditor.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class SurfRideEditor : public OperationMode { +public: + SurfRideEditor(csl::fnd::IAllocator* allocator); + ~SurfRideEditor(); + virtual void Render() override; +}; \ No newline at end of file