From bc929cbb467c218d29e9cdb9f6ef17e987140f69 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 30 Oct 2025 23:06:47 -0500 Subject: [PATCH] feat(component): implement CCharacterComponent::ItemsLoaded --- src/component/CCharacterComponent.cpp | 72 +++++++++++++++++++++++++++ src/component/CCharacterComponent.hpp | 1 + 2 files changed, 73 insertions(+) diff --git a/src/component/CCharacterComponent.cpp b/src/component/CCharacterComponent.cpp index e9e1f3d..7927b60 100644 --- a/src/component/CCharacterComponent.cpp +++ b/src/component/CCharacterComponent.cpp @@ -37,6 +37,23 @@ CompSectionInfo CCharacterComponent::s_sectionInfoRaw[] = { { 0, 384, 256, 128 }, // SECTION_HEAD_LOWER }; +const char* s_componentSections[] = { + "ArmUpperTexture", + "ArmLowerTexture", + "HandTexture", + "TorsoUpperTexture", + "TorsoLowerTexture", + "LegUpperTexture", + "LegLowerTexture", + "FootTexture" +}; + +const char* s_fileDecorations[] = { + "M", + "F", + "U" +}; + /** * Texture priorities for each item slot and component section. Determines order for pasting * textures in RenderPrep functions. Priority start and end for leg component sections is @@ -75,6 +92,8 @@ int32_t s_bInRenderPrep = 0; uint32_t* s_componentHeap; char* s_pathEnd; char s_path[STORM_MAX_PATH]; +char* s_pathEnd2; +char s_path2[STORM_MAX_PATH]; CStatus s_status; #define TEXTURE_INDEX(section, texture) (3 * section + texture) @@ -118,6 +137,7 @@ void CCharacterComponent::Initialize(EGxTexFormat textureFormat, uint32_t textur } s_pathEnd = s_path; + s_pathEnd2 = s_path2; CCharacterComponent::s_prepFunc[SECTION_ARM_UPPER] = &CCharacterComponent::RenderPrepAU; CCharacterComponent::s_prepFunc[SECTION_ARM_LOWER] = &CCharacterComponent::RenderPrepAL; @@ -613,6 +633,24 @@ void CCharacterComponent::CreateBaseTexture() { this->m_data.model->ReplaceTexture(1, this->m_baseTexture); } +void* CCharacterComponent::CreateTexture(const ItemDisplayInfoRec* displayRec, int32_t section) { + SStrPrintf( + s_path, + STORM_MAX_PATH, + "Item\\TextureComponents\\%s\\%s_%s.blp", + s_componentSections[section], + displayRec->m_texture[section], + s_fileDecorations[2] + ); + + // Substitute gender suffix + if (!SFile::FileExists(s_path)) { + s_path[SStrLen(s_path) - 5] = *s_fileDecorations[this->m_data.sexID]; + } + + return TextureCacheCreateTexture(s_path); +} + void CCharacterComponent::GeosRenderPrep() { // Check for eye glow @@ -681,6 +719,40 @@ int32_t CCharacterComponent::Init(ComponentData* data, const char* a3) { } int32_t CCharacterComponent::ItemsLoaded(int32_t a2) { + if (a2) { + TCTEXTUREINFO info; + + for (int32_t section = 0; section < NUM_COMPONENT_SECTIONS; section++) { + if (!(this->m_sectionDirty & (1 << section))) { + continue; + } + + auto& itemDisplay = this->m_itemDisplays[section]; + + for (int32_t priority = 0; priority < 7; priority++) { + if (!itemDisplay.displayID[priority] && !itemDisplay.texture[priority]) { + continue; + } + + if (itemDisplay.displayID[priority] && !itemDisplay.texture[priority]) { + auto displayRec = g_itemDisplayInfoDB.GetRecord(itemDisplay.displayID[priority]); + itemDisplay.texture[priority] = this->CreateTexture(displayRec, section); + } + + // Trigger texture load + TextureCacheGetInfo(itemDisplay.texture[priority], info, 1); + + if (TextureCacheHasMips(itemDisplay.texture[priority])) { + itemDisplay.priorityDirty |= (1 << priority); + } else { + itemDisplay.priorityDirty &= ~(1 << priority); + } + } + } + + return 1; + } + // TODO return 1; diff --git a/src/component/CCharacterComponent.hpp b/src/component/CCharacterComponent.hpp index 04a5738..5013a62 100644 --- a/src/component/CCharacterComponent.hpp +++ b/src/component/CCharacterComponent.hpp @@ -80,6 +80,7 @@ class CCharacterComponent { void AddItemBySlot(INVENTORY_SLOTS invSlot, int32_t displayID, int32_t a4); void ClearItemDisplay(COMPONENT_SECTIONS section, int32_t priority); void CreateBaseTexture(); + void* CreateTexture(const ItemDisplayInfoRec* displayRec, int32_t section); void GeosRenderPrep(); CharSectionsRec* GetSectionsRecord(COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex, int32_t colorIndex, bool* found); int32_t Init(ComponentData* data, const char* a3);