From 32632cacdb316d7f2d3b6ecdb634f0ef9aebadf0 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Wed, 14 May 2025 18:30:32 -0600 Subject: Impl new intro (#193) * Update menus * Update CMakeLists.txt * Add Ship * Impl hm ship actors * Update HM course * Impl new intro * Finish intro scene * Rename * Start Editor Work * raycast works * Fix ScreenRayTrace in widescreen * Basic Actor Picking * wip * Editor use vtx collision * gizmo work * otr works for object picking * Impl objects for editor * actor init * Update * Add all axis move (freemove) * Docking Windows works here * Setup imgui layout for editor * Editor Snap to Ground works * Basic Scene Explorer Works * Editor get actor names * Impl editor object names * impl Editor Play and Pause buttons * Editor translate works while paused * Fix freecam lighting * Added adjustable track properties to editor * Editor matrix, icons, rotation, impl light * Setup Track Properties 1 * Editor tooling wip * Load modded o2rs * Don't enable hud if editor is enabled * Updates * SceneManager nearly working * Fix mario kart 64 intro logo sizing * Fix Rotator * Finish new matrix translation code * Cleanup headers * Cleanup * Cleanup 2 * Cleanup 3 * Prevent divize by zero crash * Add visible circle for translate in all axis * Editor scaling/rot works properly now * Scale All_Axis evenly * Fixes to includes to work on Linux. * Removed overfilled arguments in gfx_create_framebuffer() * Added missing function definitions to Game.h * Editor sun face the camera * Add rotation model to gizmo * Add new handles * Failed attempt at transforming collision * Impl water volume * Import fast64 paths * water surface * Scene Setup 1 * Custom Track O2R almost working needs testing * Custom Track Load path O2r * Render custom track. Wip collision * Add missing function * Debug Spawning Custom O2R Track * Import courses working now * Fix memory leak * Remove New Track Button * Engine.cpp more consistent with sf64 * Fix Editor Enable Button * Editor Accurate mouse click drag objects * Editor selects closest object and cleanup * Gizmo rot and scale collision working * Remove constexpr from IRotator * Impl properties for location/rot/scale * Better Properties display, swap rot handles * Fix content browser dock and editor now disabled by default * Remove GameInfoWindow, Multiplayer Button, and FPS Slider * Disable Editor when its disabled * Add new logo to hm intro * Fix pause menu item box cursor * Remove minimap from Course::from_json and to_json * Impl Import Minimap * Fix custom minimap rendering * minimap uses extension .png * Refactor minimap * Freecam only for player 1 * GrandPrix Balloons work in custom track * Track Id is now std::string and outside of Props * Moved editor assets to be included in ship.o2r * Fixed GenerateO2R to package the correct folder and save to the correct filename * Linux specific changes. * Added "#include " that required them * Changed how the "ship.o2r" file is loaded to allow it to load the file from within appimages. * Changed the Linuxdeploy version to avoid errors later when the Github Actions creates appimages(same fix applied to other ports.) * Revert "Moved editor assets to be included in ship.o2r" This reverts commit 05704c01f761baa67a83e357d9765f5c6b5e3fdb. * Added back files(this time without LUS changes) * Changed workflow file to use correct filename for assets file. * Missed a few spots in the workflow file. * Added .desktop file and made corrections to the main workflow. * Added the rest of upstream CMakeLists.txt * disabled USE_NETWORKING * New InverseMatrix * Renamed both .o2r files to be more accurate to its contents. * Reverted CmakeList.txt --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com> Co-authored-by: sitton76 <58642183+sitton76@users.noreply.github.com> --- src/engine/courses/Course.cpp | 178 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 16 deletions(-) (limited to 'src/engine/courses/Course.cpp') diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp index 3e5c0b2ab..bbc9455fe 100644 --- a/src/engine/courses/Course.cpp +++ b/src/engine/courses/Course.cpp @@ -3,6 +3,9 @@ #include "Course.h" #include "MarioRaceway.h" #include "ChocoMountain.h" +#include "port/Game.h" +#include "port/resource/type/TrackWaypoint.h" +#include "port/resource/type/TrackSections.h" extern "C" { #include "main.h" @@ -18,20 +21,36 @@ extern "C" { #include "staff_ghosts.h" #include "code_800029B0.h" #include "render_courses.h" +#include "collision.h" +#include "actors.h" extern StaffGhost* d_mario_raceway_staff_ghost; } Course::Course() { // Props.Name = "Course Name"; // Props.DebugName = "CName"; - // Props.CourseLength = "567m"; + Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength)); // Props.Cup = FLOWER_CUP; // Props.CupIndex = 3; + Id = ""; + Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway; + Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture); + Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture); + Props.Minimap.Pos[0].X = 257; + Props.Minimap.Pos[0].Y = 170; + Props.Minimap.PlayerX = 0; + Props.Minimap.PlayerY = 0; + Props.Minimap.PlayerScaleFactor = 0.22f; + Props.Minimap.FinishlineX = 0; + Props.Minimap.FinishlineY = 0; + Props.Minimap.Colour = {255, 255, 255}; + Props.WaterLevel = -10.0f; + Props.LakituTowType = (s32) OLakitu::LakituTowType::NORMAL; Props.AIBehaviour = D_0D008F28; Props.AIMaximumSeparation = 50.0f; Props.AIMinimumSeparation = 0.3f; - Props.SomePtr = D_800DCB34; + Props.AIDistance = gMarioRacewayAIDistances; Props.AISteeringSensitivity = 48; Props.NearPersp = 3.0f; @@ -71,11 +90,10 @@ Course::Course() { Props.Clouds = NULL; Props.CloudList = NULL; - Props.MinimapFinishlineX = 0; - Props.MinimapFinishlineY = 0; Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN; } +// Load custom track from code void Course::Load(Vtx* vtx, Gfx* gfx) { gSegmentTable[4] = reinterpret_cast(&vtx[0]); gSegmentTable[7] = reinterpret_cast(&gfx[0]); @@ -83,8 +101,60 @@ void Course::Load(Vtx* vtx, Gfx* gfx) { Course::Init(); } +void Course::LoadO2R(std::string trackPath) { + if (!trackPath.empty()) { + TrackSectionsPtr = (trackPath + "/data_track_sections"); + + std::string path_file = (trackPath + "/data_paths").c_str(); + + auto res = std::dynamic_pointer_cast(ResourceLoad(path_file.c_str())); + + if (res != nullptr) { + auto& paths = res->PathList; + + size_t i = 0; + for (auto& path : paths) { + if (i == 0) { + Props.PathTable[0] = (TrackWaypoint*)path.data(); + Props.PathTable[1] = NULL; + Props.PathTable[2] = NULL; + Props.PathTable[3] = NULL; + Props.PathTable2[0] = (TrackWaypoint*)path.data(); + Props.PathTable2[1] = NULL; + Props.PathTable2[2] = NULL; + Props.PathTable2[3] = NULL; + } + + i += 1; + } + } + + } else { + printf("Course.cpp: LoadO2R: trackPath str is empty\n"); + } +} + +// Load stock track void Course::Load() { + // Load from O2R + if (!TrackSectionsPtr.empty()) { + bIsMod = true; + //auto res = std::dynamic_pointer_cast(ResourceLoad(TrackSectionsPtr.c_str())); + + TrackSectionsO2R* sections = (TrackSectionsO2R*) LOAD_ASSET_RAW(TrackSectionsPtr.c_str()); + size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str()); + + if (sections != nullptr) { + Course::Init(); + ParseCourseSections(sections, size); + func_80295C6C(); + Props.WaterLevel = gCourseMinY - 10.0f; + } + return; + } + + // Stock size_t vtxSize = (ResourceGetSizeByName(this->vtx) / sizeof(CourseVtx)) * sizeof(Vtx); size_t texSegSize; @@ -129,6 +199,53 @@ void Course::Load() { Course::Init(); } +// C++ version of parse_course_displaylists() +void Course::ParseCourseSections(TrackSectionsO2R* sections, size_t size) { + for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) { + if (sections[i].flags & 0x8000) { + D_8015F59C = 1; + } else { + D_8015F59C = 0; + } + if (sections[i].flags & 0x2000) { + D_8015F5A0 = 1; + } else { + D_8015F5A0 = 0; + } + if (sections[i].flags & 0x4000) { + D_8015F5A4 = 1; + } else { + D_8015F5A4 = 0; + } + printf("LOADING DL %s\n", sections[i].addr.c_str()); + generate_collision_mesh((Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()), sections[i].surfaceType, sections[i].sectionId); + } +} + +void Course::TestPath() { + // DEBUG ONLY TO VISUALIZE PATH + return; + s16 x; + s16 y; + s16 z; + Vec3s rot = {0, 0, 0}; + Vec3f vel = {0, 0, 0}; + + for (size_t i = 0; i < gWaypointCountByPathIndex[0]; i++) { + x = D_80164550[0][i].posX; + y = D_80164550[0][i].posY; + z = D_80164550[0][i].posZ; + + if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) { + break; + } + + f32 height = spawn_actor_on_surface(x, 2000.0f, z); + Vec3f itemPos = {x, height, z}; + add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX); + } +} + void Course::Init() { gNumActors = 0; gCourseMinX = 0; @@ -153,6 +270,7 @@ void Course::LoadTextures() { } void Course::BeginPlay() { + TestPath(); } void Course::InitClouds() { @@ -181,9 +299,6 @@ void Course::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f ar func_8003E048(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -void Course::MinimapSettings() { -} - void Course::InitCourseObjects() { } @@ -206,13 +321,6 @@ void Course::WhatDoesThisDo(Player* player, int8_t playerId) { void Course::WhatDoesThisDoAI(Player* player, int8_t playerId) { } -// Positions the finishline on the minimap -void Course::MinimapFinishlinePosition() { - //! todo: Place hard-coded values here. - draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, - (u8*) common_texture_minimap_finish_line); -} - void Course::SetStaffGhost() { D_80162DD6 = 1; D_80162DF4 = 1; @@ -226,11 +334,49 @@ void Course::Waypoints(Player* player, int8_t playerId) { } void Course::Render(struct UnkStruct_800DC5EC* arg0) { + if (!TrackSectionsPtr.empty()) { + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); + // set_track_light_direction(D_800DC610, D_802B87D4, 0, 1); + gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + + if (func_80290C20(arg0->camera) == 1) { + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2); + // d_course_big_donut_packed_dl_DE8 + } + + TrackSectionsO2R* sections = (TrackSectionsO2R*)LOAD_ASSET_RAW(TrackSectionsPtr.c_str()); + size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str()); + for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) { + gSPDisplayList(gDisplayListHead++, (Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str())); + } + } } + void Course::RenderCredits() { } -void Course::Collision() { + +f32 Course::GetWaterLevel(FVector pos, Collision* collision) { + float highestWater = -FLT_MAX; + bool found = false; + + for (const auto& volume : gWorldInstance.CurrentCourse->WaterVolumes) { + if (pos.x >= volume.MinX && pos.x <= volume.MaxX && + pos.z >= volume.MinZ && pos.z <= volume.MaxZ) { + // Choose the highest water volume the player is over + if (!found || volume.Height > highestWater) { + highestWater = volume.Height; + found = true; + } + } + } + + // If player is not over-top of a water volume then return the courses default water level + return found ? highestWater : gWorldInstance.CurrentCourse->Props.WaterLevel; } + void Course::ScrollingTextures() { } void Course::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, @@ -241,7 +387,7 @@ void Course::Destroy() { } bool Course::IsMod() { - return false; + return bIsMod; } Course* currentCourse = nullptr; -- cgit v1.2.3