Files
Dansori_EQ/docs/LIVE2D_CHARACTER_INTEGRATION_PLAN.md
T
2026-07-04 10:34:46 +09:00

38 KiB

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

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:

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:

{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:

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:

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:

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:

{
  "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:

D:\Work_AI\Dansori\DansoriEQ\docs\LIVE2D_CHARACTER_INTEGRATION_PLAN.md

Then check:

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.