Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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:
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion sdks/miller-sdk
2 changes: 1 addition & 1 deletion sdks/rangers-sdk
2 changes: 1 addition & 1 deletion sdks/wars-sdk
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -294,6 +296,7 @@ if(${DEVTOOLS_TARGET_SDK} STREQUAL "rangers")
ResGismoConfigPlanEditor
ResMirageLightEditor
ResVibrationEditor
ResParticleLocationEditor
)
set(DEVTOOLS_FEATURE_CORE_SERVICE_INSPECTORS
MemoryInspector
Expand Down
212 changes: 98 additions & 114 deletions src/debug-rendering/renderables/PhysicalAnimation.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,9 @@
#ifndef DEVTOOLS_TARGET_SDK_wars
#include "PhysicalAnimation.h"
#include <ui/common/overlays/Tag.h>
#include <utilities/math/MathUtils.h>

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();
Expand All @@ -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<hh::pba::GOCPhysicalAnimationBullet*>(goc);
// for (auto i = 0; i < physGoc->rigidBodies.size(); i++) {
// const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 };
// auto* rigidBody = reinterpret_cast<btCollisionShape*>(physGoc->rigidBodies[i*2]);
// csl::math::Matrix34 worldTransform = convertBulletToDirectX(rigidBody->worldTransform);
// if (!gameObject->GetComponent<app::player::GOCPlayerVisual>())
// 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<btSoftBody*>(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<hh::gfnd::DrawVertex*>(tempAlloc->Alloc((2 * softBody->linkCount) * sizeof(hh::gfnd::DrawVertex), 4));
// unsigned short* indices = static_cast<unsigned short*>(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<hh::pba::GOCPhysicalAnimationBullet*>(goc);

auto animTf = TransformToAffine3f(gocPBA->gocAnimationSingle->GetTransform());

csl::ut::MoveArray<hh::fnd::WorldPosition> 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<csl::math::Vector3> 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<hh::pba::GOCPhysicalAnimationBullet*>(goc);
// for (auto i = 0; i < physGoc->rigidBodies.size(); i++) {
// const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 };
// auto* rigidBody = reinterpret_cast<btCollisionShape*>(physGoc->rigidBodies[i*2]);
// auto& resRigidBody = physGoc->physSkelRes->rigidbodies[i];
// csl::math::Vector3 translation = csl::math::Vector3{ rigidBody->worldTransform.translation() };
// if (!gameObject->GetComponent<app::player::GOCPlayerVisual>())
// 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<hh::pba::GOCPhysicalAnimationBullet*>(goc);
for (auto i = 0; i < physGoc->rigidBodies.size(); i++) {
const csl::ut::Color8 rigidBodyColor = { 255, 0, 255, 255 };
auto* rigidBody = reinterpret_cast<btCollisionShape*>(physGoc->rigidBodies[i*2]);
auto& resRigidBody = physGoc->physSkelRes->rigidbodies[i];
csl::math::Vector3 translation = csl::math::Vector3{ rigidBody->worldTransform.translation() };
if (!gameObject->GetComponent<app::player::GOCPlayerVisual>())
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
2 changes: 1 addition & 1 deletion src/ui/common/Theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand Down
Loading
Loading