From 73df85276e5c1fd3f327bf95007982eb2d6de740 Mon Sep 17 00:00:00 2001 From: Prince Frizzy Date: Tue, 5 Apr 2022 16:44:05 -0400 Subject: [PATCH] Add support for dynamic water regions. (#55) * Add support for dynamic water regions. --- data/dynos.c.h | 2 + data/dynos.cpp.h | 1 + data/dynos_c.cpp | 8 ++++ data/dynos_misc.cpp | 21 ++++++++- src/game/moving_texture.c | 91 ++++++++++++++++++++++++++++++--------- src/game/moving_texture.h | 1 + 6 files changed, 103 insertions(+), 21 deletions(-) diff --git a/data/dynos.c.h b/data/dynos.c.h index 3f48ace5..c7e5822c 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -4,6 +4,7 @@ #include "dynos.h" #include "types.h" +#include "src/game/moving_texture.h" // -- built in -- // void *dynos_update_cmd (void *cmd); @@ -37,6 +38,7 @@ Collision* dynos_collision_get(const char* collisionName); void dynos_add_level(s32 modIndex, const char *modPath, const char* levelName); LevelScript* dynos_level_get(const char* levelName); +struct MovtexQuadCollection *dynos_level_movtexqc_getfromindex(s32 index); #endif #endif diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 49cfff09..e3fd12cb 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -722,6 +722,7 @@ void DynOS_Lvl_Add(s32 modIndex, const SysPath &aPackFolder, const char *aLevelN LevelScript* DynOS_Lvl_Get(const char* levelName); s32 DynOS_Lvl_GetModIndex(void* levelScript); DataNode *DynOS_Lvl_Texture_Get(void *aPtr); +DataNode *DynOS_Lvl_MovtexQuadCollection_GetFromIndex(s32 index); // // Warps diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index b23ec32e..7c248493 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -1,5 +1,6 @@ #include "dynos.cpp.h" extern "C" { +#include "src/game/moving_texture.h" // -- built in -- // @@ -107,4 +108,11 @@ LevelScript* dynos_level_get(const char* levelName) { return DynOS_Lvl_Get(levelName); } +struct MovtexQuadCollection *dynos_level_movtexqc_getfromindex(s32 index) { + DataNode *node = DynOS_Lvl_MovtexQuadCollection_GetFromIndex(index); + if (node == NULL) { return NULL; } + + return node->mData; +} + } diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 2456fa70..9a842cfd 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -1,6 +1,7 @@ #include "dynos.cpp.h" extern "C" { #include "object_fields.h" +#include "engine/level_script.h" #include "game/object_helpers.h" #include "game/segment2.h" #include "game/level_geo.h" @@ -501,6 +502,7 @@ static const Array> sGeoFunctions = { define_geo_function(geo_switch_peach_eyes), // coop-specific define_geo_function(geo_mario_set_player_colors), + define_geo_function(geo_movtex_draw_water_regions_ext), }; #undef define_geo_function return sGeoFunctions; @@ -1132,7 +1134,9 @@ void DynOS_Lvl_Add(s32 modIndex, const SysPath &aPackFolder, const char *aLevelN LevelScript* DynOS_Lvl_Get(const char* levelName) { static u32 index = 0; // DO NOT COMMIT - index = (index + 1) % sDynosCustomLevelScripts.Count(); // DO NOT COMMIT + s32 levelScriptCount = sDynosCustomLevelScripts.Count(); // DO NOT COMMIT + if (levelScriptCount < 1) { return NULL; } // DO NOT COMMIT + index = (index + 1) % levelScriptCount; // DO NOT COMMIT auto& scripts = sDynosCustomLevelScripts[index].second->mLevelScripts; // DO NOT COMMIT Print("Going to level: %s\n", scripts[scripts.Count() - 1]->mName); // DO NOT COMMIT return scripts[scripts.Count() - 1]->mData; // DO NOT COMMIT @@ -1168,4 +1172,19 @@ DataNode *DynOS_Lvl_Texture_Get(void *aPtr) { } } return NULL; +} + +DataNode *DynOS_Lvl_MovtexQuadCollection_GetFromIndex(s32 index) { + s32 modIndex = gLevelScriptModIndex - 1; + // Sanity check our currently loaded mod. + if (modIndex < 0 || modIndex >= sDynosCustomLevelScripts.Count()) { return NULL; } + + auto &mMovtexQCs = sDynosCustomLevelScripts[modIndex].second->mMovtexQCs; + + // Sanity check the index we passed. + if (index < 0 || index >= mMovtexQCs.Count()) { return NULL; } + + auto &movetexQC = mMovtexQCs[index]; + + return movetexQC; } \ No newline at end of file diff --git a/src/game/moving_texture.c b/src/game/moving_texture.c index 94b69d54..0729e2af 100644 --- a/src/game/moving_texture.c +++ b/src/game/moving_texture.c @@ -13,6 +13,7 @@ #include "geo_misc.h" #include "rendering_graph_node.h" #include "object_list_processor.h" +#include "data/dynos.c.h" /** * This file contains functions for generating display lists with moving textures @@ -621,28 +622,25 @@ void movtex_change_texture_format(u32 quadCollectionId, Gfx **gfx) { */ Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx) { Gfx *gfxHead = NULL; - Gfx *gfx = NULL; - Gfx *subList; - void *quadCollection; - struct GraphNodeGenerated *asGenerated; - s16 numWaterBoxes; - s16 waterId; - s16 waterY; - s32 i; if (callContext == GEO_CONTEXT_RENDER) { gMovtexVtxColor = MOVTEX_VTX_COLOR_DEFAULT; if (gEnvironmentRegions == NULL) { return NULL; } - numWaterBoxes = gEnvironmentRegions[0]; + s16 numWaterBoxes = gEnvironmentRegions[0]; gfxHead = alloc_display_list((numWaterBoxes + 3) * sizeof(*gfxHead)); if (gfxHead == NULL) { return NULL; - } else { - gfx = gfxHead; } - asGenerated = (struct GraphNodeGenerated *) node; + + Gfx *gfx = gfxHead; + + struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node; + if (asGenerated == NULL) { + return NULL; + } + if (asGenerated->parameter == JRB_MOVTEX_INTIAL_MIST) { if (gLakituState.goalPos[1] < 1024.0) { // if camera under water return NULL; @@ -655,22 +653,75 @@ Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUS } else if (asGenerated->parameter == SSL_MOVTEX_TOXBOX_QUICKSAND_MIST) { gMovtexVtxColor = MOVTEX_VTX_COLOR_RED; } - quadCollection = get_quad_collection_from_id(asGenerated->parameter); + + void *quadCollection = get_quad_collection_from_id(asGenerated->parameter); if (quadCollection == NULL) { return NULL; } - asGenerated->fnNode.node.flags = - (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_TRANSPARENT_INTER << 8); + asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_TRANSPARENT_INTER << 8); movtex_change_texture_format(asGenerated->parameter, &gfx); gMovetexLastTextureId = -1; - for (i = 0; i < numWaterBoxes; i++) { - waterId = gEnvironmentRegions[i * 6 + 1]; - waterY = gEnvironmentRegions[i * 6 + 6]; - subList = movtex_gen_quads_id(waterId, waterY, quadCollection); - if (subList != NULL) + for (s32 i = 0; i < numWaterBoxes; i++) { + s16 waterId = gEnvironmentRegions[i * 6 + 1]; + s16 waterY = gEnvironmentRegions[i * 6 + 6]; + Gfx *subList = movtex_gen_quads_id(waterId, waterY, quadCollection); + if (subList != NULL) { gSPDisplayList(gfx++, VIRTUAL_TO_PHYSICAL(subList)); + } + } + gSPDisplayList(gfx++, dl_waterbox_end); + gSPEndDisplayList(gfx); + } + return gfxHead; +} + +/** + * Geo script responsible for drawing quads with a moving texture at the height + * of the corresponding water region for DynOS. The node's parameter determines which quad + * collection is drawn, see moving_texture.h. + */ +Gfx *geo_movtex_draw_water_regions_ext(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx) { + Gfx *gfxHead = NULL; + void *quadCollection = NULL; + + if (callContext == GEO_CONTEXT_RENDER) { + if (gEnvironmentRegions == NULL) { + return NULL; + } + + gMovtexVtxColor = MOVTEX_VTX_COLOR_DEFAULT; + + s16 numWaterBoxes = gEnvironmentRegions[0]; + gfxHead = alloc_display_list((numWaterBoxes + 3) * sizeof(*gfxHead)); + if (gfxHead == NULL) { + return NULL; + } + + Gfx *gfx = gfxHead; + + struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node; + if (asGenerated == NULL) { + return NULL; + } + + quadCollection = dynos_level_movtexqc_getfromindex(asGenerated->parameter); + if (quadCollection == NULL) { + return NULL; + } + + asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_TRANSPARENT_INTER << 8); + + movtex_change_texture_format(asGenerated->parameter, &gfx); + gMovetexLastTextureId = -1; + for (s32 i = 0; i < numWaterBoxes; i++) { + s16 waterId = gEnvironmentRegions[i * 6 + 1]; + s16 waterY = gEnvironmentRegions[i * 6 + 6]; + Gfx *subList = movtex_gen_quads_id(waterId, waterY, quadCollection); + if (subList != NULL) { + gSPDisplayList(gfx++, VIRTUAL_TO_PHYSICAL(subList)); + } } gSPDisplayList(gfx++, dl_waterbox_end); gSPEndDisplayList(gfx); diff --git a/src/game/moving_texture.h b/src/game/moving_texture.h index 9d2e3db1..d8ad31bc 100644 --- a/src/game/moving_texture.h +++ b/src/game/moving_texture.h @@ -114,6 +114,7 @@ extern f32 gPaintingMarioYEntry; Gfx *geo_wdw_set_initial_water_level(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx); Gfx *geo_movtex_pause_control(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx); Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); +Gfx *geo_movtex_draw_water_regions_ext(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); Gfx *geo_movtex_draw_nocolor(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); Gfx *geo_movtex_draw_colored(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); Gfx *geo_movtex_draw_colored_no_update(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);