From 98ff007818dd7377877d77dd29b4d8b12e17db18 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Thu, 5 Jun 2025 22:33:24 +1000 Subject: [PATCH] get_texture_average_color pass in a texture, it returns the average color of the texture --- autogen/lua_definitions/functions.lua | 8 ++++ data/dynos.c.h | 1 + data/dynos.cpp.h | 2 + data/dynos_c.cpp | 4 ++ data/dynos_mgr_builtin_tex.cpp | 20 ++++++++-- data/dynos_mgr_tex.cpp | 56 +++++++++++++++++++-------- docs/lua/functions-6.md | 24 ++++++++++++ docs/lua/functions.md | 1 + src/pc/lua/smlua_functions_autogen.c | 24 ++++++++++++ src/pc/lua/utils/smlua_misc_utils.c | 24 +++++++++++- src/pc/lua/utils/smlua_misc_utils.h | 3 ++ 11 files changed, 145 insertions(+), 22 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 7b891e8c7..4023bf88b 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -11098,6 +11098,14 @@ function geo_get_current_held_object() -- ... end +--- @param tex Pointer_integer +--- @param out Color +--- @return boolean +--- Calculates the average color of a given texture. Returns true if success +function get_texture_average_color(tex, out) + -- ... +end + --- @param name string --- @return ModelExtendedId --- Gets the extended model ID for the `name` of a `GeoLayout` diff --git a/data/dynos.c.h b/data/dynos.c.h index 999b4c640..56f65b360 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -48,6 +48,7 @@ Collision* dynos_collision_get(const char* collisionName); // -- textures -- // void dynos_add_texture(const char *filePath, const char* textureName); bool dynos_texture_get(const char* textureName, struct TextureInfo* outTextureInfo); +bool dynos_texture_get_from_data(const Texture *tex, struct TextureInfo* outTextureInfo); void dynos_texture_override_set(const char* textureName, struct TextureInfo* overrideTextureInfo); void dynos_texture_override_reset(const char* textureName); diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 31414dab7..d3bfa3261 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -862,6 +862,7 @@ const Texture* DynOS_Builtin_Tex_GetFromName(const char* aDataName); const char* DynOS_Builtin_Tex_GetFromData(const Texture* aData); const char* DynOS_Builtin_Tex_GetNameFromFileName(const char* aDataName); const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromName(const char* aDataName); +const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromData(const Texture* aData); const void* DynOS_Builtin_Func_GetFromName(const char* aDataName); const void* DynOS_Builtin_Func_GetFromIndex(s32 aIndex); const char * DynOS_Builtin_Func_GetNameFromIndex(s64 aIndex); @@ -918,6 +919,7 @@ void DynOS_Tex_Activate(DataNode* aNode, bool aCustomTexture); void DynOS_Tex_Deactivate(DataNode* aNode); void DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName); bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo); +bool DynOS_Tex_GetFromData(const Texture *aTex, struct TextureInfo* aOutTexInfo); void DynOS_Tex_Override_Set(const char* textureName, struct TextureInfo* aOverrideTexInfo); void DynOS_Tex_Override_Reset(const char* textureName); void DynOS_Tex_ModShutdown(); diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index 911b8a28d..bac30dd43 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -148,6 +148,10 @@ bool dynos_texture_get(const char* textureName, struct TextureInfo* outTextureIn return DynOS_Tex_Get(textureName, outTextureInfo); } +bool dynos_texture_get_from_data(const Texture *tex, struct TextureInfo* outTextureInfo) { + return DynOS_Tex_GetFromData(tex, outTextureInfo); +} + void dynos_texture_override_set(const char* textureName, struct TextureInfo* overrideTextureInfo) { DynOS_Tex_Override_Set(textureName, overrideTextureInfo); } diff --git a/data/dynos_mgr_builtin_tex.cpp b/data/dynos_mgr_builtin_tex.cpp index 497a84086..29e0b8cbd 100644 --- a/data/dynos_mgr_builtin_tex.cpp +++ b/data/dynos_mgr_builtin_tex.cpp @@ -1153,7 +1153,7 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = { define_builtin_tex(texture_selectionbox_back_icon, "textures/segment2/custom_selectionbox_back_icon.rgba16.png", 16, 16, 16), define_builtin_tex(texture_selectionbox_forward_icon, "textures/segment2/custom_selectionbox_forward_icon.rgba16.png", 16, 16, 16), define_builtin_tex(texture_coopdx_logo, "textures/segment2/custom_coopdx_logo.rgba32.png", 2048, 1024, 32), - + // Goddard define_builtin_tex(gd_texture_hand_open, "textures/intro_raw/hand_open.rgba16.png", 32, 32, 16), define_builtin_tex(gd_texture_hand_closed, "textures/intro_raw/hand_closed.rgba16.png", 32, 32, 16), @@ -1179,7 +1179,7 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = { define_builtin_tex(gd_texture_sparkle_3, "textures/intro_raw/sparkle_3.rgba16.png", 32, 32, 16), define_builtin_tex(gd_texture_sparkle_4, "textures/intro_raw/sparkle_4.rgba16.png", 32, 32, 16), define_builtin_tex(gd_texture_sparkle_5, "textures/intro_raw/sparkle_5.rgba16.png", 32, 32, 16), - + // Version Exclusives #if defined(VERSION_JP) define_builtin_tex(texture_font_char_jp_0, "textures/segment2/segment2.07100.ia1.png", 8, 8, 16), @@ -1448,7 +1448,7 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = { define_builtin_tex(texture_font_char_eu_unknown, "textures/segment2/font_graphics.06510.ia1.png", 16, 8, 16), define_builtin_tex(texture_font_char_eu_Cedilla, "textures/segment2/font_graphics.06520.ia1.png", 16, 8, 16), define_builtin_tex(texture_font_char_eu_eszeet, "textures/segment2/font_graphics.06530.ia1.png", 16, 8, 16), - + define_builtin_tex(cake_end_texture_eu_35, "levels/ending/eu_023000.rgba16.png", 64, 32, 16), define_builtin_tex(cake_end_texture_eu_36, "levels/ending/eu_024000.rgba16.png", 64, 32, 16), define_builtin_tex(cake_end_texture_eu_37, "levels/ending/eu_025000.rgba16.png", 64, 32, 16), @@ -1614,7 +1614,7 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = { define_builtin_tex(water_skybox_texture_0003D, "textures/skybox_tiles/water.61.rgba16.png", 32, 32, 16), define_builtin_tex(water_skybox_texture_0003E, "textures/skybox_tiles/water.62.rgba16.png", 32, 32, 16), define_builtin_tex(water_skybox_texture_0003F, "textures/skybox_tiles/water.63.rgba16.png", 32, 32, 16), - + define_builtin_tex(bitfs_skybox_texture_00000, "textures/skybox_tiles/bitfs.0.rgba16.png", 32, 32, 16), define_builtin_tex(bitfs_skybox_texture_00001, "textures/skybox_tiles/bitfs.1.rgba16.png", 32, 32, 16), define_builtin_tex(bitfs_skybox_texture_00002, "textures/skybox_tiles/bitfs.2.rgba16.png", 32, 32, 16), @@ -2461,3 +2461,15 @@ const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromName(const char* aData return NULL; } + +const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromData(const Texture* aData) { + size_t count = sizeof(sDynosBuiltinTexs) / (sizeof(struct BuiltinTexInfo)); + for (size_t i = 0; i < count; i++) { + const struct BuiltinTexInfo* info = &sDynosBuiltinTexs[i]; + if (info->pointer == aData) { + return info; + } + } + + return NULL; +} diff --git a/data/dynos_mgr_tex.cpp b/data/dynos_mgr_tex.cpp index c4316c39a..5531c0710 100644 --- a/data/dynos_mgr_tex.cpp +++ b/data/dynos_mgr_tex.cpp @@ -447,24 +447,24 @@ void DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName) { } } -bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { - #define CONVERT_TEXINFO() { \ - /* translate bit size */ \ - switch (_Data->mRawSize) { \ - case G_IM_SIZ_8b: aOutTexInfo->bitSize = 8; break; \ - case G_IM_SIZ_16b: aOutTexInfo->bitSize = 16; break; \ - case G_IM_SIZ_32b: aOutTexInfo->bitSize = 32; break; \ - default: return false; \ - } \ - aOutTexInfo->width = _Data->mRawWidth; \ - aOutTexInfo->height = _Data->mRawHeight; \ - aOutTexInfo->texture = _Data->mRawData.begin(); \ - aOutTexInfo->name = aTexName; \ - } +#define CONVERT_TEXINFO(texName) { \ + /* translate bit size */ \ + switch (_Data->mRawSize) { \ + case G_IM_SIZ_8b: aOutTexInfo->bitSize = 8; break; \ + case G_IM_SIZ_16b: aOutTexInfo->bitSize = 16; break; \ + case G_IM_SIZ_32b: aOutTexInfo->bitSize = 32; break; \ + default: return false; \ + } \ + aOutTexInfo->width = _Data->mRawWidth; \ + aOutTexInfo->height = _Data->mRawHeight; \ + aOutTexInfo->texture = _Data->mRawData.begin(); \ + aOutTexInfo->name = texName; \ +} - auto& _DynosCustomTexs = DynosCustomTexs(); +bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { // check custom textures + auto& _DynosCustomTexs = DynosCustomTexs(); for (s32 i = 0; i < _DynosCustomTexs.Count(); ++i) { if (!strcmp(_DynosCustomTexs[i].first, aTexName)) { auto& _Data = _DynosCustomTexs[i].second->mData; @@ -483,7 +483,7 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { free(_RawData); } - CONVERT_TEXINFO(); + CONVERT_TEXINFO(aTexName); return true; } } @@ -494,7 +494,7 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { for (DataNode* _Node : DynosValidTextures()) { // check valid textures if (_Node->mName == aTexName) { auto& _Data = _Node->mData; - CONVERT_TEXINFO(); + CONVERT_TEXINFO(aTexName); return true; } } @@ -508,6 +508,28 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { return true; } +bool DynOS_Tex_GetFromData(const Texture *aTex, struct TextureInfo* aOutTexInfo) { + DataNode *node = DynOS_Tex_RetrieveNode((void *) aTex); + if (node) { + auto& _Data = node->mData; + CONVERT_TEXINFO(node->mName.begin()); + return true; + } + + // check builtin textures + const struct BuiltinTexInfo* info = DynOS_Builtin_Tex_GetInfoFromData(aTex); + if (info) { + aOutTexInfo->bitSize = info->bitSize; + aOutTexInfo->width = info->width; + aOutTexInfo->height = info->height; + aOutTexInfo->texture = (u8*)info->pointer; + aOutTexInfo->name = info->identifier; + return true; + } + + return false; +} + static DataNode *DynOS_Lua_Tex_RetrieveNode(const char* aName) { auto& _DynosCustomTexs = DynosCustomTexs(); for (s32 i = 0; i < _DynosCustomTexs.Count(); ++i) { diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index 7fb4b0148..3eb2397b1 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -5105,6 +5105,30 @@ Gets the current GraphNodeHeldObject
+## [get_texture_average_color](#get_texture_average_color) + +### Description +Calculates the average color of a given texture. Returns true if success + +### Lua Example +`local booleanValue = get_texture_average_color(tex, out)` + +### Parameters +| Field | Type | +| ----- | ---- | +| tex | `Pointer` <`integer`> | +| out | [Color](structs.md#Color) | + +### Returns +- `boolean` + +### C Prototype +`bool get_texture_average_color(const u8 *tex, OUT Color out);` + +[:arrow_up_small:](#) + +
+ --- # functions from smlua_model_utils.h diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 327b08d98..8a6b829dd 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1990,6 +1990,7 @@ - [geo_get_current_perspective](functions-6.md#geo_get_current_perspective) - [geo_get_current_camera](functions-6.md#geo_get_current_camera) - [geo_get_current_held_object](functions-6.md#geo_get_current_held_object) + - [get_texture_average_color](functions-6.md#get_texture_average_color)
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 0ed003edf..5a248bf3c 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -33075,6 +33075,29 @@ int smlua_func_geo_get_current_held_object(UNUSED lua_State* L) { return 1; } +int smlua_func_get_texture_average_color(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_texture_average_color", 2, top); + return 0; + } + + u8 * tex = (u8 *)smlua_to_cpointer(L, 1, LVT_U8_P); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_texture_average_color"); return 0; } + + Color out; + smlua_get_color(out, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "get_texture_average_color"); return 0; } + + lua_pushboolean(L, get_texture_average_color(tex, out)); + + smlua_push_color(out, 2); + + return 1; +} + ///////////////////////// // smlua_model_utils.h // ///////////////////////// @@ -36957,6 +36980,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "geo_get_current_perspective", smlua_func_geo_get_current_perspective); smlua_bind_function(L, "geo_get_current_camera", smlua_func_geo_get_current_camera); smlua_bind_function(L, "geo_get_current_held_object", smlua_func_geo_get_current_held_object); + smlua_bind_function(L, "get_texture_average_color", smlua_func_get_texture_average_color); // smlua_model_utils.h smlua_bind_function(L, "smlua_model_util_get_id", smlua_func_smlua_model_util_get_id); diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c index b3f2d4452..d9b11800e 100644 --- a/src/pc/lua/utils/smlua_misc_utils.c +++ b/src/pc/lua/utils/smlua_misc_utils.c @@ -584,4 +584,26 @@ struct GraphNodeCamera* geo_get_current_camera(void) { struct GraphNodeHeldObject* geo_get_current_held_object(void) { return gCurGraphNodeHeldObject; -} \ No newline at end of file +} + +bool get_texture_average_color(const u8 *tex, OUT Color out) { + struct TextureInfo texInfo; + if (!tex) { return false; } + if (!dynos_texture_get_from_data(tex, &texInfo)) { return false; } + u32 w = texInfo.width; + u32 h = texInfo.height; + u32 texSize = w * h; + const u8 *data = texInfo.texture; + u32 r = 0; + u32 g = 0; + u32 b = 0; + for (u32 i = 0; i < texSize; i++) { + r += data[4 * i + 0]; + g += data[4 * i + 1]; + b += data[4 * i + 2]; + } + out[0] = r / texSize; + out[1] = g / texSize; + out[2] = b / texSize; + return true; +} diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h index c7e3d0712..4224ba73d 100644 --- a/src/pc/lua/utils/smlua_misc_utils.h +++ b/src/pc/lua/utils/smlua_misc_utils.h @@ -231,4 +231,7 @@ struct GraphNodeCamera* geo_get_current_camera(void); /* |description|Gets the current GraphNodeHeldObject|descriptionEnd|*/ struct GraphNodeHeldObject* geo_get_current_held_object(void); +/* |description|Calculates the average color of a given texture. Returns true if success|descriptionEnd|*/ +bool get_texture_average_color(const u8 *tex, OUT Color out); + #endif