From b4c8f023d2e9f9d835fb0018407972004c72eaff Mon Sep 17 00:00:00 2001 From: PeachyPeachSM64 <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Sun, 5 Oct 2025 12:12:14 +0200 Subject: [PATCH] Make painting textures replaceable by Lua Fix `textureArray` type to be recognized by autogen. Painting textures can be replaced with the following code: ``` local tex1 = get_texture_info("texture_bottom") local tex2 = get_texture_info("texture_top") gPaintingValues.bob_painting.textureArray[1] = tex1.texture gPaintingValues.bob_painting.textureArray[2] = tex2.texture ``` Texture format must be RGBA 16-bit for built-in textures or RGBA 32-bit for mod loaded textures. --- autogen/convert_structs.py | 1 + autogen/lua_definitions/structs.lua | 4 +- docs/lua/structs.md | 3 +- levels/castle_inside/painting.inc.c | 78 ++++++++++++++--------------- levels/hmc/areas/1/painting.inc.c | 6 +-- levels/ttm/areas/1/painting.inc.c | 6 +-- src/game/paintings.c | 34 ++++++++++++- src/game/paintings.h | 2 +- src/pc/lua/smlua_cobject_autogen.c | 78 ++++++++++++++--------------- 9 files changed, 120 insertions(+), 92 deletions(-) diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index c8af5f8e1..9216d915e 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -96,6 +96,7 @@ override_field_invisible = { "Object": [ "firstSurface" ], "Animation": [ "unusedBoneCount" ], "ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ], + "Painting": [ "normalDisplayList", "textureMaps", "rippleDisplayList", "ripples" ], "DialogEntry": [ "str" ], "ModFsFile": [ "data", "capacity" ], "ModFs": [ "files" ], diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 8dfc585dc..76a1c2a0f 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -2176,10 +2176,9 @@ --- @field public rippleTimer number --- @field public rippleX number --- @field public rippleY number ---- @field public normalDisplayList Pointer_Gfx +--- @field public textureArray Pointer_Texture[] --- @field public textureWidth integer --- @field public textureHeight integer ---- @field public rippleDisplayList Pointer_Gfx --- @field public rippleTrigger integer --- @field public alpha integer --- @field public marioWasUnder integer @@ -2528,4 +2527,5 @@ --- @alias Pointer_Mat4 Mat4 --- @alias Pointer_Vec4s Vec4s --- @alias Pointer_BehaviorScript BehaviorScript +--- @alias Pointer_Texture[] Texture[] --- @alias Pointer_Texture Texture diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 4050f958e..6ba8fff59 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -2947,10 +2947,9 @@ | rippleTimer | `number` | | | rippleX | `number` | | | rippleY | `number` | | -| normalDisplayList | `Pointer` <`Gfx`> | read-only | +| textureArray | `Array` <`Pointer` <`Texture`>> | read-only | | textureWidth | `integer` | read-only | | textureHeight | `integer` | read-only | -| rippleDisplayList | `Pointer` <`Gfx`> | read-only | | rippleTrigger | `integer` | | | alpha | `integer` | | | marioWasUnder | `integer` | | diff --git a/levels/castle_inside/painting.inc.c b/levels/castle_inside/painting.inc.c index fac982371..c12f799bc 100644 --- a/levels/castle_inside/painting.inc.c +++ b/levels/castle_inside/painting.inc.c @@ -1255,57 +1255,57 @@ static const Gfx inside_castle_seg7_painting_dl_070235B8[] = { gsSPBranchList(inside_castle_seg7_painting_dl_07023580), }; -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235C0[] = { - inside_castle_seg7_texture_0700B800, inside_castle_seg7_texture_0700A800, -}; +#define inside_castle_seg7_painting_textures_070235C0 { \ + inside_castle_seg7_texture_0700B800, inside_castle_seg7_texture_0700A800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235C8[] = { - inside_castle_seg7_texture_0700D800, inside_castle_seg7_texture_0700C800, -}; +#define inside_castle_seg7_painting_textures_070235C8 { \ + inside_castle_seg7_texture_0700D800, inside_castle_seg7_texture_0700C800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235D0[] = { - inside_castle_seg7_texture_0700F800, inside_castle_seg7_texture_0700E800, -}; +#define inside_castle_seg7_painting_textures_070235D0 { \ + inside_castle_seg7_texture_0700F800, inside_castle_seg7_texture_0700E800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235D8[] = { - inside_castle_seg7_texture_07011800, inside_castle_seg7_texture_07010800, -}; +#define inside_castle_seg7_painting_textures_070235D8 { \ + inside_castle_seg7_texture_07011800, inside_castle_seg7_texture_07010800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235E0[] = { - inside_castle_seg7_texture_07012800, inside_castle_seg7_texture_07013800, -}; +#define inside_castle_seg7_painting_textures_070235E0 { \ + inside_castle_seg7_texture_07012800, inside_castle_seg7_texture_07013800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235E8[] = { - inside_castle_seg7_texture_07015800, inside_castle_seg7_texture_07014800, -}; +#define inside_castle_seg7_painting_textures_070235E8 { \ + inside_castle_seg7_texture_07015800, inside_castle_seg7_texture_07014800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F0[] = { - inside_castle_seg7_texture_07016800, -}; +#define inside_castle_seg7_painting_textures_070235F0 { \ + inside_castle_seg7_texture_07016800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F4[] = { - inside_castle_seg7_texture_07017000, -}; +#define inside_castle_seg7_painting_textures_070235F4 { \ + inside_castle_seg7_texture_07017000, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F8[] = { - inside_castle_seg7_texture_07018800, inside_castle_seg7_texture_07017800, -}; +#define inside_castle_seg7_painting_textures_070235F8 { \ + inside_castle_seg7_texture_07018800, inside_castle_seg7_texture_07017800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023600[] = { - inside_castle_seg7_texture_0701A800, inside_castle_seg7_texture_07019800, -}; +#define inside_castle_seg7_painting_textures_07023600 { \ + inside_castle_seg7_texture_0701A800, inside_castle_seg7_texture_07019800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023608[] = { - inside_castle_seg7_texture_0701C800, inside_castle_seg7_texture_0701B800, -}; +#define inside_castle_seg7_painting_textures_07023608 { \ + inside_castle_seg7_texture_0701C800, inside_castle_seg7_texture_0701B800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023610[] = { - inside_castle_seg7_texture_0701E800, inside_castle_seg7_texture_0701D800, -}; +#define inside_castle_seg7_painting_textures_07023610 { \ + inside_castle_seg7_texture_0701E800, inside_castle_seg7_texture_0701D800, \ +} -ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023618[] = { - inside_castle_seg7_texture_07020800, inside_castle_seg7_texture_0701F800, -}; +#define inside_castle_seg7_painting_textures_07023618 { \ + inside_castle_seg7_texture_07020800, inside_castle_seg7_texture_0701F800, \ +} // 0x07023620 - 0x07023698 struct Painting bob_painting = { diff --git a/levels/hmc/areas/1/painting.inc.c b/levels/hmc/areas/1/painting.inc.c index ebad311eb..871750397 100644 --- a/levels/hmc/areas/1/painting.inc.c +++ b/levels/hmc/areas/1/painting.inc.c @@ -505,9 +505,9 @@ static const Gfx hmc_seg7_painting_dl_070254E0[] = { }; // 0x07025518 - 0x07025594 -const Texture *const hmc_seg7_painting_textures_07025518[] = { - hmc_seg7_texture_07024CE0, -}; +#define hmc_seg7_painting_textures_07025518 { \ + hmc_seg7_texture_07024CE0, \ +} // 0x0702551C (PaintingData) struct Painting cotmc_painting = { diff --git a/levels/ttm/areas/1/painting.inc.c b/levels/ttm/areas/1/painting.inc.c index fea728990..2ae5d05db 100644 --- a/levels/ttm/areas/1/painting.inc.c +++ b/levels/ttm/areas/1/painting.inc.c @@ -537,9 +537,9 @@ static const Gfx ttm_seg7_painting_dl_07012E98[] = { }; // 0x07012EF8 - 0x07012F78 -ALIGNED8 const Texture *const ttm_seg7_painting_textures_07012EF8[] = { - ttm_seg7_texture_07004000, ttm_seg7_texture_07003000, -}; +#define ttm_seg7_painting_textures_07012EF8 { \ + ttm_seg7_texture_07004000, ttm_seg7_texture_07003000, \ +} // 0x07012F00 (PaintingData) struct Painting ttm_slide_painting = { diff --git a/src/game/paintings.c b/src/game/paintings.c index 574e6bc45..071337531 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -20,6 +20,7 @@ #include "obj_behaviors.h" #include "level_update.h" #include "pc/network/network_player.h" +#include "pc/lua/utils/smlua_gfx_utils.h" #include "print.h" #include "hardcoded.h" @@ -1537,6 +1538,31 @@ Gfx *display_painting_rippling(struct Painting *painting) { return dlist; } +static Gfx *get_painting_normal_display_list(struct Painting *painting) { + const Gfx *normalDisplayList = painting->normalDisplayList; + if (!normalDisplayList) { + return NULL; + } + + u32 dlistLength = gfx_get_length_no_sentinel(normalDisplayList); + Gfx *dlist = alloc_display_list(dlistLength * sizeof(Gfx)); + if (!dlist) { + return NULL; + } + + Gfx *gfx = dlist; + s8 textureIndex = 0; + for (u32 i = 0; i < dlistLength; ++i, gfx++, normalDisplayList++) { + *gfx = *normalDisplayList; + + // Replace the texture pointer by the painting's corresponding texture + if (GFX_OP(normalDisplayList) == G_SETTIMG && textureIndex < painting->imageCount) { + gfx->words.w1 = (uintptr_t) painting->textureArray[textureIndex++]; + } + } + return dlist; +} + /** * Render a normal painting. */ @@ -1547,8 +1573,14 @@ Gfx *display_painting_not_rippling(struct Painting *painting) { if (dlist == NULL) { return dlist; } + + Gfx *normalDisplayList = get_painting_normal_display_list(painting); + if (!normalDisplayList) { + return NULL; + } + gSPDisplayList(gfx++, painting_model_view_transform(painting)); - gSPDisplayList(gfx++, painting->normalDisplayList); + gSPDisplayList(gfx++, normalDisplayList); gSPPopMatrix(gfx++, G_MTX_MODELVIEW); gSPEndDisplayList(gfx); return dlist; diff --git a/src/game/paintings.h b/src/game/paintings.h index 086c9fafd..98fe85fd8 100644 --- a/src/game/paintings.h +++ b/src/game/paintings.h @@ -109,7 +109,7 @@ struct Painting const s16 *const *textureMaps; // Texture data - const Texture *const *textureArray; + const Texture *textureArray[2]; s16 textureWidth; s16 textureHeight; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index aced624c1..2bd02f925 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -2521,48 +2521,44 @@ static struct LuaObjectField sOffsetSizePairFields[LUA_OFFSET_SIZE_PAIR_FIELD_CO { "size", LVT_U32, offsetof(struct OffsetSizePair, size), false, LOT_NONE, 1, sizeof(u32) }, }; -#define LUA_PAINTING_FIELD_COUNT 37 +#define LUA_PAINTING_FIELD_COUNT 36 static struct LuaObjectField sPaintingFields[LUA_PAINTING_FIELD_COUNT] = { - { "alpha", LVT_U8, offsetof(struct Painting, alpha), false, LOT_NONE, 1, sizeof(u8) }, - { "currFloor", LVT_S8, offsetof(struct Painting, currFloor), false, LOT_NONE, 1, sizeof(s8) }, - { "currRippleMag", LVT_F32, offsetof(struct Painting, currRippleMag), false, LOT_NONE, 1, sizeof(f32) }, - { "currRippleRate", LVT_F32, offsetof(struct Painting, currRippleRate), false, LOT_NONE, 1, sizeof(f32) }, - { "dispersionFactor", LVT_F32, offsetof(struct Painting, dispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, - { "entryDispersionFactor", LVT_F32, offsetof(struct Painting, entryDispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, - { "entryRippleDecay", LVT_F32, offsetof(struct Painting, entryRippleDecay), false, LOT_NONE, 1, sizeof(f32) }, - { "entryRippleMag", LVT_F32, offsetof(struct Painting, entryRippleMag), false, LOT_NONE, 1, sizeof(f32) }, - { "entryRippleRate", LVT_F32, offsetof(struct Painting, entryRippleRate), false, LOT_NONE, 1, sizeof(f32) }, - { "floorEntered", LVT_S8, offsetof(struct Painting, floorEntered), false, LOT_NONE, 1, sizeof(s8) }, - { "id", LVT_S16, offsetof(struct Painting, id), true, LOT_NONE, 1, sizeof(s16) }, - { "imageCount", LVT_S8, offsetof(struct Painting, imageCount), true, LOT_NONE, 1, sizeof(s8) }, - { "lastFloor", LVT_S8, offsetof(struct Painting, lastFloor), false, LOT_NONE, 1, sizeof(s8) }, - { "marioIsUnder", LVT_S8, offsetof(struct Painting, marioIsUnder), false, LOT_NONE, 1, sizeof(s8) }, - { "marioWasUnder", LVT_S8, offsetof(struct Painting, marioWasUnder), false, LOT_NONE, 1, sizeof(s8) }, - { "marioWentUnder", LVT_S8, offsetof(struct Painting, marioWentUnder), false, LOT_NONE, 1, sizeof(s8) }, - { "normalDisplayList", LVT_COBJECT_P, offsetof(struct Painting, normalDisplayList), true, LOT_GFX, 1, sizeof(const Gfx*) }, - { "passiveDispersionFactor", LVT_F32, offsetof(struct Painting, passiveDispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, - { "passiveRippleDecay", LVT_F32, offsetof(struct Painting, passiveRippleDecay), false, LOT_NONE, 1, sizeof(f32) }, - { "passiveRippleMag", LVT_F32, offsetof(struct Painting, passiveRippleMag), false, LOT_NONE, 1, sizeof(f32) }, - { "passiveRippleRate", LVT_F32, offsetof(struct Painting, passiveRippleRate), false, LOT_NONE, 1, sizeof(f32) }, - { "pitch", LVT_F32, offsetof(struct Painting, pitch), false, LOT_NONE, 1, sizeof(f32) }, - { "posX", LVT_F32, offsetof(struct Painting, posX), false, LOT_NONE, 1, sizeof(f32) }, - { "posY", LVT_F32, offsetof(struct Painting, posY), false, LOT_NONE, 1, sizeof(f32) }, - { "posZ", LVT_F32, offsetof(struct Painting, posZ), false, LOT_NONE, 1, sizeof(f32) }, - { "rippleDecay", LVT_F32, offsetof(struct Painting, rippleDecay), false, LOT_NONE, 1, sizeof(f32) }, - { "rippleDisplayList", LVT_COBJECT_P, offsetof(struct Painting, rippleDisplayList), true, LOT_GFX, 1, sizeof(const Gfx*) }, - { "rippleTimer", LVT_F32, offsetof(struct Painting, rippleTimer), false, LOT_NONE, 1, sizeof(f32) }, - { "rippleTrigger", LVT_S8, offsetof(struct Painting, rippleTrigger), false, LOT_NONE, 1, sizeof(s8) }, - { "rippleX", LVT_F32, offsetof(struct Painting, rippleX), false, LOT_NONE, 1, sizeof(f32) }, - { "rippleY", LVT_F32, offsetof(struct Painting, rippleY), false, LOT_NONE, 1, sizeof(f32) }, -// { "ripples", LVT_???, offsetof(struct Painting, ripples), false, LOT_???, 1, sizeof(struct { ... }) }, <--- UNIMPLEMENTED - { "size", LVT_F32, offsetof(struct Painting, size), false, LOT_NONE, 1, sizeof(f32) }, - { "state", LVT_S8, offsetof(struct Painting, state), false, LOT_NONE, 1, sizeof(s8) }, -// { "textureArray", LVT_???, offsetof(struct Painting, textureArray), true, LOT_???, 1, sizeof(const Texture *const*) }, <--- UNIMPLEMENTED - { "textureHeight", LVT_S16, offsetof(struct Painting, textureHeight), true, LOT_NONE, 1, sizeof(s16) }, -// { "textureMaps", LVT_???, offsetof(struct Painting, textureMaps), true, LOT_???, 1, sizeof(const s16 *const*) }, <--- UNIMPLEMENTED - { "textureType", LVT_S8, offsetof(struct Painting, textureType), true, LOT_NONE, 1, sizeof(s8) }, - { "textureWidth", LVT_S16, offsetof(struct Painting, textureWidth), true, LOT_NONE, 1, sizeof(s16) }, - { "yaw", LVT_F32, offsetof(struct Painting, yaw), false, LOT_NONE, 1, sizeof(f32) }, + { "alpha", LVT_U8, offsetof(struct Painting, alpha), false, LOT_NONE, 1, sizeof(u8) }, + { "currFloor", LVT_S8, offsetof(struct Painting, currFloor), false, LOT_NONE, 1, sizeof(s8) }, + { "currRippleMag", LVT_F32, offsetof(struct Painting, currRippleMag), false, LOT_NONE, 1, sizeof(f32) }, + { "currRippleRate", LVT_F32, offsetof(struct Painting, currRippleRate), false, LOT_NONE, 1, sizeof(f32) }, + { "dispersionFactor", LVT_F32, offsetof(struct Painting, dispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, + { "entryDispersionFactor", LVT_F32, offsetof(struct Painting, entryDispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, + { "entryRippleDecay", LVT_F32, offsetof(struct Painting, entryRippleDecay), false, LOT_NONE, 1, sizeof(f32) }, + { "entryRippleMag", LVT_F32, offsetof(struct Painting, entryRippleMag), false, LOT_NONE, 1, sizeof(f32) }, + { "entryRippleRate", LVT_F32, offsetof(struct Painting, entryRippleRate), false, LOT_NONE, 1, sizeof(f32) }, + { "floorEntered", LVT_S8, offsetof(struct Painting, floorEntered), false, LOT_NONE, 1, sizeof(s8) }, + { "id", LVT_S16, offsetof(struct Painting, id), true, LOT_NONE, 1, sizeof(s16) }, + { "imageCount", LVT_S8, offsetof(struct Painting, imageCount), true, LOT_NONE, 1, sizeof(s8) }, + { "lastFloor", LVT_S8, offsetof(struct Painting, lastFloor), false, LOT_NONE, 1, sizeof(s8) }, + { "marioIsUnder", LVT_S8, offsetof(struct Painting, marioIsUnder), false, LOT_NONE, 1, sizeof(s8) }, + { "marioWasUnder", LVT_S8, offsetof(struct Painting, marioWasUnder), false, LOT_NONE, 1, sizeof(s8) }, + { "marioWentUnder", LVT_S8, offsetof(struct Painting, marioWentUnder), false, LOT_NONE, 1, sizeof(s8) }, + { "passiveDispersionFactor", LVT_F32, offsetof(struct Painting, passiveDispersionFactor), false, LOT_NONE, 1, sizeof(f32) }, + { "passiveRippleDecay", LVT_F32, offsetof(struct Painting, passiveRippleDecay), false, LOT_NONE, 1, sizeof(f32) }, + { "passiveRippleMag", LVT_F32, offsetof(struct Painting, passiveRippleMag), false, LOT_NONE, 1, sizeof(f32) }, + { "passiveRippleRate", LVT_F32, offsetof(struct Painting, passiveRippleRate), false, LOT_NONE, 1, sizeof(f32) }, + { "pitch", LVT_F32, offsetof(struct Painting, pitch), false, LOT_NONE, 1, sizeof(f32) }, + { "posX", LVT_F32, offsetof(struct Painting, posX), false, LOT_NONE, 1, sizeof(f32) }, + { "posY", LVT_F32, offsetof(struct Painting, posY), false, LOT_NONE, 1, sizeof(f32) }, + { "posZ", LVT_F32, offsetof(struct Painting, posZ), false, LOT_NONE, 1, sizeof(f32) }, + { "rippleDecay", LVT_F32, offsetof(struct Painting, rippleDecay), false, LOT_NONE, 1, sizeof(f32) }, + { "rippleTimer", LVT_F32, offsetof(struct Painting, rippleTimer), false, LOT_NONE, 1, sizeof(f32) }, + { "rippleTrigger", LVT_S8, offsetof(struct Painting, rippleTrigger), false, LOT_NONE, 1, sizeof(s8) }, + { "rippleX", LVT_F32, offsetof(struct Painting, rippleX), false, LOT_NONE, 1, sizeof(f32) }, + { "rippleY", LVT_F32, offsetof(struct Painting, rippleY), false, LOT_NONE, 1, sizeof(f32) }, + { "size", LVT_F32, offsetof(struct Painting, size), false, LOT_NONE, 1, sizeof(f32) }, + { "state", LVT_S8, offsetof(struct Painting, state), false, LOT_NONE, 1, sizeof(s8) }, + { "textureArray", LVT_TEXTURE_P, offsetof(struct Painting, textureArray), true, LOT_POINTER, 2, sizeof(const Texture*) }, + { "textureHeight", LVT_S16, offsetof(struct Painting, textureHeight), true, LOT_NONE, 1, sizeof(s16) }, + { "textureType", LVT_S8, offsetof(struct Painting, textureType), true, LOT_NONE, 1, sizeof(s8) }, + { "textureWidth", LVT_S16, offsetof(struct Painting, textureWidth), true, LOT_NONE, 1, sizeof(s16) }, + { "yaw", LVT_F32, offsetof(struct Painting, yaw), false, LOT_NONE, 1, sizeof(f32) }, }; #define LUA_PAINTING_MESH_VERTEX_FIELD_COUNT 2