feat(pngtuber): Implement PNGtuber feature#890
feat(pngtuber): Implement PNGtuber feature#890ozekimasaki wants to merge 17 commits intomoeru-ai:mainfrom
Conversation
…onstants - Move animation constants (BLINK_*, MOUTH_PAC_*, CANVAS_RESOLUTION_*) before their usage - Replace magic numbers with named constants for better maintainability - Add ResizeObserver for dynamic canvas resizing - Improve canvas resize handling with size validation
…error handling - Extract common canvas creation logic into createPreviewCanvas utility - Extract common cropping and padding logic into cropAndPadPreview utility - Standardize error messages across preview generation functions - Replace magic numbers with named constants (PREVIEW_*, LIVE2D_*, VRM_*) - Improve type safety with clearer return types and null checks - Add logic to regenerate missing PNGtuber previews from IndexedDB
- Remove console.log statements from model selector dialog - Remove console.log statements from PNGtuber ZIP loader - Clean up development-only debugging code
- Add pngtuber-scene-class prop to ModelSettings component - Ensure PNGtuberScene renders correctly in model settings view
Summary of ChangesHello @ozekimasaki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! このプルリクエストは、アプリケーションにPNGtuber機能を追加することを目的としています。これにより、ユーザーは2D PNG画像ベースのアバターをロードし、リップシンク、自動まばたき、感情表現などの動的なアニメーションをステージ上で表示できるようになります。この機能は、既存のモデル選択および設定システムにシームレスに統合され、パフォーマンスと安定性も向上しています。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request successfully implements the new PNGtuber feature, including the necessary scene components, settings, store for state management, and ZIP file loader. The integration with the existing model selection and stage components is well-executed. My review includes a few suggestions to enhance maintainability and animation loop consistency, such as using more specific i18n keys, simplifying some logic in the rendering component, and refactoring the blink animation to be fully managed within requestAnimationFrame. Overall, this is a solid contribution that adds significant new functionality.
|
|
||
| <template> | ||
| <Section | ||
| :title="t('settings.live2d.scale-and-position.title')" |
There was a problem hiding this comment.
The internationalization (i18n) keys used in this component appear to be copied from the Live2D settings. For better maintainability and to avoid potential conflicts, it's recommended to use keys specific to PNGtuber, such as settings.pngtuber.scale-and-position.title. This should be applied to all labels within this component.
:title="t('settings.pngtuber.scale-and-position.title')"
| const baseSprite = (emotionData && typeof emotionData !== 'string' ? emotionData.default : null) ?? manifest.value.idle.default | ||
| const blinkSprite = (emotionData && typeof emotionData !== 'string' ? emotionData.blink : null) ?? manifest.value.idle.blink |
There was a problem hiding this comment.
The check typeof emotionData !== 'string' is redundant, as the PNGtuberManifest type defines emotions as a record of objects. emotionData will therefore be an object or undefined, never a string. You can simplify this logic using optional chaining for better readability.
const baseSprite = emotionData?.default ?? manifest.value.idle.default
const blinkSprite = emotionData?.blink ?? manifest.value.idle.blink
| // Update blink state - only schedule a new blink if not already blinking | ||
| if (!blinkState.value.isBlinking) { | ||
| blinkState.value.blinkTimer += deltaTime | ||
| if (blinkState.value.blinkTimer >= blinkState.value.nextBlinkTime) { | ||
| blinkState.value.isBlinking = true | ||
| setTimeout(() => { | ||
| blinkState.value.isBlinking = false | ||
| blinkState.value.blinkTimer = 0 | ||
| blinkState.value.nextBlinkTime = BLINK_INTERVAL_MIN_MS + Math.random() * (BLINK_INTERVAL_MAX_MS - BLINK_INTERVAL_MIN_MS) | ||
| }, BLINK_DURATION_MS) | ||
| } | ||
| } |
There was a problem hiding this comment.
Using setTimeout within a requestAnimationFrame loop can lead to animation synchronization issues. It's best practice to manage all animation timing within the render loop using the provided timestamp and deltaTime.
To improve this, you could add a blinkEndTime to your blinkState ref:
const blinkState = ref({
// ... other properties
blinkEndTime: 0,
})Then, refactor the blink logic to be fully managed by the render loop, like so:
// Update blink state
if (blinkState.value.isBlinking) {
if (timestamp >= blinkState.value.blinkEndTime) {
blinkState.value.isBlinking = false
blinkState.value.blinkTimer = 0
blinkState.value.nextBlinkTime = BLINK_INTERVAL_MIN_MS + Math.random() * (BLINK_INTERVAL_MAX_MS - BLINK_INTERVAL_MIN_MS)
}
}
else {
blinkState.value.blinkTimer += deltaTime
if (blinkState.value.blinkTimer >= blinkState.value.nextBlinkTime) {
blinkState.value.isBlinking = true
blinkState.value.blinkEndTime = timestamp + BLINK_DURATION_MS
}
}
⏳ Approval required for deploying to Cloudflare Workers (Preview) for stage-web.
Hey, @nekomeowww, @sumimakito, @luoling8192, @LemonNekoGH, kindly take some time to review and approve this deployment when you are available. Thank you! 🙏 |
|
Rebase needed. |
Overview
Implements PNGtuber feature that provides 2D PNG image-based avatar display and animation functionality.
Main Changes
New Additions
Integration
Improvements
Change Statistics
Testing