diff --git a/README.md b/README.md index 8a65148..2475f81 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# Sonic Frontiers DevTools +# HE2 DevTools -This is an in-engine modding toolkit for the SEGA game Sonic Frontiers. -Releases can be found on [GitHub](https://github.com/angryzor/sonic-frontiers-devtools/releases) +This is an in-engine modding toolkit for the Sonic Team Engine Hedgehog Engine 2. +Releases can be found on [GitHub](https://github.com/HE2-SDK/he2-devtools/releases) or on [the project's GameBanana page](https://gamebanana.com/tools/15218). A HMM update server is also available. @@ -10,34 +10,37 @@ A HMM update server is also available. ## Setting up the development environment ### Using Visual Studio 2022's CMake integration + You will need to have the following prerequisites installed: -* Visual Studio 2022 +- Visual Studio 2022 Check out the project and make sure to also check out its submodules: ```sh -git clone --recurse-submodules https://github.com/angryzor/sonic-frontiers-devtools.git +git clone --recurse-submodules https://github.com/HE2-SDK/he2-devtools.git ``` Simply open the project folder in Visual Studio 2022 (File > Open > CMake...) and it should automatically detect the CMakeLists.txt file. The following presets are available: -* x64 Debug: Debug build. -* x64 Debug ImGui Demo: Debug build with ImGui demo window enabled (for editing themes etc.). -* x64 Release: Release build. -* x64 RelWithDebInfo: Release build with debug information. + +- x64 Debug: Debug build. +- x64 Debug ImGui Demo: Debug build with ImGui demo window enabled (for editing themes etc.). +- x64 Release: Release build. +- x64 RelWithDebInfo: Release build with debug information. ### Using CMake with the Visual Studio 2022 generator + You will need to have the following prerequisites installed: -* Visual Studio 2022 -* CMake 3.28 or higher +- Visual Studio 2022 +- CMake 3.28 or higher Check out the project and make sure to also check out its submodules: ```sh -git clone --recurse-submodules https://github.com/angryzor/sonic-frontiers-devtools.git +git clone --recurse-submodules https://github.com/HE2-SDK/he2-devtools.git ``` Now let CMake do its thing: @@ -46,7 +49,7 @@ Now let CMake do its thing: cmake -B build ``` -If you have Sonic Frontiers installed in a non-standard location, you can specify that location +If you have your target game installed in a non-standard location, you can specify that location with the `DEVTOOLS_GAME_FOLDER` variable: ```sh diff --git a/sdks/miller-sdk b/sdks/miller-sdk index 9fe3ce8..93647cd 160000 --- a/sdks/miller-sdk +++ b/sdks/miller-sdk @@ -1 +1 @@ -Subproject commit 9fe3ce8fdd7d39ae02a6fd6b9655fa73ea2fcdef +Subproject commit 93647cda6e001bbc0763cea4dc5f19873785c5f9 diff --git a/sdks/rangers-sdk b/sdks/rangers-sdk index c406df9..7125747 160000 --- a/sdks/rangers-sdk +++ b/sdks/rangers-sdk @@ -1 +1 @@ -Subproject commit c406df9bb35388299bf7755b9b154adc60a3d5a9 +Subproject commit 7125747c58b1bba87863b056e7afcd66e3947c61 diff --git a/sdks/wars-sdk b/sdks/wars-sdk index b4128e6..2c45499 160000 --- a/sdks/wars-sdk +++ b/sdks/wars-sdk @@ -1 +1 @@ -Subproject commit b4128e6918dfbde5fdcc13cb94005dcb306f3f61 +Subproject commit 2c4549976fd8fb1c911487dd5ebd733cafd353f6 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66cdf97..3eb9f97 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ target_sources(${DEVTOOLS_TARGET} ui/common/editors/Pointcloud.cpp ui/common/editors/Resources.cpp ui/common/editors/HsmBase.cpp + ui/common/editors/ParticleLocation.cpp ui/common/viewers/Basic.cpp ui/common/viewers/RflDiff.cpp ui/common/inputs/Basic.cpp @@ -119,6 +120,7 @@ target_sources(${DEVTOOLS_TARGET} ui/common/editors/Pointcloud.h ui/common/editors/Resources.h ui/common/editors/HsmBase.h + ui/common/editors/ParticleLocation.h ui/common/viewers/Basic.h ui/common/viewers/RflDiff.h ui/common/inputs/Basic.h @@ -294,6 +296,7 @@ if(${DEVTOOLS_TARGET_SDK} STREQUAL "rangers") ResGismoConfigPlanEditor ResMirageLightEditor ResVibrationEditor + ResParticleLocationEditor ) set(DEVTOOLS_FEATURE_CORE_SERVICE_INSPECTORS MemoryInspector diff --git a/src/debug-rendering/renderables/PhysicalAnimation.cpp b/src/debug-rendering/renderables/PhysicalAnimation.cpp index f0df5ad..4bf64f4 100644 --- a/src/debug-rendering/renderables/PhysicalAnimation.cpp +++ b/src/debug-rendering/renderables/PhysicalAnimation.cpp @@ -1,36 +1,9 @@ #ifndef DEVTOOLS_TARGET_SDK_wars #include "PhysicalAnimation.h" #include +#include namespace devtools::debug_rendering::renderables { - struct btCollisionShape { - int64_t vftable; - csl::math::Matrix34 worldTransform; - }; - - struct Node { - char padding0[16]; - csl::math::Vector3 position; - char padding1[224]; - }; - - struct alignas(16) Link { - char padding0[32]; - Node* nodes[2]; - char padding1[32]; - }; - - struct alignas(16) btSoftBody { - char padding0[952]; - int nodeCount; - int nodeCapacity; - Node* nodes; - char padding1[48]; - int linkCount; - int linkCapacity; - Link* links; - }; - csl::math::Matrix34 convertBulletToDirectX(const csl::math::Matrix34& bulletStyle) { csl::math::Matrix34 directXStyle; directXStyle.linear() = bulletStyle.linear().transpose(); @@ -43,98 +16,109 @@ namespace devtools::debug_rendering::renderables { if (!enabled) return; - //auto* gameManager = hh::game::GameManager::GetInstance(); - //if (!gameManager) - // return; - - //for (auto* gameObject : gameManager->objects) { - // for (auto* goc : gameObject->components) { - // if (goc->pStaticClass == hh::pba::GOCPhysicalAnimationBullet::GetClass()) { - // auto* physGoc = static_cast(goc); - // for (auto i = 0; i < physGoc->rigidBodies.size(); i++) { - // const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 }; - // auto* rigidBody = reinterpret_cast(physGoc->rigidBodies[i*2]); - // csl::math::Matrix34 worldTransform = convertBulletToDirectX(rigidBody->worldTransform); - // if (!gameObject->GetComponent()) - // worldTransform.translation() += physGoc->gocAnimator0->visualModel->frame2->fullTransform.position; - // auto& resRigidBody = physGoc->physSkelRes->rigidbodies[i]; - // if (resRigidBody.isShapeBox) - // ctx.DrawOBB(worldTransform, csl::math::Vector3(resRigidBody.shapeRadius, resRigidBody.shapeHeight, resRigidBody.shapeDepth), rigidBodyColor); - // else { - // if (resRigidBody.shapeHeight > 0) - // ctx.DrawCapsule(worldTransform, resRigidBody.shapeRadius, resRigidBody.shapeHeight, rigidBodyColor); - // else - // ctx.DrawSphere(worldTransform, resRigidBody.shapeRadius, rigidBodyColor); - // } - // } - // if (physGoc->hasSoftBody) { - // for (auto i = 0; i < physGoc->softbodies.size(); i++) { - // const csl::ut::Color8 softBodyColor = { 0, 255, 0, 255 }; - // auto* softBody = reinterpret_cast(physGoc->softbodies[i * 2]); - // auto& resSoftBody = physGoc->physSkelRes->softbodies[i]; - // for (auto x = 0; x < softBody->nodeCount; x++) { - // auto& node = softBody->nodes[x]; - // auto transform = csl::math::Matrix34::Identity(); - // transform.translate(node.position); - // ctx.DrawSphere(transform, 0.01f, softBodyColor); - // } - // auto* tempAlloc = hh::fnd::MemoryRouter::GetTempAllocator(); - // hh::gfnd::DrawVertex* vertices = static_cast(tempAlloc->Alloc((2 * softBody->linkCount) * sizeof(hh::gfnd::DrawVertex), 4)); - // unsigned short* indices = static_cast(tempAlloc->Alloc((2 * softBody->linkCount) * sizeof(short), 2)); - // for (auto x = 0; x < softBody->linkCount; x++) { - // auto& link = softBody->links[x]; - // int curVert = x * 2; - // vertices[curVert].x = link.nodes[0]->position.x(); - // vertices[curVert].y = link.nodes[0]->position.y(); - // vertices[curVert].z = link.nodes[0]->position.z(); - // vertices[curVert].color = 0xFF00FF00; - // vertices[curVert + 1].x = link.nodes[1]->position.x(); - // vertices[curVert + 1].y = link.nodes[1]->position.y(); - // vertices[curVert + 1].z = link.nodes[1]->position.z(); - // vertices[curVert + 1].color = 0xFF00FF00; - // indices[curVert] = curVert; - // indices[curVert + 1] = curVert + 1; - // } - // ctx.DrawPrimitive(hh::gfnd::PrimitiveType::LINE_LIST, vertices, indices, softBody->linkCount * 2); - // tempAlloc->Free(vertices); - // tempAlloc->Free(indices); - // } - // } - // } - // } - //} + auto* gameManager = hh::game::GameManager::GetInstance(); + if (!gameManager) + return; + + for (auto* gameObject : gameManager->objects) { + for (auto* goc : gameObject->components) { + if (goc->pStaticClass == hh::pba::GOCPhysicalAnimationBullet::GetClass()) { + auto* gocPBA = static_cast(goc); + + auto animTf = TransformToAffine3f(gocPBA->gocAnimationSingle->GetTransform()); + + csl::ut::MoveArray rigidBodyPositions{ hh::fnd::MemoryRouter::GetTempAllocator() }; + gocPBA->GetRigidBodyPositions(rigidBodyPositions); + + for (size_t i = 0; i < gocPBA->physSkelRes->rigidbodies.size(); i++) { + static const csl::ut::Color8 rigidBodyColor{ 255, 0, 255, 255 }; + auto& rb = gocPBA->physSkelRes->rigidbodies[i]; + auto& pos = rigidBodyPositions[i]; + + csl::math::Matrix34 tf{}; + tf.fromPositionOrientationScale(pos.m_Position, pos.m_Rotation, csl::math::Vector3{ 1.0f, 1.0f, 1.0f }); + + if (rb.shape == ucsl::resources::pba::v1::RigidBody::Shape::SPHERE) { + if (rb.shapeHeight > 0) + ctx.DrawCapsule(animTf * tf, rb.shapeRadius, rb.shapeHeight, rigidBodyColor); + else + ctx.DrawSphere(animTf * tf, rb.shapeRadius, rigidBodyColor); + } + else + ctx.DrawOBB(animTf * tf, { rb.shapeRadius, rb.shapeHeight, rb.shapeDepth }, rigidBodyColor); + } + + if (gocPBA->hasSoftBody) { + for (auto i = 0; i < gocPBA->physSkelRes->softbodies.size(); i++) { + static const csl::ut::Color8 softBodyColor{ 0, 255, 0, 255 }; + auto& sb = gocPBA->physSkelRes->softbodies[i]; + + csl::ut::MoveArray nodePositions{ hh::fnd::MemoryRouter::GetTempAllocator() }; + gocPBA->GetSoftBodyNodePositions(i, nodePositions); + + for (auto x = 0; x < sb.nodes.size(); x++) { + auto transform{ csl::math::Matrix34::Identity() }; + transform.translate(nodePositions[x]); + ctx.DrawSphere(transform, 0.01f, softBodyColor); + } + + auto* tempAlloc = hh::fnd::MemoryRouter::GetTempAllocator(); + + unsigned int linkCount = sb.links.size(); + unsigned int linkSize = linkCount * 2; + hh::gfnd::DrawVertex* vertices = new (tempAlloc) hh::gfnd::DrawVertex[linkSize]; + unsigned short* indices = new (tempAlloc) unsigned short[linkSize]; + + for (auto x = 0; x < linkCount; x++) { + auto& link = sb.links[x]; + csl::math::Vector3 nodes[2]{ nodePositions[link.verts[0]], nodePositions[link.verts[1]] }; + int curVert = x * 2; + vertices[curVert] = { .x = nodes[0].x(), .y = nodes[0].y(), .z = nodes[0].z(), .color = 0xFF00FF00 }; + vertices[curVert + 1] = { .x = nodes[1].x(), .y = nodes[1].y(), .z = nodes[1].z(), .color = 0xFF00FF00 }; + indices[curVert] = curVert; + indices[curVert + 1] = curVert + 1; + } + ctx.DrawPrimitive(hh::gfnd::PrimitiveType::LINE_LIST, vertices, indices, linkSize); + + tempAlloc->Free(vertices); + tempAlloc->Free(indices); + } + } + } + } + } } void PhysicalAnimation::RenderImGuiDebugVisuals(const ImGuiDrawContext& ctx) { - if (!enabled) + /*if (!enabled) + return; + + auto* gameManager = hh::game::GameManager::GetInstance(); + if (!gameManager) return; - //auto* gameManager = hh::game::GameManager::GetInstance(); - //if (!gameManager) - // return; - - //for (auto* gameObject : gameManager->objects) { - // for (auto* goc : gameObject->components) { - // if (goc->pStaticClass == hh::pba::GOCPhysicalAnimationBullet::GetClass()) { - // auto* physGoc = static_cast(goc); - // for (auto i = 0; i < physGoc->rigidBodies.size(); i++) { - // const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 }; - // auto* rigidBody = reinterpret_cast(physGoc->rigidBodies[i*2]); - // auto& resRigidBody = physGoc->physSkelRes->rigidbodies[i]; - // csl::math::Vector3 translation = csl::math::Vector3{ rigidBody->worldTransform.translation() }; - // if (!gameObject->GetComponent()) - // translation += physGoc->gocAnimator0->visualModel->frame2->fullTransform.position; - // auto maybePos = ctx.WorldCoordsToImGui(translation); - - // if (!maybePos.has_value()) - // continue; - - // OverlayTag(resRigidBody.boneName, false, maybePos.value(), ImVec4(0.0f, 1.0f, 0.0f, 1.0f)); - // } - // } - // } - //} + for (auto* gameObject : gameManager->objects) { + for (auto* goc : gameObject->components) { + if (goc->pStaticClass == hh::pba::GOCPhysicalAnimationBullet::GetClass()) { + auto* physGoc = static_cast(goc); + for (auto i = 0; i < physGoc->rigidBodies.size(); i++) { + const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 }; + auto* rigidBody = reinterpret_cast(physGoc->rigidBodies[i*2]); + auto& resRigidBody = physGoc->physSkelRes->rigidbodies[i]; + csl::math::Vector3 translation = csl::math::Vector3{ rigidBody->worldTransform.translation() }; + if (!gameObject->GetComponent()) + translation += physGoc->gocAnimator0->visualModel->frame2->fullTransform.position; + auto maybePos = ctx.WorldCoordsToImGui(translation); + + if (!maybePos.has_value()) + continue; + + OverlayTag(resRigidBody.boneName, false, maybePos.value(), ImVec4(0.0f, 1.0f, 0.0f, 1.0f)); + } + } + } + }*/ } } #endif diff --git a/src/ui/common/Theme.cpp b/src/ui/common/Theme.cpp index 952488f..90edc98 100644 --- a/src/ui/common/Theme.cpp +++ b/src/ui/common/Theme.cpp @@ -667,7 +667,7 @@ void Theme_ModernContrastImGui() { colors[ImGuiCol_NavHighlight] = ImVec4(0.00f, 0.46f, 1.00f, 1.00f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); } Theme Theme::themes[themeCount] = { diff --git a/src/ui/common/editors/Camera.cpp b/src/ui/common/editors/Camera.cpp index 2f7d885..73e4113 100644 --- a/src/ui/common/editors/Camera.cpp +++ b/src/ui/common/editors/Camera.cpp @@ -3,23 +3,36 @@ using namespace app_cmn::camera; -bool Editor(const char* label, CameraParameter::Target& target) { +bool Editor(const char* label, CameraParameter::Orientation::Target& target) { bool edited{}; ImGui::PushID(label); - edited |= Editor("Position", target.position); - edited |= Editor("Offset", target.offset); - edited |= Editor("Unk3", target.unk3); + edited |= Editor("Up Vector", target.upVector); + edited |= Editor("Unk8b", target.unk8b); ImGui::PopID(); return edited; } -bool Editor(const char* label, CameraParameter::Offset& offset) { +bool Editor(const char* label, CameraParameter::Orientation::Offset& offset) { bool edited{}; ImGui::PushID(label); edited |= Editor("Offset", reinterpret_cast(offset)); + edited |= Editor("Target Position", offset.targetPosition); + edited |= Editor("Use Position", offset.usePosition); + + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, CameraParameter::Positioning& positioning) { + bool edited{}; + ImGui::PushID(label); + + edited |= Editor("Position", positioning.position); + edited |= Editor("Offset", positioning.offset); + edited |= Editor("Unk3", positioning.unk3); ImGui::PopID(); return edited; @@ -29,10 +42,8 @@ bool Editor(const char* label, CameraParameter::Orientation& orientation) { bool edited{}; ImGui::PushID(label); - edited |= Editor("Unk7", orientation.unk7); - edited |= Editor("Unk8", orientation.unk8); - edited |= Editor("Unk9", orientation.unk9); - edited |= Editor("Unk8b", orientation.unk8b); + edited |= Editor("Offset", orientation.offset); + edited |= Editor("Target", orientation.target); ImGui::PopID(); return edited; @@ -42,8 +53,7 @@ bool Editor(const char* label, CameraParameter& parameter) { bool edited{}; ImGui::PushID(label); - edited |= Editor("Target", parameter.target); - edited |= Editor("Offset", parameter.offset); + edited |= Editor("Positioning", parameter.positioning); edited |= Editor("Orientation", parameter.orientation); ImGui::PopID(); diff --git a/src/ui/common/editors/Camera.h b/src/ui/common/editors/Camera.h index 1bdff12..d0b0dd0 100644 --- a/src/ui/common/editors/Camera.h +++ b/src/ui/common/editors/Camera.h @@ -1,8 +1,9 @@ #pragma once -bool Editor(const char* label, app_cmn::camera::CameraParameter::Target& target); -bool Editor(const char* label, app_cmn::camera::CameraParameter::Offset& offset); +bool Editor(const char* label, app_cmn::camera::CameraParameter::Orientation::Target& target); +bool Editor(const char* label, app_cmn::camera::CameraParameter::Orientation::Offset& offset); bool Editor(const char* label, app_cmn::camera::CameraParameter::Orientation& orientation); +bool Editor(const char* label, app_cmn::camera::CameraParameter::Positioning& positioning); bool Editor(const char* label, app_cmn::camera::CameraParameter& parameter); bool Editor(const char* label, app_cmn::camera::FrustumParameter& parameter); bool Editor(const char* label, app_cmn::camera::CameraPose& pose); diff --git a/src/ui/common/editors/Needle.cpp b/src/ui/common/editors/Needle.cpp index a45c29b..1877bfd 100644 --- a/src/ui/common/editors/Needle.cpp +++ b/src/ui/common/editors/Needle.cpp @@ -393,22 +393,8 @@ bool Editor(const char* label, hh::needle::RenderingPipelineRangers& pipeline) if (ImGui::TreeNode(label)) { edited |= Editor("WorldRenderingPipeline", static_cast(pipeline)); Viewer("name", pipeline.name); - edited |= Editor("qword118", pipeline.qword118); - edited |= Editor("qword120", pipeline.qword120); - edited |= Editor("qword128", pipeline.qword128); - edited |= Editor("qword130", pipeline.qword130); edited |= Editor("qword138", pipeline.qword138); - edited |= Editor("qword140", pipeline.qword140); - edited |= Editor("qword148", pipeline.qword148); edited |= Editor("qword150", pipeline.qword150); - edited |= Editor("qword178", pipeline.qword178); - edited |= Editor("qword180", pipeline.qword180); - edited |= Editor("qword188", pipeline.qword188); - edited |= Editor("qword190", pipeline.qword190); - edited |= Editor("qword198", pipeline.qword198); - edited |= Editor("qword1A0", pipeline.qword1A0); - edited |= Editor("qword1A8", pipeline.qword1A8); - edited |= Editor("qword1B0", pipeline.qword1B0); ImGui::TreePop(); } return edited; diff --git a/src/ui/common/editors/ParticleLocation.cpp b/src/ui/common/editors/ParticleLocation.cpp new file mode 100644 index 0000000..87f7781 --- /dev/null +++ b/src/ui/common/editors/ParticleLocation.cpp @@ -0,0 +1,95 @@ +#include "ParticleLocation.h" +#ifndef DEVTOOLS_TARGET_SDK_wars +#include + +bool Editor(const char* name, hh::fnd::ManagedResource* resource, ucsl::resources::effdb::v100::Particle& data); +bool Editor(const char* name, hh::fnd::ManagedResource* resource, const char*& data); +bool Editor(const char* name, hh::fnd::ManagedResource* resource, ucsl::resources::effdb::v100::Binding& data); + +#include +#include +#include + +using namespace hh::animeff; +using namespace ucsl::resources::effdb::v100; + +bool Editor(const char* name, hh::fnd::ManagedResource* resource, Particle& data) { + bool changed{}; + + if (ImGui::TreeNode(name)) { + changed |= Editor("Attached To Bone", data.attachedToBone); + changed |= CheckboxFlags("Ignore Relative Position", data.flags, Particle::Flag::IGNORE_RELATIVE_POSITION); + changed |= CheckboxFlags("Use Position", data.flags, Particle::Flag::USE_POSITION); + changed |= CheckboxFlags("Use Rotation", data.flags, Particle::Flag::USE_ROTATION); + changed |= CheckboxFlags("Use Scale", data.flags, Particle::Flag::USE_SCALE); + changed |= InputText("Particle Name", data.particleName, resource); + changed |= InputText("Bone Name", data.boneName, resource); + changed |= Editor("Position", data.position); + changed |= Editor("Rotation", data.rotation); + changed |= Editor("Scale", data.scale); + + ImGui::TreePop(); + } + + return changed; +} + +bool Editor(const char* name, hh::fnd::ManagedResource* resource, const char*& data) { + bool changed{}; + + changed |= InputText(name, data, resource); + + return changed; +} + +void InitParticle(hh::fnd::ManagedResource* resource, Particle& item) { + item = {}; + item.boneName = "BoneName"; + item.particleName = "ParticleName"; + item.rotation = { 0, 0, 0, 1 }; + item.scale = { 1, 1, 1 }; +} + +void DeinitParticle(hh::fnd::ManagedResource* resource, Particle& item) { } + +void InitSoundName(hh::fnd::ManagedResource* resource, const char*& item) { + item = {}; + item = "SoundName"; +} + +void DeinitSoundName(hh::fnd::ManagedResource* resource, const char*& item) {} + +bool Editor(const char* name, hh::fnd::ManagedResource* resource, Binding& data) { + bool changed{}; + + if (ImGui::TreeNode(name)) { + changed |= InputText("Clip Name", data.clipName, resource); + + resources::ManagedCArray particles{ resource, data.particles, data.particleCount }; + changed |= Editor("Particles", resource, particles, InitParticle, DeinitParticle); + + resources::ManagedCArray soundNames{ resource, data.soundNames, data.soundNameCount }; + changed |= Editor("Sound Names", resource, soundNames, InitSoundName, DeinitSoundName); + + ImGui::TreePop(); + } + + return changed; +} + +void InitBinding(hh::fnd::ManagedResource* resource, Binding& item) { + item = {}; + item.clipName = "ClipName"; +} + +void DeinitBinding(hh::fnd::ManagedResource* resource, Binding& item) {} + +bool Editor(EffdbData& data, ResParticleLocation* resource) { + bool changed{}; + + resources::ManagedCArray bindings{ resource, data.bindings, data.bindingCount }; + changed |= Editor("Bindings", resource, bindings, InitBinding, DeinitBinding); + + return changed; +} +#endif diff --git a/src/ui/common/editors/ParticleLocation.h b/src/ui/common/editors/ParticleLocation.h new file mode 100644 index 0000000..5b6ce66 --- /dev/null +++ b/src/ui/common/editors/ParticleLocation.h @@ -0,0 +1,5 @@ +#pragma once + +#ifndef DEVTOOLS_TARGET_SDK_wars +bool Editor(ucsl::resources::effdb::v100::EffdbData& data, hh::animeff::ResParticleLocation* resource); +#endif diff --git a/src/ui/game-services/game-service-inspectors/EventPlayer.cpp b/src/ui/game-services/game-service-inspectors/EventPlayer.cpp index cbec1d7..20703f2 100644 --- a/src/ui/game-services/game-service-inspectors/EventPlayer.cpp +++ b/src/ui/game-services/game-service-inspectors/EventPlayer.cpp @@ -14,7 +14,7 @@ void RenderGameServiceInspector(app::evt::EventPlayer& service) } if (ImGui::TreeNode("Event Scenes")) { for (auto* x : service.evtSceneMgr->evtScenes) { - if (ImGui::TreeNode(x->setupData.cutsceneName)) { + if (ImGui::TreeNode(x->setupData.playInfo.cutsceneName)) { Editor("unk2", x->unk2); Editor("unk3", x->unk3); ImGui::TreePop(); diff --git a/src/ui/operation-modes/modes/dvscene-editor/DvNode.cpp b/src/ui/operation-modes/modes/dvscene-editor/DvNode.cpp index 60f6175..58a50a5 100644 --- a/src/ui/operation-modes/modes/dvscene-editor/DvNode.cpp +++ b/src/ui/operation-modes/modes/dvscene-editor/DvNode.cpp @@ -83,6 +83,7 @@ namespace ui::operation_modes::modes::dvscene_editor { return node->nodeType == hh::dv::DvNodeBase::NodeType::PATH; } + //TODO: Fix parent transforms Eigen::Affine3f DvNode::GetTransform() const { if(CanTransform()) diff --git a/src/ui/operation-modes/modes/dvscene-editor/SceneSettings.cpp b/src/ui/operation-modes/modes/dvscene-editor/SceneSettings.cpp index ce3d74e..52ebcd0 100644 --- a/src/ui/operation-modes/modes/dvscene-editor/SceneSettings.cpp +++ b/src/ui/operation-modes/modes/dvscene-editor/SceneSettings.cpp @@ -49,7 +49,7 @@ namespace ui::operation_modes::modes::dvscene_editor { GetBehavior>()->DeselectAll(); context.goDVSC = dvsc; for (auto* evtScn : hh::game::GameManager::GetInstance()->GetService()->evtSceneMgr->evtScenes) - if (strcmp(evtScn->setupData.cutsceneName, dvsc->cutsceneName.c_str()) == 0) + if (strcmp(evtScn->setupData.playInfo.cutsceneName, dvsc->cutsceneName.c_str()) == 0) context.evtScene = evtScn; context.parsedScene = new dv::DvScene; context.parsedScene->read(static_cast(dvsc->resource->binaryData), dvsc->resource->size); diff --git a/src/ui/operation-modes/modes/dvscene-editor/node-inspector/elements/Weather.h b/src/ui/operation-modes/modes/dvscene-editor/node-inspector/elements/Weather.h index e79d609..f3b6a48 100644 --- a/src/ui/operation-modes/modes/dvscene-editor/node-inspector/elements/Weather.h +++ b/src/ui/operation-modes/modes/dvscene-editor/node-inspector/elements/Weather.h @@ -2,14 +2,27 @@ #include "../Elements.h" namespace ui::operation_modes::modes::dvscene_editor { +#ifdef DEVTOOLS_TARGET_SDK_rangers + const char* weatherTypeNames[] = { + "SUNNY", + "CLOUDY", + "RAINY", + "SANDSTORM", + "METEOR_SHOWER" + }; +#endif + template<> bool RenderElementInspector(char* element) { bool changed = false; - //auto* data = reinterpret_cast(element); - //unsigned int weatherType = static_cast(data->weatherType); - //if (changed |= Editor("Weather Type", weatherType)) - // data->weatherType = static_cast(weatherType); - ImGui::Text("Ashrindy fix this please."); + auto* data = reinterpret_cast(element); +#ifdef DEVTOOLS_TARGET_SDK_miller + unsigned int weatherType = static_cast(data->weatherType); + if(changed |= Editor("Weather Type", weatherType)) + data->weatherType = static_cast(weatherType); +#else + changed |= ComboEnum("Weather Type", data->weatherType, weatherTypeNames); +#endif return changed; } } diff --git a/src/ui/operation-modes/modes/dvscene-editor/timeline/Timeline.cpp b/src/ui/operation-modes/modes/dvscene-editor/timeline/Timeline.cpp index 46dc6e3..536a745 100644 --- a/src/ui/operation-modes/modes/dvscene-editor/timeline/Timeline.cpp +++ b/src/ui/operation-modes/modes/dvscene-editor/timeline/Timeline.cpp @@ -72,8 +72,9 @@ namespace ui::operation_modes::modes::dvscene_editor { if ((context.evtScene->flags.bits & 0x80) != 0) context.evtScene->SetMovie(play); x->moviePlayer->SetPause(!play); - context.goDVSC->play = play; } + if (changed) + context.goDVSC->play = play; } ImGui::EndChild(); } diff --git a/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerBlackboard.cpp b/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerBlackboard.cpp index fb01f5f..023e791 100644 --- a/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerBlackboard.cpp +++ b/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerBlackboard.cpp @@ -41,7 +41,8 @@ void RenderBlackboardBattleInspector(app::player::BlackboardBattle& blackboard) csl::ut::MoveArray debugArray2; csl::ut::MoveArray unk4; ImGui::DragScalar("Unk5", ImGuiDataType_U32, &blackboard.unk5); - ImGui::DragScalar("unk6", ImGuiDataType_U16, &blackboard.unk6); + ImGui::DragScalar("unk6a", ImGuiDataType_U8, &blackboard.unk6a); + ImGui::DragScalar("unk6b", ImGuiDataType_U8, &blackboard.unk6b); ImGui::DragScalar("unk7", ImGuiDataType_U8, &blackboard.unk7); ImGui::DragScalar("Combo count", ImGuiDataType_U32, &blackboard.comboCount); ImGui::DragFloat("Phantom rush amount", &blackboard.phantomRushAmount); @@ -53,7 +54,8 @@ void RenderBlackboardBattleInspector(app::player::BlackboardBattle& blackboard) ImGui::Text("%zx", blackboard.unk13); ImGui::Text("%zx", blackboard.unk14); ImGui::Text("Unk16: %s", blackboard.unk16.c_str()); - ImGui::DragScalar("unk17", ImGuiDataType_U16, &blackboard.unk17); + ImGui::DragScalar("flags0", ImGuiDataType_U8, &blackboard.flags0); + ImGui::DragScalar("flags1", ImGuiDataType_U8, &blackboard.flags1); } const char* difficultyNames[]{ "EASY", "NORMAL", "HARD", "EXTREME" }; @@ -404,9 +406,24 @@ const char* worldFlagNames[128]{ nullptr, }; +const char* characterIdNames[] = { + "SONIC", + "AMY", + "KNUCKLES", + "TAILS", + "NONE" +}; + +const char* formStateNames[] = { + "NORMAL", + "SUPER", + "UNK0" +}; + void RenderBlackboardStatusInspector(app::player::BlackboardStatus& blackboard) { - ImGui::DragScalar("word20", ImGuiDataType_U16, &blackboard.word20); - ImGui::DragScalar("dword24", ImGuiDataType_U32, &blackboard.dword24); + ImGui::DragScalar("byte20", ImGuiDataType_U8, &blackboard.byte20); + ComboEnum("characterId", blackboard.characterId, characterIdNames); + ComboEnum("formState", blackboard.formState, formStateNames); if (ImGui::TreeNode("Combat flags")) { for (size_t i = 0; i < 64; i++) { @@ -453,13 +470,13 @@ void RenderBlackboardStatusInspector(app::player::BlackboardStatus& blackboard) ImGui::Text("Out of control time: %f", blackboard.outOfControlTime); ImGui::Text("In control time: %f", blackboard.inControlTime); ImGui::Text("%zx", blackboard.qword58); - ImGui::Text("%zx", blackboard.qword60); + ImGui::Text("%zx", blackboard.dword60); + ImGui::Text("%zx", blackboard.dword64); //ut::PriorityList> qword68; //csl::ut::InplaceMoveArray qword90; //csl::ut::InplaceMoveArray qwordC0; //csl::ut::InplaceMoveArray qwordF0; - ImGui::Text("%zx", blackboard.qword120); - ImGui::DragScalar("dword128", ImGuiDataType_U32, &blackboard.dword128); + Editor("dword120", blackboard.dword120); //ut::PriorityList> qword130; Editor("oword160", blackboard.oword160); ImGui::DragScalar("dword170", ImGuiDataType_U32, &blackboard.dword170); diff --git a/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerKinematicParams.cpp b/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerKinematicParams.cpp index 27028c4..850060c 100644 --- a/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerKinematicParams.cpp +++ b/src/ui/operation-modes/modes/object-inspection/component-inspectors/GOCPlayerKinematicParams.cpp @@ -20,8 +20,10 @@ void RenderComponentInspector(app::player::GOCPlayerKinematicParams& component) ImGui::Text("Unk7"); Viewer("Unk7", component.unk7); +#ifdef DEVTOOLS_TARGET_SDK_miller Editor("Unk9.unk1", component.unk9.unk1); Editor("Unk9.unk2", component.unk9.unk2); +#endif Editor("Unk11.unk3", component.unk11.unk3); Editor("Unk14.unk1", component.unk14.unk1); Editor("Unk14.unk2", component.unk14.unk2); diff --git a/src/ui/operation-modes/modes/object-inspection/component-inspectors/rangers/GOCColliderQuery.cpp b/src/ui/operation-modes/modes/object-inspection/component-inspectors/rangers/GOCColliderQuery.cpp index 0916dfc..785ca70 100644 --- a/src/ui/operation-modes/modes/object-inspection/component-inspectors/rangers/GOCColliderQuery.cpp +++ b/src/ui/operation-modes/modes/object-inspection/component-inspectors/rangers/GOCColliderQuery.cpp @@ -5,12 +5,18 @@ void RenderComponentInspector(app::physics::GOCColliderQuery& component) { Editor("Local transform", component.localTransform); Editor("World transform", component.worldTransform); + CheckboxFlags("Enter Flag", component.ownerOverlapFlags, app::physics::GOCColliderQuery::OverlapFlag::ENTER); + CheckboxFlags("Leave Flag", component.ownerOverlapFlags, app::physics::GOCColliderQuery::OverlapFlag::LEAVE); + CheckboxFlags("Stay Flag", component.ownerOverlapFlags, app::physics::GOCColliderQuery::OverlapFlag::STAY); + CheckboxFlags("Enabled", component.flags, app::physics::GOCColliderQuery::Flag::ENABLED); } void RenderComponentInspector(app::physics::GOCMoveSphereColliderQuery& component) { RenderComponentInspector(static_cast(component)); - Editor("unk201", component.unk201); - Editor("unk201", component.unk202); + Editor("Position", component.position); + Editor("Velocity", component.velocity); + Editor("Radius", component.radius); + Editor("unk204", component.unk204); } diff --git a/src/ui/resources/ResourceBrowser.cpp b/src/ui/resources/ResourceBrowser.cpp index 257b260..735650a 100644 --- a/src/ui/resources/ResourceBrowser.cpp +++ b/src/ui/resources/ResourceBrowser.cpp @@ -12,6 +12,7 @@ #include "editors/ResMaterialEditor.h" #ifndef DEVTOOLS_TARGET_SDK_wars #include "editors/ResPhysicalSkeletonEditor.h" +#include "editors/ResParticleLocationEditor.h" #endif #include #include @@ -232,6 +233,8 @@ void ResourceBrowser::RenderResource(ManagedResource* resource) { ResMaterialEditor::Create(Desktop::instance->GetAllocator(), static_cast(resource)); else if (typeInfo == hh::pba::ResPhysicalSkeleton::GetTypeInfo()) ResPhysicalSkeletonEditor::Create(Desktop::instance->GetAllocator(), static_cast(resource)); + else if (typeInfo == hh::animeff::ResParticleLocation::GetTypeInfo()) + ResParticleLocationEditor::Create(Desktop::instance->GetAllocator(), static_cast(resource)); #endif #ifdef DEVTOOLS_TARGET_SDK_rangers else if (typeInfo == app::ResGismoConfigDesign::GetTypeInfo()) diff --git a/src/ui/resources/editors/ResEffectEditor.cpp b/src/ui/resources/editors/ResEffectEditor.cpp index 1086009..47db8b9 100644 --- a/src/ui/resources/editors/ResEffectEditor.cpp +++ b/src/ui/resources/editors/ResEffectEditor.cpp @@ -1,10 +1,16 @@ #include "ResEffectEditor.h" -bool Editor(const char* label, ucsl::resources::cemt::v100000::Texture& texture); +bool Editor(const char* label, ucsl::resources::cemt::v100000::TextureParam& texture); bool Editor(const char* label, ucsl::resources::cemt::v100000::ChildEffect& effect); -bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::GravityVectorSettings& settings); -bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::GravityOtherSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::GravitySettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::SpeedSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::MagnetSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::NewtonSettings& settings); bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::VortexSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::SpinSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::Spin2Settings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::RandomSettings& settings); +bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::TailSettings& settings); bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam::FluctuationSettings& settings); bool Editor(const char* label, ucsl::resources::cemt::v100000::ModifierParam& modifier); bool Editor(const char* label, ucsl::resources::cemt::v100000::Table::Unk1& v); @@ -19,19 +25,47 @@ bool Editor(const char* label, ucsl::resources::cemt::v100000::EmitterParam& emi using namespace ucsl::resources::cemt::v100000; const char* modifierNames[] = { - "GRAVITY_VECTOR", - "GRAVITY_OTHER", - "UNK0", - "UNK1", + "GRAVITY", + "SPEED", + "MAGNET", + "NEWTON", "VORTEX", - "UNK2", - "UNK3", - "UNK4", - "UNK5", + "SPIN", + "SPIN2", + "RANDOM", + "TAIL", "FLUCTUATION", + "UNK0" }; -bool Editor(const char* label, Texture& texture) { +const char* shapeNames[] = { + "POINT", + "SPHERE", + "DISC", + "CYLINDER", + "LINE", + "TORUS", + "CUBE", + "null", + "FIXED" +}; + +const char* originNames[] = { + "WORLD", + "EMISSION", + "INHERIT", + "UNK0" +}; + +const char* waveformNames[] = { + "TRIANGLE", + "INVERSE_TRIANGLE", + "SAW", + "STEP", + "SINE" +}; + +bool Editor(const char* label, TextureParam& texture) { bool edited{}; ImGui::PushID(label); edited |= Editor("name", texture.name); @@ -43,24 +77,45 @@ bool Editor(const char* label, ChildEffect& effect) { bool edited{}; ImGui::PushID(label); edited |= Editor("flags", effect.flags); + edited |= Editor("unkType", effect.unkType); edited |= Editor("name", effect.name); ImGui::PopID(); return edited; } -bool Editor(const char* label, ModifierParam::GravityVectorSettings& settings) { +bool Editor(const char* label, ModifierParam::GravitySettings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("scale", settings.scale); + edited |= Editor("rotation", settings.rotation); + edited |= Editor("usesDirection", settings.usesDirection); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::SpeedSettings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("scale", settings.scale); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::MagnetSettings& settings) { bool edited{}; ImGui::PushID(label); + edited |= Editor("magnetPoint", settings.magnetPoint); edited |= Editor("scale", settings.scale); - edited |= Editor("value", settings.value); ImGui::PopID(); return edited; } -bool Editor(const char* label, ModifierParam::GravityOtherSettings& settings) { +bool Editor(const char* label, ModifierParam::NewtonSettings& settings) { bool edited{}; ImGui::PushID(label); - edited |= Editor("value", settings.value); + edited |= Editor("targetPoint", settings.targetPoint); + edited |= Editor("scale", settings.scale); + edited |= Editor("maxDistance", settings.maxDistance); ImGui::PopID(); return edited; } @@ -68,9 +123,58 @@ bool Editor(const char* label, ModifierParam::GravityOtherSettings& settings) { bool Editor(const char* label, ModifierParam::VortexSettings& settings) { bool edited{}; ImGui::PushID(label); - edited |= Editor("unk1", settings.unk1); - edited |= Editor("unk2", settings.unk2); - edited |= Editor("unk3", settings.unk3); + edited |= Editor("max", settings.max); + edited |= Editor("min", settings.min); + edited |= Editor("radius", settings.radius); + edited |= Editor("rotation", settings.rotation); + edited |= Editor("usesDirection", settings.usesDirection); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::SpinSettings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("scale", settings.scale); + edited |= Editor("rotation", settings.rotation); + edited |= Editor("usesDirection", settings.usesDirection); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::Spin2Settings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("baseStrength", settings.baseStrength); + edited |= Editor("spinStrength", settings.spinStrength); + edited |= Editor("rotationAngle", settings.rotationAngle); + edited |= Editor("axisFalloff", settings.axisFalloff); + edited |= Editor("axisVector", settings.axisVector); + edited |= Editor("useEulerRotation", settings.useEulerRotation); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::RandomSettings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("scale", settings.scale); + edited |= Editor("spreadScale", settings.spreadScale); + edited |= Editor("updateInterval", settings.updateInterval); + edited |= CheckboxFlags("RANDOMIZED_SCALE", settings.flags, ModifierParam::RandomSettings::Flags::RANDOMIZED_SCALE); + edited |= CheckboxFlags("X", settings.flags, ModifierParam::RandomSettings::Flags::X); + edited |= CheckboxFlags("Y", settings.flags, ModifierParam::RandomSettings::Flags::Y); + edited |= CheckboxFlags("Z", settings.flags, ModifierParam::RandomSettings::Flags::Z); + edited |= Editor("normalizedSpreadVector", settings.normalizedSpreadVector); + edited |= Editor("randomPerAxis", settings.randomPerAxis); + ImGui::PopID(); + return edited; +} + +bool Editor(const char* label, ModifierParam::TailSettings& settings) { + bool edited{}; + ImGui::PushID(label); + edited |= Editor("multiplier", settings.multiplier); ImGui::PopID(); return edited; } @@ -78,14 +182,9 @@ bool Editor(const char* label, ModifierParam::VortexSettings& settings) { bool Editor(const char* label, ModifierParam::FluctuationSettings& settings) { bool edited{}; ImGui::PushID(label); - edited |= Editor("unk0", settings.unk0); - edited |= Editor("unk1", settings.unk1); - edited |= Editor("unk2", settings.unk2); - edited |= Editor("unk3", settings.unk3); - edited |= Editor("unk4", settings.unk4); - edited |= Editor("unk5", settings.unk5); - edited |= Editor("unk6", settings.unk6); - edited |= Editor("unk7", settings.unk7); + edited |= ComboEnum("waveformType", settings.waveformType, waveformNames); + edited |= Editor("baseOffset", settings.baseOffset); + edited |= Editor("axisFlags", settings.axisFlags); ImGui::PopID(); return edited; } @@ -94,15 +193,22 @@ bool Editor(const char* label, ModifierParam& modifier) { bool edited{}; ImGui::PushID(label); + ImGui::Separator(); edited |= Editor("enabled", modifier.enabled); edited |= ComboEnum("type", modifier.type, modifierNames); - edited |= Editor("option1", modifier.option1); + edited |= ComboEnum("origin", modifier.origin, originNames); edited |= Editor("option2", modifier.option2); switch (modifier.type) { - case ModifierParam::Type::GRAVITY_VECTOR: edited |= Editor("settings", modifier.settings.gravityVector); break; - case ModifierParam::Type::GRAVITY_OTHER: edited |= Editor("settings", modifier.settings.gravityOther); break; + case ModifierParam::Type::GRAVITY: edited |= Editor("settings", modifier.settings.gravity); break; + case ModifierParam::Type::SPEED: edited |= Editor("settings", modifier.settings.speed); break; + case ModifierParam::Type::MAGNET: edited |= Editor("settings", modifier.settings.magnet); break; + case ModifierParam::Type::NEWTON: edited |= Editor("settings", modifier.settings.newton); break; case ModifierParam::Type::VORTEX: edited |= Editor("settings", modifier.settings.vortex); break; + case ModifierParam::Type::SPIN: edited |= Editor("settings", modifier.settings.spin); break; + case ModifierParam::Type::SPIN2: edited |= Editor("settings", modifier.settings.spin2); break; + case ModifierParam::Type::RANDOM: edited |= Editor("settings", modifier.settings.random); break; + case ModifierParam::Type::TAIL: edited |= Editor("settings", modifier.settings.tail); break; case ModifierParam::Type::FLUCTUATION: edited |= Editor("settings", modifier.settings.fluctuation); break; default: ImGui::Text("not yet implemented"); break; } @@ -163,17 +269,23 @@ bool Editor(const char* label, ElementParam& element) { edited |= Editor("unk18a0", element.unk18a0); edited |= Editor("angularVelocity", element.angularVelocity); edited |= Editor("unk18a01", element.unk18a01); - edited |= Editor("emitSpeed2", element.emitSpeed2); - edited |= Editor("unk18a02", element.unk18a02); - edited |= Editor("unkCount2", element.unkCount2); - edited |= Editor("unkCount3", element.unkCount3); + edited |= Editor("sizeX", element.sizeX); + edited |= Editor("sizeXJitter", element.sizeXJitter); + edited |= Editor("sizeY", element.sizeY); + edited |= Editor("sizeYJitter", element.sizeYJitter); + edited |= Editor("sizeZ", element.sizeZ); + edited |= Editor("sizeZJitter", element.sizeZJitter); + edited |= Editor("sizeFlags", element.sizeFlags); + edited |= Editor("scaleX", element.scaleX); + edited |= Editor("scaleXJitter", element.scaleXJitter); + edited |= Editor("scaleY", element.scaleY); + edited |= Editor("scaleYJitter", element.scaleYJitter); + edited |= Editor("scaleZ", element.scaleZ); + edited |= Editor("scaleZJitter", element.scaleZJitter); + edited |= Editor("scaleFlags", element.scaleFlags); edited |= Editor("tables", element.tables); edited |= Editor("fps", element.fps); - edited |= Editor("unk19a23", element.unk19a23); - edited |= Editor("unk18a6", element.unk18a6); - edited |= Editor("unk18a8", element.unk18a8); - edited |= Editor("unk18a1", element.unk18a1); - edited |= Editor("unk18a2", element.unk18a2); + edited |= Editor("fpsJitter", element.fpsJitter); edited |= Editor("unk18a", element.unk18a); edited |= Editor("modelName", element.modelName); edited |= Editor("particleTypeOrSomething", element.particleTypeOrSomething); @@ -202,10 +314,43 @@ bool Editor(const char* label, ElementParam& element) { bool Editor(const char* label, EmitterParam& emitter) { bool edited{}; ImGui::PushID(label); - edited |= Editor("emitspeed", emitter.emitSpeed); + edited |= Editor("position", emitter.position); + edited |= Editor("rotation", emitter.rotation); + edited |= Editor("scale", emitter.scale); + edited |= ComboEnum("shape", emitter.shape, shapeNames); + edited |= Editor("spread", emitter.spread); + edited |= Editor("startAngle", emitter.startAngle); + edited |= Editor("endAngle", emitter.endAngle); + edited |= Editor("useRadialDistribution", emitter.useRadialDistribution); + edited |= Editor("consistentAngle", emitter.consistentAngle); + edited |= Editor("useAngularSubdivisions", emitter.useAngularSubdivisions); + edited |= Editor("numSubDivisions", emitter.numSubDivisions); + edited |= Editor("disabled", emitter.disabled); + edited |= Editor("frequency", emitter.frequency); + edited |= Editor("frequencyJitter", emitter.frequencyJitter); + edited |= Editor("emitterCount", emitter.emitterCount); + edited |= Editor("emitterCountJitter", emitter.emitterCountJitter); + edited |= Editor("duration", emitter.duration); + edited |= Editor("startDelay", emitter.startDelay); + edited |= Editor("fadeSpeed", emitter.fadeSpeed); + edited |= Editor("lifeEndTime", emitter.lifeEndTime); + edited |= Editor("accelarationMultiplier", emitter.accelarationMultiplier); + edited |= Editor("accelarationNormalMultiplier", emitter.accelarationNormalMultiplier); + edited |= Editor("initialSpeed", emitter.initialSpeed); + edited |= Editor("velocityMultiplier", emitter.velocityMultiplier); + edited |= Editor("shapeRadius", emitter.shapeRadius); + edited |= Editor("velocityScale", emitter.velocityScale); + edited |= Editor("emitSize", emitter.emitSize); + edited |= Editor("useEmitVector", emitter.useEmitVector); edited |= Editor("emitVector", emitter.emitVector); - edited |= Editor("emitVectorUnk", emitter.emitVectorUnk); + edited |= Editor("emitVectorJitter", emitter.emitVectorJitter); + edited |= Editor("directionJitter", emitter.directionJitter); + edited |= Editor("inheritRatio", emitter.inheritRatio); edited |= Editor("randomSeed", emitter.randomSeed); + edited |= Editor("unkFloat0", emitter.unkFloat0); + edited |= Editor("unkFloat0Jitter", emitter.unkFloat0Jitter); + edited |= Editor("unkFloat1", emitter.unkFloat1); + edited |= Editor("unkFloat1Jitter", emitter.unkFloat1Jitter); edited |= Editor("element", emitter.elementParam); ImGui::PopID(); return edited; diff --git a/src/ui/resources/editors/ResEffectEditor.h b/src/ui/resources/editors/ResEffectEditor.h index 4fed94f..eb08d03 100644 --- a/src/ui/resources/editors/ResEffectEditor.h +++ b/src/ui/resources/editors/ResEffectEditor.h @@ -1,10 +1,6 @@ #pragma once #include -namespace heur::resources { - class ResEffect; -} - class ResEffectEditor : public StandaloneWindow { hh::fnd::Reference resource; public: diff --git a/src/ui/resources/editors/ResParticleLocationEditor.cpp b/src/ui/resources/editors/ResParticleLocationEditor.cpp new file mode 100644 index 0000000..e053c21 --- /dev/null +++ b/src/ui/resources/editors/ResParticleLocationEditor.cpp @@ -0,0 +1,21 @@ +#include "ResParticleLocationEditor.h" +#include + +ResParticleLocationEditor::ResParticleLocationEditor(csl::fnd::IAllocator* allocator, hh::animeff::ResParticleLocation* resource) : StandaloneWindow{ allocator }, resource{ resource } { + char namebuf[500]; + snprintf(namebuf, sizeof(namebuf), "%s - %s @ 0x%zx (file mapped @ 0x%zx)", resource->GetName(), resource->GetClass().pName, (size_t)&resource, (size_t)resource->unpackedBinaryData); + SetTitle(namebuf); +} + +ResParticleLocationEditor* ResParticleLocationEditor::Create(csl::fnd::IAllocator* allocator, hh::animeff::ResParticleLocation* resource) { + return new (allocator) ResParticleLocationEditor{ allocator, resource }; +} + +void ResParticleLocationEditor::RenderContents() { + auto* effdbData = static_cast(resource->unpackedBinaryData); + + if (Editor(*effdbData, resource)) { + resource->bindings.clear(); + resource->Load(effdbData, 0); + } +} diff --git a/src/ui/resources/editors/ResParticleLocationEditor.h b/src/ui/resources/editors/ResParticleLocationEditor.h new file mode 100644 index 0000000..bca1f7c --- /dev/null +++ b/src/ui/resources/editors/ResParticleLocationEditor.h @@ -0,0 +1,10 @@ +#pragma once +#include + +class ResParticleLocationEditor : public StandaloneWindow { + hh::fnd::Reference resource; +public: + ResParticleLocationEditor(csl::fnd::IAllocator* allocator, hh::animeff::ResParticleLocation* resource); + virtual void RenderContents(); + static ResParticleLocationEditor* Create(csl::fnd::IAllocator* allocator, hh::animeff::ResParticleLocation* resource); +};