Files
SpaghettiKart/src/port/ui/TrackProperties.cpp
T
coco875 5d7cf20c83 pr Code 80005fd0 (#181)
* fix error

* a lot of change

* basic rename of local variable

* continue rename and improve Enhancements

* re-apply change

* revert the remove of dma_texture and fix mtxf_multiplication

* more documentation port

* some fix

* more fix

* fix arround

* Update torch

* fix spelling

---------

Co-authored-by: MegaMech <MegaMech@users.noreply.github.com>
2025-06-19 16:26:04 -06:00

284 lines
13 KiB
C++

#include "TrackProperties.h"
#include "port/ui/PortMenu.h"
#include "UIWidgets.h"
#include "libultraship/src/Context.h"
#include <imgui.h>
#include <map>
#include <libultraship/libultraship.h>
#include <spdlog/fmt/fmt.h>
#include "spdlog/formatter.h"
#include <common_structs.h>
#include <defines.h>
#include "port/Game.h"
extern "C" {
#include "code_800029B0.h"
#include "sounds.h"
#include "external.h"
#include "render_courses.h"
#include "render_objects.h"
}
namespace Editor {
TrackPropertiesWindow::~TrackPropertiesWindow() {
SPDLOG_TRACE("destruct track properties window");
}
void TrackPropertiesWindow::DrawElement() {
static char idBuffer[256] = "mk:mario_raceway";
static char nameBuffer[256] = "Mario Raceway";
static char debugNameBuffer[256] = "m circuit";
static char lengthBuffer[256] = "567m";
ImGui::InputText("ID", idBuffer, IM_ARRAYSIZE(idBuffer));
ImGui::InputText("Name", gWorldInstance.CurrentCourse->Props.Name, IM_ARRAYSIZE(nameBuffer));
ImGui::InputText("Debug Name", gWorldInstance.CurrentCourse->Props.DebugName, IM_ARRAYSIZE(debugNameBuffer));
ImGui::InputText("Course Length", gWorldInstance.CurrentCourse->Props.CourseLength, IM_ARRAYSIZE(lengthBuffer));
ImGui::InputFloat("Water Level", &gWorldInstance.CurrentCourse->Props.WaterLevel);
if (ImGui::CollapsingHeader("Camera")) {
ImGui::InputFloat("Near Perspective", &gWorldInstance.CurrentCourse->Props.NearPersp);
ImGui::InputFloat("Far Perspective", &gWorldInstance.CurrentCourse->Props.FarPersp);
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Controls the far clipping distance for perspective rendering.");
ImGui::Text("Disable culling enhancement needs to be off to see a difference.");
ImGui::EndTooltip();
}
}
if (ImGui::CollapsingHeader("Environment")) {
TrackPropertiesWindow::DrawLight();
}
if (ImGui::CollapsingHeader("AI")) {
ImGui::InputFloat("AI Max Separation", &gWorldInstance.CurrentCourse->Props.AIMaximumSeparation);
ImGui::InputFloat("AI Min Separation", &gWorldInstance.CurrentCourse->Props.AIMinimumSeparation);
ImGui::InputInt("AI Steering Sensitivity", (int*)&gWorldInstance.CurrentCourse->Props.AISteeringSensitivity);
ImGui::Separator();
for (size_t i = 0; i < 32; i++) {
ImGui::InputScalar(("Element " + std::to_string(i)).c_str(), ImGuiDataType_S16, &gWorldInstance.CurrentCourse->Props.AIDistance[i]);
}
}
if (ImGui::CollapsingHeader("Random Junk")) {
for (size_t i = 0; i < 4; i++) {
ImGui::InputFloat(fmt::format("CurveTargetSpeed[{}]", i).c_str(), &gWorldInstance.CurrentCourse->Props.CurveTargetSpeed[i]);
}
ImGui::Separator();
for (size_t i = 0; i < 4; i++) {
ImGui::InputFloat(fmt::format("NormalTargetSpeed[{}]", i).c_str(), &gWorldInstance.CurrentCourse->Props.NormalTargetSpeed[i]);
}
ImGui::Separator();
for (size_t i = 0; i < 4; i++) {
ImGui::InputFloat(fmt::format("D_0D0096B8[{}]", i).c_str(), &gWorldInstance.CurrentCourse->Props.D_0D0096B8[i]);
}
ImGui::Separator();
for (size_t i = 0; i < 4; i++) {
ImGui::InputFloat(fmt::format("OffTrackTargetSpeed[{}]", i).c_str(), &gWorldInstance.CurrentCourse->Props.OffTrackTargetSpeed[i]);
}
}
float minimapColour[3];
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Minimap.Colour, minimapColour);
if (ImGui::CollapsingHeader("Minimap")) {
ImGui::Text("Position");
ImGui::SameLine();
if (ImGui::DragInt2("##MinimapPosition", &gWorldInstance.CurrentCourse->Props.Minimap.Pos[0].X, 1.0f)) {
}
ImGui::Text("P2 Position");
ImGui::SameLine();
if (ImGui::DragInt2("##MinimapPosition2p", &gWorldInstance.CurrentCourse->Props.Minimap.Pos[1].X, 1.0f)) {
}
ImGui::Text("Player Markers");
ImGui::SameLine();
if (ImGui::DragInt2("##MinimapPlayers", &gWorldInstance.CurrentCourse->Props.Minimap.PlayerX, 1.0f)) {
}
ImGui::Text("Player Scale Factor");
ImGui::SameLine();
if (ImGui::DragFloat("##MinimapScaleFactor", &gWorldInstance.CurrentCourse->Props.Minimap.PlayerScaleFactor, 0.0001f)) {
}
ImGui::Text("Finishline");
ImGui::SameLine();
ImGui::DragFloat2("##MinimapFinishlineX", &gWorldInstance.CurrentCourse->Props.Minimap.FinishlineX, 1.0f);
ImGui::Text("Colour");
ImGui::SameLine();
ImGui::ColorEdit3("##MinimapColour", minimapColour, 1.0f);
}
FloatToRGB8(minimapColour, (u8*)&gWorldInstance.CurrentCourse->Props.Minimap.Colour);
// Convert and pass to ImGui ColorEdit3
float topRight[3], bottomRight[3], bottomLeft[3], topLeft[3];
float floorTopRight[3], floorBottomRight[3], floorBottomLeft[3], floorTopLeft[3];
// Convert RGB8 (0-255) to float (0.0f to 1.0f)
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.TopRight, topRight);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.BottomRight, bottomRight);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.BottomLeft, bottomLeft);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.TopLeft, topLeft);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorTopRight, floorTopRight);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorBottomRight, floorBottomRight);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorBottomLeft, floorBottomLeft);
RGB8ToFloat((u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorTopLeft, floorTopLeft);
if (ImGui::CollapsingHeader("Skybox")) {
ImGui::ColorEdit3("Skybox Top Right", topRight);
ImGui::ColorEdit3("Skybox Bottom Right", bottomRight);
ImGui::ColorEdit3("Skybox Bottom Left", bottomLeft);
ImGui::ColorEdit3("Skybox Top Left", topLeft);
ImGui::ColorEdit3("Skybox Floor Top Right", floorTopRight);
ImGui::ColorEdit3("Skybox Floor Bottom Right", floorBottomRight);
ImGui::ColorEdit3("Skybox Floor Bottom Left", floorBottomLeft);
ImGui::ColorEdit3("Skybox Floor Top Left", floorTopLeft);
}
// Convert the modified float values back to RGB8 (0-255)
FloatToRGB8(topRight, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.TopRight);
FloatToRGB8(bottomRight, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.BottomRight);
FloatToRGB8(bottomLeft, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.BottomLeft);
FloatToRGB8(topLeft, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.TopLeft);
FloatToRGB8(floorTopRight, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorTopRight);
FloatToRGB8(floorBottomRight, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorBottomRight);
FloatToRGB8(floorBottomLeft, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorBottomLeft);
FloatToRGB8(floorTopLeft, (u8*)&gWorldInstance.CurrentCourse->Props.Skybox.FloorTopLeft);
TrackPropertiesWindow::DrawMusic();
}
void TrackPropertiesWindow::DrawMusic() {
const char* items[] = {
"None", "Title Screen", "Main Menu", "Raceways Wario Stadium", "Moo Moo Farm / Yoshi Valley",
"Choco Mountain", "Koopa Troopa Beach", "Banshee Boardwalk", "Frappe Snowland", "Bowser's Castle",
"Kalimari Desert", "Start Grid GP/VS", "Final Lap Fanfare", "Finish 1st Place", "Finish 2nd-4th Place",
"Finish 5th-8th Place", "16", "Star Jingle", "Rainbow Road", "DK Jungle", "Game Over", "Toad's Turnpike",
"Start Grid Time Attack", "VS Battle Results", "Losing Results", "Battle Arenas", "Award Ceremony Buildup",
"Award Ceremony 1st-3rd", "Staff Roll", "Award Ceremony 4th-8th"
};
const char* currentItem = MusicSeqToString(gWorldInstance.CurrentCourse->Props.Sequence); // Get the current selected value's string
if (ImGui::BeginCombo("Music Sequence", currentItem)) {
for (int i = 0; i < IM_ARRAYSIZE(items); ++i) {
bool isSelected = (currentItem == items[i]);
if (ImGui::Selectable(items[i], isSelected)) {
// Update the sequence when an option is selected
gWorldInstance.CurrentCourse->Props.Sequence = static_cast<MusicSeq>(i);
play_sequence(gWorldInstance.CurrentCourse->Props.Sequence); // Call play_sequence with the updated sequence
// Update currentItem after selection is made
currentItem = items[i];
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
}
// Enum to string conversion
const char* TrackPropertiesWindow::MusicSeqToString(MusicSeq seq) {
switch (seq) {
case MUSIC_SEQ_00: return "None";
case MUSIC_SEQ_TITLE_SCREEN: return "Title Screen";
case MUSIC_SEQ_MAIN_MENU: return "Main Menu";
case MUSIC_SEQ_RACEWAYS_WARIO_STADIUM: return "Raceways Wario Stadium";
case MUSIC_SEQ_MOO_MOO_FARM_YOSHI_VALLEY: return "Moo Moo Farm / Yoshi Valley";
case MUSIC_SEQ_CHOCO_MOUNTAIN: return "Choco Mountain";
case MUSIC_SEQ_KOOPA_TROOPA_BEACH: return "Koopa Troopa Beach";
case MUSIC_SEQ_BANSHEE_BOARDWALK: return "Banshee Boardwalk";
case MUSIC_SEQ_FRAPPE_SNOWLAND: return "Frappe Snowland";
case MUSIC_SEQ_BOWSERS_CASTLE: return "Bowser's Castle";
case MUSIC_SEQ_KALIMARI_DESERT: return "Kalimari Desert";
case MUSIC_SEQ_START_GRID_GP_VS: return "Start Grid GP/VS";
case MUSIC_SEQ_FINAL_LAP_FANFARE: return "Final Lap Fanfare";
case MUSIC_SEQ_FINISH_1ST_PLACE: return "Finish 1st Place";
case MUSIC_SEQ_FINISH_2ND_4TH_PLACE: return "Finish 2nd-4th Place";
case MUSIC_SEQ_FINISH_5TH_8TH_PLACE: return "Finish 5th-8th Place";
case MUSIC_SEQ_16: return "16";
case MUSIC_SEQ_STAR_JINGLE: return "Star Jingle";
case MUSIC_SEQ_RAINBOW_ROAD: return "Rainbow Road";
case MUSIC_SEQ_DK_JUNGLE: return "DK Jungle";
case MUSIC_SEQ_GAME_OVER: return "Game Over";
case MUSIC_SEQ_TOADS_TURNPIKE: return "Toad's Turnpike";
case MUSIC_SEQ_START_GIRD_TIME_ATTACK: return "Start Grid Time Attack";
case MUSIC_SEQ_VS_BATTLE_RESULTS: return "VS Battle Results";
case MUSIC_SEQ_LOSING_RESULTS: return "Losing Results";
case MUSIC_SEQ_BATTLE_ARENAS: return "Battle Arenas";
case MUSIC_SEQ_AWARD_CEREMONY_BUILDUP: return "Award Ceremony Buildup";
case MUSIC_SEQ_AWARD_CEREMONY_1ST_3RD: return "Award Ceremony 1st-3rd";
case MUSIC_SEQ_STAFF_ROLL: return "Staff Roll";
case MUSIC_SEQ_AWARD_CEREMONY_4TH_8TH: return "Award Ceremony 4th-8th";
default: return "None";
}
}
void TrackPropertiesWindow::DrawLight() {
// Convert and pass to ImGui ColorEdit3
for (int i = 0; i < 2; ++i) {
float ambient[3], diffuse[3], direction[3];
RGB8ToFloat((u8*)&D_800DC610[i].a.l.col, ambient);
RGB8ToFloat((u8*)&D_800DC610[i].l->l.col, diffuse);
RGB8ToFloat((u8*)&D_800DC610[i].l->l.dir, direction);
// Edit the ambient RGB color
ImGui::Text("Light %d - Ambient Color", i + 1);
ImGui::ColorEdit3(("Ambient Color " + std::to_string(i)).c_str(), ambient); // Modify ambient color
// Edit the diffuse RGB color
ImGui::Text("Light %d - Diffuse Color", i + 1);
ImGui::ColorEdit3(("Diffuse Color " + std::to_string(i)).c_str(), diffuse); // Modify diffuse color
// Edit the direction RGB color (this could be represented as a direction vector)
ImGui::Text("Light %d - Direction", i + 1);
ImGui::ColorEdit3(("Direction Color " + std::to_string(i)).c_str(), direction); // Modify direction vector color
FloatToRGB8(ambient, (u8*)&D_800DC610[i].a.l.col);
FloatToRGB8(ambient, (u8*)&D_800DC610[i].a.l.colc);
FloatToRGB8(diffuse, (u8*)&D_800DC610[i].l->l.col);
FloatToRGB8(diffuse, (u8*)&D_800DC610[i].l->l.colc);
FloatToRGB8(direction, (u8*)&D_800DC610[i].l->l.dir);
}
}
// Convert s16 color values to float (normalized to [0, 1] range)
void TrackPropertiesWindow::RGB8ToFloat(const u8* src, float* dst) {
for (int i = 0; i < 3; ++i) {
dst[i] = src[i] / 255.0f; // Normalize to the range [0.0f, 1.0f]
}
}
void TrackPropertiesWindow::FloatToRGB8(const float* src, u8* dst) {
for (int i = 0; i < 3; ++i) {
dst[i] = static_cast<u8>(src[i] * 255.0f); // Scale to [0, 255] range
}
}
}