1091 lines
38 KiB
Markdown
1091 lines
38 KiB
Markdown
# 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.
|
|
|