Make painting textures replaceable by Lua
Some checks failed
Build coop / build-linux (push) Has been cancelled
Build coop / build-steamos (push) Has been cancelled
Build coop / build-windows-opengl (push) Has been cancelled
Build coop / build-windows-directx (push) Has been cancelled
Build coop / build-macos-arm (push) Has been cancelled
Build coop / build-macos-intel (push) Has been cancelled

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.
This commit is contained in:
PeachyPeachSM64 2025-10-05 12:12:14 +02:00
parent 68f4fd18d7
commit b4c8f023d2
9 changed files with 120 additions and 92 deletions

View file

@ -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" ],

View file

@ -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

View file

@ -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` | |

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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;

View file

@ -109,7 +109,7 @@ struct Painting
const s16 *const *textureMaps;
// Texture data
const Texture *const *textureArray;
const Texture *textureArray[2];
s16 textureWidth;
s16 textureHeight;

View file

@ -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