From bee428ae0c15de99dd9b670e2cde2bb4d0222293 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 4 Jun 2026 12:02:48 -0400 Subject: [PATCH] fix: outfit texture swap via internalModel.textures array model.internalModel.coreModel.setTexture() expects a raw WebGL texture, not a PixiJS Texture. Instead, set the new PixiJS Texture directly on the model's internalModel.textures[2] array. The render loop's bindTexture() call extracts the WebGL handle from the PixiJS BaseTexture and passes it to the Cubism core. This eliminates the cascade of try-catch fallbacks and the 'coreModel.setTexture is not a function' TypeError. --- frontend/src/components/KiraAvatar.tsx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/KiraAvatar.tsx b/frontend/src/components/KiraAvatar.tsx index faf3e41..be2e9e3 100644 --- a/frontend/src/components/KiraAvatar.tsx +++ b/frontend/src/components/KiraAvatar.tsx @@ -169,19 +169,14 @@ export default function KiraAvatar(props: Props) { (async () => { try { - const { Assets, Texture } = await import('pixi.js'); + const { Assets } = await import('pixi.js'); const tex = await Assets.load(outfitUrl); - // Swap texture slot 2 (clothing layer) - if ((model as any).setTexture) { - (model as any).setTexture(2, tex); + // Swap texture slot 2 (clothing layer) in the model's texture array. + // The render loop automatically binds WebGL textures from PixiJS textures. + if ((model as any).internalModel?.textures) { + (model as any).internalModel.textures[2] = tex; } else { - // Fallback: try internal model - try { - (model.internalModel as any).setTexture(2, tex); - } catch { - // Fallback: direct core model - (model.internalModel.coreModel as any).setTexture(2, tex); - } + console.warn('[Outfit] cannot swap — no textures array'); } } catch (e) { console.warn('[Outfit] texture swap failed:', e);