# Live2D Character Integration Plan > Goal: DansoriEQ에 AI 반응형 Live2D 캐릭터를 탑재한다. 최종 형태는 Equalizer APO + AI EQ 워크플로우에 맞춰 캐릭터가 상태, 감정, 말풍선, 모션으로 반응하는 WPF 앱이다. ## 0. Important Context - 사용자는 Live2D, 디자인, 캐릭터 제작 지식이 없다고 전제한다. - 캐릭터 이미지, 레이어 분리, 표정/포즈 요청서, 검수 문서는 모두 ChatGPT를 통해 만든다. - 사람 디자이너 없이 진행하므로, 제작물은 “상업 품질 완성본”보다 “앱에 실제 탑재 가능한 반복 개선형 자산”을 우선한다. - 코드 적용은 DansoriEQ 앱에서 진행한다. - 제작 원본은 `D:\Work_AI\Dansori\Characters_Build_Docs`에 보관한다. - 앱 탑재본은 `D:\Work_AI\Dansori\DansoriEQ\src\DansoriEQ.App\Assets\Characters`에 복사해 사용한다. ## 1. Current Prepared Assets ### DansoriEQ App - .NET 8 WPF 앱 구조가 있다. - 기존 캐릭터/애니메이션 진입점이 있다. - `src/DansoriEQ.App/Controls/MascotAvatar.xaml` - `src/DansoriEQ.App/Controls/MascotToast.xaml` - `src/DansoriEQ.App/Controls/LottieView.cs` - `src/DansoriEQ.App/Controls/SoundwaveRings.xaml` - `src/DansoriEQ.App/Controls/EqBarsFx.xaml` - `SkiaSharp.Skottie`가 이미 포함되어 있어 Lottie FX 재생 기반이 있다. - AI EQ 흐름이 있다. - user prompt - AI provider - EQ delta parsing - EQ state apply - APO writer ### Character Build Docs Prepared Live2D source packages: - `D:\Work_AI\Dansori\Characters_Build_Docs\LeeSori_Live2D` - `D:\Work_AI\Dansori\Characters_Build_Docs\Haruka_Live2D` - `D:\Work_AI\Dansori\Characters_Build_Docs\Isabel_Live2D` - `D:\Work_AI\Dansori\Characters_Build_Docs\Noeul_Live2D` Each package currently contains: - Live2D layer PNG bundle under `03_Assets/Live2D/LayerPNGs` - `layer_manifest.json` - `LayerPNGs_README.md` - `layer_generation_report.json` - preview PNGs - Photoshop assembler JSX - Cubism/PSD workflow documentation Validation status from generation: - 78 layer PNGs generated per character. - 67 required layers non-empty per character. - No missing generated layer files. ## 2. Not Prepared Yet The following are still required before true Live2D runtime integration: - Cubism Editor import result - `.moc3` - `.model3.json` - texture atlas PNG - `.motion3.json` - `.exp3.json` - optional `.physics3.json` - WPF WebView2 Live2D host - Cubism SDK for Web runtime files - Character event bridge between WPF and JavaScript - Character state model inside DansoriEQ - AI/EQ event mapping to character reactions - Final app asset packaging structure ## 3. Recommended Runtime Architecture Use WPF + WebView2 + Cubism SDK for Web. Reason: - WPF-native Live2D integration is more complex and slower to debug. - Cubism SDK for Web is the most practical runtime for loading `.model3.json` assets. - WPF can communicate with the WebView through message passing. - This keeps Live2D rendering isolated from Equalizer APO and AI EQ logic. Proposed layers: ```text DansoriEQ WPF MainWindow / existing panels Live2DCharacterView.xaml WebView2 live2d-host/index.html live2d-host/characterHost.js Cubism SDK for Web Assets/Characters/{CharacterId}/model.model3.json ``` ## 4. Character Production Workflow Using ChatGPT Because no designer is available, every character asset task must be converted into a concrete ChatGPT task. ### 4.1 Character Identity Lock For each character, maintain a short identity sheet: - name - role in DansoriEQ - personality - color palette - hairstyle - face traits - default outfit - forbidden changes - reference image path Output file per character: ```text {Character}_Live2D/01_Overview/Character_Lock.md ``` Completion criteria: - The character can be regenerated consistently enough across multiple prompts. - The app role is clear. - Visual differences between characters are obvious. ### 4.2 Source Image Generation ChatGPT image generation tasks: - neutral full-body A-pose - head expression set - alternate hand/arm poses - optional outfit variants - transparent or removable background when possible Required style constraints: - character only - no UI - no text - no logo - clean front-facing or slight 3/4 pose - high resolution - consistent face and hair - suitable for Live2D layer separation Completion criteria: - At least one A-pose source exists. - Head and body are visually consistent. - Image is suitable for part extraction. ### 4.3 AI-Assisted Layer Separation Use the existing `*_Live2D` tooling to produce coarse Live2D layer PNGs. Current layer categories: - Guide - BackHair - Body - Clothes - Head - Eyes - Brows - Mouth - FrontHair - Accessories - SwapParts Completion criteria: - `layer_generation_report.json` shows all required layers non-empty. - Preview image is visually recognizable. - Obvious empty or wrong-color masks are fixed by script fallback or prompt regeneration. ### 4.4 PSD Assembly Use `photoshop_assemble_live2d_psd.jsx` from each `*_Live2D` folder. Expected outputs: - `{character}_live2d_material_separation.psd` - `{character}_live2d_import.psd` Completion criteria: - PSD opens in Photoshop or compatible editor. - Layers are named according to `layer_manifest.json`. - Transparent background is preserved. ### 4.5 Cubism Editor Work This is the only area that may require manual GUI work unless automated later. Tasks: - Import PSD into Cubism Editor. - Create ArtMeshes. - Create deformers. - Add parameters. - Create basic expressions. - Create idle motion. - Export runtime model. Minimum viable export: ```text model.model3.json model.moc3 textures/*.png motions/idle.motion3.json expressions/*.exp3.json ``` Completion criteria: - Cubism Viewer or Web runtime can load the model. - Idle motion plays. - At least 3 expressions work: neutral, happy, thinking. ## 5. App Integration Phases ### Phase 1 - Static Compatibility Baseline Goal: Keep current DansoriEQ stable and identify where the character belongs. Tasks: - Build/test current solution. - Locate existing `MascotAvatar` usage. - Document current mascot UI surfaces. - Add no Live2D yet. Completion criteria: - App builds. - Existing mascot UI still works. - We know the exact insertion point for dynamic character UI. ### Phase 2 - WebView2 Live2D Host PoC Goal: Add a WebView2-based character host without real model dependency. Tasks: - Add WebView2 package if missing. - Create `Controls/Live2DCharacterView.xaml`. - Create `Assets/Live2DHost/index.html`. - Create `Assets/Live2DHost/characterHost.js`. - Load local host page inside WPF. - Implement basic WPF-to-JS messages. Example commands from WPF to JS: ```text setCharacter(characterId) setState(state) playMotion(group, index) setExpression(expressionId) showText(message) ``` Completion criteria: - WPF window displays the host page. - WPF can send a test message to JS. - JS can send `hostReady` back to WPF. ### Phase 3 - Placeholder Character Runtime Goal: Use generated preview PNGs before real Cubism export exists. Tasks: - Copy each character preview PNG into app assets. - Show selected character in the Live2D host placeholder. - Animate placeholder with simple CSS transforms. - Hook app events to placeholder states. Completion criteria: - The app can switch LeeSori, Haruka, Isabel, Noeul. - Idle/thinking/success/error states visibly differ. - No Cubism model required yet. ### Phase 4 - Real Cubism Model Loading Goal: Replace placeholder with actual Cubism model. Tasks: - Add Cubism SDK for Web runtime assets. - Copy one exported model into `Assets/Characters/LeeSori`. - Load `model.model3.json` in WebView2. - Play idle motion. - Trigger expression and motion from WPF. Completion criteria: - LeeSori Live2D model loads inside DansoriEQ. - Idle motion plays. - WPF can trigger at least one expression and one motion. ### Phase 5 - AI/EQ Reaction Mapping Goal: Character reacts to real app events. Events to map: - App launched - APO setup required - AI prompt started - AI response received - EQ delta parsed - EQ applied - EQ apply failed - bypass on/off - preset selected - profile not found Recommended state mapping: ```text Idle -> default breathing/idle Listening -> user is typing or prompt submitted Thinking -> AI request in progress Talking -> AI explanation shown ApplyingEq -> APO write in progress Success -> EQ applied Error -> failed operation Muted -> bypass/off Guide -> setup/help required ``` Completion criteria: - Character state changes are driven by app events, not hard-coded UI buttons. - AI response text can appear in `MascotToast` or Live2D host overlay. - Failure states are visible and useful. ### Phase 6 - Multi-Character System Goal: Let users choose a character. Tasks: - Add character registry JSON. - Add app setting for selected character. - Add Settings UI character selector. - Add per-character personality text for AI explanations. Example registry: ```json { "characters": [ { "id": "leesori", "name": "LeeSori", "model": "Assets/Characters/LeeSori/model.model3.json" }, { "id": "haruka", "name": "Haruka", "model": "Assets/Characters/Haruka/model.model3.json" }, { "id": "isabel", "name": "Isabel", "model": "Assets/Characters/Isabel/model.model3.json" }, { "id": "noeul", "name": "Noeul", "model": "Assets/Characters/Noeul/model.model3.json" } ] } ``` Completion criteria: - User can select a character. - Selection persists between app launches. - Character-specific assets load correctly. ### Phase 7 - Polish and Release Readiness Goal: Make the feature shippable. Tasks: - Add fallback if Live2D fails to load. - Add performance setting: off/static/live. - Add reduced motion option. - Ensure local files load in packaged app. - Validate release build. - Add documentation. Completion criteria: - App works without Live2D assets. - App does not crash if WebView2 or model loading fails. - Character feature can be disabled. - Release build includes required assets. ## 6. Immediate Next Step Start with Phase 1 and Phase 2. Recommended next implementation task: 1. Build current DansoriEQ solution. 2. Add WebView2 dependency if missing. 3. Add `Live2DCharacterView` placeholder control. 4. Add local `Live2DHost` HTML/JS. 5. Display the host in a non-invasive area of the existing UI. 6. Verify WPF-to-JS and JS-to-WPF message bridge. This can be done before real Cubism models exist. ## 7. Working Rule for Future Sessions At the start of any future session, read this file first: ```text D:\Work_AI\Dansori\DansoriEQ\docs\LIVE2D_CHARACTER_INTEGRATION_PLAN.md ``` Then check: ```text D:\Work_AI\Dansori\Characters_Build_Docs D:\Work_AI\Dansori\DansoriEQ ``` Do not assume the user can manually create character art. Convert every character-art need into a ChatGPT/image-generation task or a scriptable asset-processing task. ## 8. Progress Log ### 2026-07-03 - Phase 1, Phase 2, Phase 3 Placeholder Started Completed: - Baseline `dotnet build .\DansoriEQ.sln` passed with 0 warnings and 0 errors. - Added `Microsoft.Web.WebView2` package to `DansoriEQ.App`. - Added WPF control: - `src/DansoriEQ.App/Controls/Live2DCharacterView.xaml` - `src/DansoriEQ.App/Controls/Live2DCharacterView.xaml.cs` - Added local WebView host: - `src/DansoriEQ.App/Assets/Live2DHost/index.html` - `src/DansoriEQ.App/Assets/Live2DHost/style.css` - `src/DansoriEQ.App/Assets/Live2DHost/characterHost.js` - `src/DansoriEQ.App/Assets/Live2DHost/characters.json` - Copied generated preview images into app assets: - `src/DansoriEQ.App/Assets/Characters/Live2DPreview/leesori.png` - `src/DansoriEQ.App/Assets/Characters/Live2DPreview/haruka.png` - `src/DansoriEQ.App/Assets/Characters/Live2DPreview/isabel.png` - `src/DansoriEQ.App/Assets/Characters/Live2DPreview/noeul.png` - Updated project file so Live2D host files and preview PNGs are copied to output. - Placed `Live2DCharacterView` in the main graph/character area. - Added temporary character selector ComboBox with LeeSori, Haruka, Isabel, Noeul. - Wired AI state messages: - idle on load - thinking on AI request - success on EQ apply - error on exception - Fixed existing parser test expectation: `LSC` maps to `FilterType.LowShelfSlope`. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Output folder contains Live2D host files and all 4 preview PNG files. - `characters.json` preview paths resolve to existing files in the debug output folder. Next recommended task: - Run the WPF app visually and confirm that the WebView2 placeholder appears in the graph area. - If placement is acceptable, replace the temporary selector with a proper Settings character selector. - Then prepare one real Cubism export, starting with LeeSori. ### 2026-07-03 - LeeSori Placeholder Visual Correction Finding: - The generated `sori_live2d_layer_preview.png` is useful as a layer-composition audit image, but it is not suitable as the app-facing placeholder. - Its face, eyes, mouth, and headphone proportions are visibly distorted because some facial/accessory layers are procedurally regenerated for Live2D separation. - The app-facing placeholder should use polished character art until a real Cubism export exists. Changed: - Replaced `src/DansoriEQ.App/Assets/Characters/Live2DPreview/leesori.png` with the existing polished `sori_idle.png` artwork. - Reduced WebView host placeholder overscaling: - `right: -18%` -> `right: -6%` - `bottom: -14%` -> `bottom: -6%` - `width/height: 118%` -> `104%` Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. Rule going forward: - Use Live2D generated previews for production QA only. - Use polished character PNGs for in-app placeholders. - Replace placeholders with real Cubism runtime models only after Cubism export quality is acceptable. ### 2026-07-03 - LeeSori Source Artwork Rework User feedback: - Character proportion is acceptable. - The black WebView character area should be taller so its vertical span matches the EQ graph more closely. - LeeSori still has a distracting white outline around the hair; this is not just missing alpha transparency. Finding: - Deterministic alpha cleanup reduced some edge matte, but the large white/pink/gray outline was baked into the source artwork as glow/highlight, especially around the hair/headphones. - Continuing to erase pixels from the existing PNG damages the intended hair/headphone shape before it fully removes the outline. - The app currently displays only `Assets/Characters/Live2DPreview/leesori.png`, not the full set of `sori_*` expression PNGs. Changed: - Increased the WPF `Live2DCharacterView` height to better match the EQ graph area. - Created non-destructive source candidates under: - `src/DansoriEQ.App/Assets/Characters/SourceCandidates/` - Generated a new ChatGPT/imagegen LeeSori candidate with the same face, outfit, pose, teal hair, and headphones, but without the original white halo/sticker-style outer glow. - Removed the generated magenta chroma-key background into real PNG alpha. - Replaced the app-facing LeeSori files with the clean candidate: - `src/DansoriEQ.App/Assets/Characters/sori_idle.png` - `src/DansoriEQ.App/Assets/Characters/Live2DPreview/leesori.png` Preserved: - Original app character PNGs remain backed up in: - `src/DansoriEQ.App/Assets/Characters_OriginalBackup/` - Generated candidates remain available for visual comparison in: - `src/DansoriEQ.App/Assets/Characters/SourceCandidates/` Next validation: - Rebuild the app and run it visually. - If LeeSori now looks acceptable, generate matching clean variants for `sori_avatar_*` and `sori_happy` only when those states become visible in-app. - If the remaining right-sleeve bright line is still distracting, create one more imagegen pass specifically targeting sleeve/jacket edge highlights. ### 2026-07-03 - WebView Character Motion Layer Changed: - Extended the WebView character host to track `currentState` independently from the selected character. - Added state image lookup through `characters.json` using an optional `states` map. - Added LeeSori state map placeholders for: - `idle` - `thinking` - `success` - `error` - Kept all LeeSori states mapped to the cleaned app-facing PNG for now, so the improved no-halo artwork remains consistent. - Added state-specific motion in CSS: - idle breathing/float - thinking faster bob plus accent glow - success upward bounce - error short shake, then return to idle - Added temporary message timeout in the WebView host so AI status text returns to the character/state label after a few seconds. Validation: - `node --check src/DansoriEQ.App/Assets/Live2DHost/characterHost.js`: passed. - `characters.json` parses successfully with PowerShell `ConvertFrom-Json`. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. Next recommended task: - Run the WPF app and verify the right-side character now feels alive during idle, AI request, success, and error states. - If the motion direction is acceptable, create clean expression variants for LeeSori and map them into `states`. - After expression variants are stable, move from PNG placeholder animation to real Cubism model export/runtime integration. ### 2026-07-04 - LeeSori Layered Puppet Prototype User feedback: - The character moved, but it was still a single whole image moving with neon effects. - Desired direction is separate part movement, not whole-image motion. Changed: - Copied LeeSori legacy full-canvas puppet parts into the app: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSori/Images/` - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSori/rig.json` - Updated `DansoriEQ.App.csproj` so Puppet PNG/JSON files are copied to the build output as Content. - Replaced the WebView host's LeeSori rendering path with a layered puppet renderer: - fetches `rig.json` - creates one DOM image layer per bone/part - stacks parts by rig `z` - applies each part's pivot as CSS `transform-origin` - Removed the previous visible neon/glow elements from the host markup. - Added separate CSS animations for part groups: - head/neck - chest/body breathing - pelvis - left/right arms and hands - legs - state-specific thinking/success/error motion - Kept the clean single PNG preview as fallback if the puppet fails to load. Known limitation: - This uses the existing A-pose/full-body legacy puppet parts, so visual quality and framing may differ from the cleaned app-facing LeeSori portrait. - This step is for validating part-based motion in the actual WPF/WebView pipeline. - If accepted, the next art task is to generate a clean upper-body puppet part set from the approved LeeSori image style. Validation: - `node --check src/DansoriEQ.App/Assets/Live2DHost/characterHost.js`: passed. - `characters.json` parses successfully. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output contains `rig.json` and 17 LeeSori puppet PNG parts. Next recommended task: - Run the WPF app and verify that LeeSori parts now move independently. - If part motion is technically acceptable, regenerate a clean upper-body part set matching the improved no-outline LeeSori art and replace this legacy A-pose puppet set. ### 2026-07-04 - Puppet Load Fix and Rebuild User feedback: - The app still looked almost the same, suggesting the previous build either was not picked up or the layered puppet did not actually load. Finding: - The build output contained the puppet files, but the WebView was opened through a local `file://` URL. - That path can make JavaScript `fetch()` for `rig.json` unreliable inside WebView2, causing the host to fall back to the single clean PNG preview. Changed: - Updated `Live2DCharacterView.xaml.cs` to expose the app `Assets` folder through WebView2 `SetVirtualHostNameToFolderMapping`. - The host now loads from: - `https://dansori-assets.local/Live2DHost/index.html?v=...` - This keeps `characters.json`, `rig.json`, and puppet PNG files under one stable virtual origin. - Added a cache-busting query string to the host URL so rebuilt HTML/JS/CSS is not silently reused. - Increased puppet part animation amplitude so the difference between fallback PNG motion and real part motion is visibly obvious during validation. - Ran `dotnet clean` before rebuilding to remove stale output files. Validation: - `dotnet clean .\DansoriEQ.sln`: passed. - `node --check src/DansoriEQ.App/Assets/Live2DHost/characterHost.js`: passed. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Output `style.css` contains the stronger puppet animation values. - Output `characterHost.js` contains `loadPuppet()`, `fetch(active.puppet.rig)`, and `has-puppet` activation. Next validation: - Run the rebuilt app from the current Debug output. - If LeeSori appears as a smaller full-body A-pose and her head/arms move separately, the puppet pipeline is working. - If the clean portrait still appears instead, inspect WebView2 runtime console/errors next. ### 2026-07-04 - Replace Legacy A-Pose Puppet With Approved-Ratio Upper Puppet User feedback: - The layered puppet pipeline is now visible: elbows/parts move independently even in idle. - However, the legacy A-pose puppet has wrong head/body/headphone proportions. Finding: - The previous `LeeSori` puppet was only useful as a technical proof that separate parts can move in the WPF/WebView pipeline. - Its source art does not match the approved clean LeeSori portrait. Changed: - Created a new `LeeSoriUpper` puppet set from the approved clean `sori_idle.png` portrait so face, body, and headphone proportions are preserved. - Generated full-canvas overlap-based parts under: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriUpper/Images/` - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriUpper/rig.json` - QA composite saved at: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriUpper/qa_composite_black.png` - Switched `characters.json` from the legacy `LeeSori` puppet to the new `LeeSoriUpper` puppet. - Reduced motion amplitude after the previous debug pass because the new overlap-based puppet should move subtly to avoid ghosting. Design tradeoff: - This is not final Cubism-grade part separation. It is an overlap puppet sliced from the approved portrait. - The benefit is exact approved visual proportions. - The cost is that large movements can reveal duplicated underlying art, so animation must stay subtle until a proper AI-generated or Cubism-authored layered source exists. Validation: - `node --check src/DansoriEQ.App/Assets/Live2DHost/characterHost.js`: passed. - `characters.json` parses and points LeeSori to `LeeSoriUpper`. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output `characters.json` also points to `LeeSoriUpper`. Next validation: - Run the WPF app and confirm proportions now match the approved LeeSori portrait. - If motion is still acceptable, next task is to improve true part separation quality by generating clean hidden-underlay patches for head/arm gaps or moving toward proper Cubism source layers. ### 2026-07-04 - LeeSori Framing Adjustment User feedback: - The new LeeSoriUpper puppet looks natural and proportions match. - The character display has too much top empty space, so LeeSori should sit higher and show more lower body. Changed: - Adjusted WebView character framing in `style.css`: - `right: -6%` -> `right: -8%` - `bottom: -5%` -> `bottom: 4%` - `width/height: 104%` -> `112%` - This raises LeeSori within the black display area and slightly enlarges her so more lower body is visible while reducing top dead space. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the new framing values. ### 2026-07-04 - Stronger LeeSoriUpper Framing Fix User feedback: - The previous framing change was not visually noticeable. - Top whitespace remained large and the hand still appeared clipped. Finding: - The shared `#preview, #puppet` rule changed `height`, but `#puppet` had its own `height: auto`, so the visible puppet size was still mostly controlled by width. - The LeeSoriUpper canvas aspect is `1086 / 1448`, not the old legacy `520 / 900`, so the puppet needed its own aspect-ratio and larger width. Changed: - Added puppet-specific framing: - `right: -30%` - `bottom: -2%` - `width: 160%` - `aspect-ratio: 1086 / 1448` - This makes the puppet fill the vertical character area much more strongly, reducing top dead space and making lower body/hand position changes visible. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the new puppet-specific framing values. ### 2026-07-04 - Character Column Width Adjustment User feedback: - The previous CSS-only framing made the character image feel enlarged. - The character display area still felt too narrow, causing the right elbow and left wrist/hand area to be clipped. - Better direction: reduce the EQ graph width and increase the character display width. Changed: - WPF layout: - `Live2DCharacterView` width: `250` -> `350` - graph right margin: `270` -> `370` - character right margin: `6` -> `0` - WebView puppet framing: - reduced puppet over-scaling from `160%` to `116%` - set puppet `bottom` to `0%` - kept a mild `right: -8%` offset Reasoning: - The prior problem was available character-column width, not the sprite size itself. - Enlarging the sprite inside a narrow column caused clipping. - The new layout gives the character more real horizontal room while keeping its proportions natural. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the updated puppet framing values. ### 2026-07-04 - FHD Window and No-Clip Character Fit User feedback: - Character column width fixed side clipping, but the top of the head and left hand were still clipped. - Suggested increasing the app window size within FHD constraints and slightly reducing character scale. Changed: - Main window size: - `1600x980` -> `1700x1020` - minimum size: `1360x820` -> `1460x900` - Graph/character zone: - `MinHeight: 545` -> `600` - `Live2DCharacterView: 350x545` -> `390x600` - graph right margin: `370` -> `410` - EQ graph height: `480` -> `520` - WebView puppet framing: - `width: 116%` -> `108%` - `right: -8%` -> `-4%` - `bottom: 0%` -> `3%` Reasoning: - The character needed more real vertical and horizontal display area, not more internal sprite scaling. - The new window size remains appropriate for FHD while giving the character enough room to avoid top/head and hand clipping. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the new no-clip puppet framing values. ### 2026-07-04 - Hide Character Status Bubble and Reduce Motion Clipping User feedback: - Need to hide the `LeeSori - idle` status box to determine whether the wrist is covered or actually clipped. - Character should be slightly smaller because animation can still clip top/bottom edges. Changed: - Hid the WebView status bubble with `display: none` on `#bubble`. - Reduced LeeSoriUpper puppet scale: - `width: 108%` -> `100%` - `right: -4%` -> `0%` - kept `bottom: 4%` - Reduced vertical animation travel so motion is less likely to clip at the top/bottom. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the hidden bubble and reduced puppet framing values. ### 2026-07-04 - Remove Reserved Bubble Area From Character Stage User feedback: - Hiding the `LeeSori - idle` bubble did not change the wrist/hand clipping point. - This suggested the former bubble area was not part of the active character display area. Finding: - `#character` still used `inset: 0 0 30px 0`, reserving 30px at the bottom for the bubble even after the bubble was hidden. - Therefore the puppet could not use the bottom area where the bubble used to sit. Changed: - Changed `#character` from `inset: 0 0 30px 0` to `inset: 0`. - Adjusted puppet/fallback bottom placement from `4%` to `2%` so the character can use more vertical space without floating too high. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains `#character { inset: 0; }` and updated `bottom: 2%` values. ### 2026-07-04 - Direct Framing QA and Applied Candidate User request: - Directly inspect and choose a better ratio/position because the left wrist still appears clipped. Finding: - A local 390x600 viewport composite showed the WebView was no longer clipping the bottom after removing the reserved bubble area. - The remaining wrist cutoff is mostly from the approved source portrait itself ending near that wrist/lower sleeve area. - However, the previous framing still had too much top dead space. QA artifact: - Current render QA: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriUpper/qa_view_390x600_current.png` - Applied candidate QA: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriUpper/qa_view_390x600_candidate_96_bottom12.png` Changed: - Applied the directly inspected candidate framing: - `right: 2%` - `bottom: 12%` - `width: 96%` - This slightly reduces the character scale and raises her in the viewport, leaving animation headroom while reducing top whitespace. Note: - To fully reveal a hand/wrist that is cut off in the source artwork, the next step would be source image extension/outpainting or a cleaner lower-arm/hand part, not just CSS framing. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output CSS contains the applied candidate values. ### 2026-07-04 - Startup EQ Disabled and Extended LeeSori Puppet User request: - Program should start with EQ inactive/disabled. - Continue image extension or part rewrite so wrist and lower body are not clipped and look natural. Changed - EQ startup: - Changed `ActiveToggle` default from checked to unchecked: - `IsChecked="True"` -> `IsChecked="False"` - Changed internal bypass default: - `_bypassed` now starts as `true`. - Startup `ApplyEqToApo()` therefore writes only bypass/volume preamp instead of applying active EQ filters. Changed - character art: - Generated a new AI-extended LeeSori source with full lower body, complete visible wrist/hand, shoes, and natural continuation of pants/jacket. - Removed magenta chroma-key background to real PNG alpha. - Saved source and QA artifacts under: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriExtended/` - Created a new full-body overlap puppet: - `leesori_ext_base` - `leesori_ext_legs` - `leesori_ext_chest` - `leesori_ext_arm_l/r` - `leesori_ext_hand_l/r` - `leesori_ext_head` - Switched `characters.json` from `LeeSoriUpper` to `LeeSoriExtended`. - Applied safe full-body framing: - `right: 10%` - `bottom: 1%` - `width: 80%` QA artifacts: - `qa_extended_black.png`: full alpha result on black background. - `qa_view_390x600_fullbody.png`: initial 390x600 viewport check. - `qa_view_390x600_fullbody_safe.png`: selected safe framing with no hand/head/lower-body clipping. Tradeoff: - The extended candidate solves wrist/lower-body clipping and gives a complete natural full body. - Its face/headphone details are close but not pixel-identical to the previously approved upper portrait. If exact identity match becomes more important than full-body completeness, the next step is a targeted imagegen pass or manual hybrid compositing: approved upper portrait + generated lower-body/hand extension. Validation: - `node --check src/DansoriEQ.App/Assets/Live2DHost/characterHost.js`: passed. - `characters.json` parses and points LeeSori to `LeeSoriExtended`. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output contains `LeeSoriExtended` rig and safe framing CSS values. ### 2026-07-04 - New Sheet LeeSoriV2 Conversion User correction: - The previous LeeSoriExtended puppet solved clipping but used the old LeeSori design. - The authoritative new design sheet is: - `Characters_Build_Docs/LeeSori_Profile/03_Assets/Reference/sori_sheet.png` Changed: - Created `LeeSoriV2` from the new sheet's front full-body pose without AI identity drift. - Extracted alpha-clean source and overlap puppet parts: - base, legs, chest, left/right arms, left/right hands, head. - Replaced the app preview image with the new sheet-based LeeSori. - Switched `characters.json` to: - `../Characters/Puppets/LeeSoriV2/rig.json` - `../Characters/Puppets/LeeSoriV2/Images/` - Updated WebView framing for the new tall sheet ratio: - `right: 17.5%` - `bottom: -20%` - `width: 65%` - Framing goal: upper-body biased view for idle/work states while keeping head and both hands visible. Full body remains available in the source/rig for later state-specific framing. QA artifacts: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriV2/qa_source_black.png` - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriV2/qa_view_390x600_upper_bias.png` - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriV2/qa_view_390x600_css_selected.png` Next: - Build and run in WPF to verify real WebView framing. - If this sheet-based puppet is accepted, add state-specific animation tuning and then generate Haruka/Isabel/Noeul with the same source-first process. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output contains `LeeSoriV2` rig/images and selected CSS framing values. ### 2026-07-04 - LeeSoriV2 Knee-Up Framing and Lower-Body Outline Fix User request: - Frame LeeSori from around the midpoint between above-knee and left-hand tip up to the top of the head. - Fix the doubled green outline around both legs that appeared while the lower body moved. Changed: - Updated WebView puppet framing: - `right: 6.5%` - `bottom: -65%` - `width: 87%` - Removed the animated `legs` bone from `LeeSoriV2/rig.json`. - The lower body now remains only in the base image, so the green pants side line no longer alternates between one and two outlines. QA artifact: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriV2/qa_view_390x600_knee_upper.png` ### 2026-07-04 - LeeSoriV2 Outline/Left-Hand Cleanup User feedback: - The knee-up framing is correct. - The green pants side line still alternates between one and two outlines. - The left hand looks slightly awkward. Changed: - Regenerated `LeeSoriV2` puppet parts with tighter moving masks. - Removed animated `upperarm_l` and `hand_l` bones; the pocketed left hand now stays in the base image. - Kept the lower body only in the base image. - Kept right-side hand/arm and head/chest motion for visible idle movement. - Retained the accepted framing values: - `right: 6.5%` - `bottom: -65%` - `width: 87%` QA artifact: - `src/DansoriEQ.App/Assets/Characters/Puppets/LeeSoriV2/qa_view_390x600_v3_clean_outline.png` Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output rig no longer references `legs`, `upperarm_l`, or `hand_l` animated bones. ### 2026-07-04 - LeeSoriV2 Cache-Busted V3 Puppet Assets Problem: - Even after removing animated lower/left-side bones, WebView2 could still show stale image assets because puppet image URLs reused the same PNG filenames. Changed: - Regenerated active LeeSoriV2 images with `leesori_v2_v3_*` filenames. - Updated `characterHost.js` to append `?v=` to each puppet image URL. - Kept accepted framing unchanged: `right: 6.5%`, `bottom: -65%`, `width: 87%`. Validation: - `node --check Assets/Live2DHost/characterHost.js`: passed. - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. - Build output rig references only `leesori_v2_v3_*` active images and no longer references `legs`, `upperarm_l`, or `hand_l` bones. ### 2026-07-04 - LeeSoriV2 Reduced Breathing Transform Changed: - Removed `scaleY` from `chestBreath` and `chestThinking` to avoid waist/pants boundary shimmer. - Reduced `armRightIdle` rotation from `-1.2/0.8deg` to `-0.6/0.4deg`. - Kept accepted framing unchanged. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests. ### 2026-07-04 - LeeSoriV2 Waist Naturalization User request: - The LeeSori waist was too excessively narrow. Modify only that area to look natural. Changed: - Backed up the prior source as `LeeSoriV2/leesori_v2_source_pre_waist_fix.png`. - Used an AI edit candidate only as a local waist-patch source, not as a full replacement, to preserve LeeSori identity and pose. - Composited only the abdomen/waistband region into `leesori_v2_source.png`. - Regenerated active `leesori_v2_v3_*` puppet parts and preview from the patched source. - Kept accepted framing and rig bone policy unchanged. QA artifacts: - `LeeSoriV2/qa_source_waist_patch_black.png`. - `LeeSoriV2/qa_view_390x600_v3_clean_outline.png`. Validation: - `dotnet build .\DansoriEQ.sln`: passed, 0 warnings, 0 errors. - `dotnet test .\DansoriEQ.sln --no-build`: passed, 15/15 tests.