@quybt93/pcgf 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +20 -0
- package/.agents/skills/bmad-advanced-elicitation/SKILL.md +64 -0
- package/.agents/skills/bmad-advanced-elicitation/assets/methods.csv +72 -0
- package/.agents/skills/bmad-advanced-elicitation/customize.toml +54 -0
- package/.agents/skills/bmad-advanced-elicitation/scripts/pick_methods.py +233 -0
- package/.agents/skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py +228 -0
- package/.agents/skills/bmad-agent-analyst/SKILL.md +76 -0
- package/.agents/skills/bmad-agent-analyst/customize.toml +103 -0
- package/.agents/skills/bmad-agent-architect/SKILL.md +76 -0
- package/.agents/skills/bmad-agent-architect/customize.toml +63 -0
- package/.agents/skills/bmad-agent-dev/SKILL.md +76 -0
- package/.agents/skills/bmad-agent-dev/customize.toml +81 -0
- package/.agents/skills/bmad-agent-pm/SKILL.md +76 -0
- package/.agents/skills/bmad-agent-pm/customize.toml +73 -0
- package/.agents/skills/bmad-agent-ux-designer/SKILL.md +76 -0
- package/.agents/skills/bmad-agent-ux-designer/customize.toml +58 -0
- package/.agents/skills/bmad-architecture/SKILL.md +85 -0
- package/.agents/skills/bmad-architecture/assets/spine-template.md +79 -0
- package/.agents/skills/bmad-architecture/customize.toml +101 -0
- package/.agents/skills/bmad-architecture/references/headless.md +26 -0
- package/.agents/skills/bmad-architecture/references/reviewer-gate.md +13 -0
- package/.agents/skills/bmad-architecture/scripts/lint_spine.py +257 -0
- package/.agents/skills/bmad-architecture/scripts/tests/test_lint_spine.py +270 -0
- package/.agents/skills/bmad-brainstorming/SKILL.md +80 -0
- package/.agents/skills/bmad-brainstorming/assets/brain-icons.json +166 -0
- package/.agents/skills/bmad-brainstorming/assets/brain-methods.csv +109 -0
- package/.agents/skills/bmad-brainstorming/assets/brain-selector.html +328 -0
- package/.agents/skills/bmad-brainstorming/customize.toml +83 -0
- package/.agents/skills/bmad-brainstorming/references/converge.md +24 -0
- package/.agents/skills/bmad-brainstorming/references/finalize.md +26 -0
- package/.agents/skills/bmad-brainstorming/references/headless.md +54 -0
- package/.agents/skills/bmad-brainstorming/references/in-chat-techniques.md +18 -0
- package/.agents/skills/bmad-brainstorming/references/mode-autonomous.md +10 -0
- package/.agents/skills/bmad-brainstorming/references/mode-facilitator.md +11 -0
- package/.agents/skills/bmad-brainstorming/references/mode-partner.md +16 -0
- package/.agents/skills/bmad-brainstorming/references/resume.md +5 -0
- package/.agents/skills/bmad-brainstorming/scripts/brain.py +789 -0
- package/.agents/skills/bmad-brainstorming/scripts/tests/test_brain.py +289 -0
- package/.agents/skills/bmad-build/SKILL.md +13 -0
- package/.agents/skills/bmad-build/compile-epic-context.md +62 -0
- package/.agents/skills/bmad-build/customize.toml +152 -0
- package/.agents/skills/bmad-build/references/claims-check.md +14 -0
- package/.agents/skills/bmad-build/references/deletion-check.md +14 -0
- package/.agents/skills/bmad-build/review-prompts/edge-case-hunter.md +112 -0
- package/.agents/skills/bmad-build/review-prompts/verification-gap.md +113 -0
- package/.agents/skills/bmad-build/spec-template.md +111 -0
- package/.agents/skills/bmad-build/step-01-clarify-and-route.md +100 -0
- package/.agents/skills/bmad-build/step-02-plan.md +62 -0
- package/.agents/skills/bmad-build/step-03-implement.md +51 -0
- package/.agents/skills/bmad-build/step-04-review.md +85 -0
- package/.agents/skills/bmad-build/step-05-present.md +43 -0
- package/.agents/skills/bmad-build/step-oneshot.md +107 -0
- package/.agents/skills/bmad-build/sync-sprint-status.md +5 -0
- package/.agents/skills/bmad-build/workflow.md +84 -0
- package/.agents/skills/bmad-build-auto/SKILL.md +13 -0
- package/.agents/skills/bmad-build-auto/compile-epic-context.md +62 -0
- package/.agents/skills/bmad-build-auto/customize.toml +119 -0
- package/.agents/skills/bmad-build-auto/references/claims-check.md +14 -0
- package/.agents/skills/bmad-build-auto/references/deletion-check.md +14 -0
- package/.agents/skills/bmad-build-auto/review-prompts/edge-case-hunter.md +112 -0
- package/.agents/skills/bmad-build-auto/review-prompts/verification-gap.md +113 -0
- package/.agents/skills/bmad-build-auto/spec-template.md +96 -0
- package/.agents/skills/bmad-build-auto/step-01-clarify-and-route.md +84 -0
- package/.agents/skills/bmad-build-auto/step-02-plan.md +27 -0
- package/.agents/skills/bmad-build-auto/step-03-implement.md +48 -0
- package/.agents/skills/bmad-build-auto/step-04-review.md +116 -0
- package/.agents/skills/bmad-build-auto/workflow.md +104 -0
- package/.agents/skills/bmad-code-review/SKILL.md +90 -0
- package/.agents/skills/bmad-code-review/customize.toml +110 -0
- package/.agents/skills/bmad-code-review/references/claims-check.md +14 -0
- package/.agents/skills/bmad-code-review/references/deletion-check.md +14 -0
- package/.agents/skills/bmad-code-review/review-prompts/edge-case-hunter.md +112 -0
- package/.agents/skills/bmad-code-review/review-prompts/verification-gap.md +113 -0
- package/.agents/skills/bmad-code-review/steps/step-01-gather-context.md +94 -0
- package/.agents/skills/bmad-code-review/steps/step-02-review.md +32 -0
- package/.agents/skills/bmad-code-review/steps/step-03-triage.md +54 -0
- package/.agents/skills/bmad-code-review/steps/step-04-present.md +134 -0
- package/.agents/skills/bmad-correct-course/SKILL.md +308 -0
- package/.agents/skills/bmad-correct-course/checklist.md +288 -0
- package/.agents/skills/bmad-correct-course/customize.toml +39 -0
- package/.agents/skills/bmad-create-epics-and-stories/SKILL.md +93 -0
- package/.agents/skills/bmad-create-epics-and-stories/customize.toml +39 -0
- package/.agents/skills/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md +263 -0
- package/.agents/skills/bmad-create-epics-and-stories/steps/step-02-design-epics.md +242 -0
- package/.agents/skills/bmad-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
- package/.agents/skills/bmad-create-epics-and-stories/steps/step-04-final-validation.md +143 -0
- package/.agents/skills/bmad-create-epics-and-stories/templates/epics-template.md +61 -0
- package/.agents/skills/bmad-customize/SKILL.md +111 -0
- package/.agents/skills/bmad-customize/scripts/list_customizable_skills.py +231 -0
- package/.agents/skills/bmad-customize/scripts/tests/test_list_customizable_skills.py +249 -0
- package/.agents/skills/bmad-deep-recon/SKILL.md +82 -0
- package/.agents/skills/bmad-deep-recon/assets/research.template.md +18 -0
- package/.agents/skills/bmad-deep-recon/customize.toml +212 -0
- package/.agents/skills/bmad-deep-recon/references/draft.md +8 -0
- package/.agents/skills/bmad-deep-recon/references/finalize.md +11 -0
- package/.agents/skills/bmad-deep-recon/references/html-briefing.md +16 -0
- package/.agents/skills/bmad-deep-recon/references/lifecycle.md +11 -0
- package/.agents/skills/bmad-deep-recon/references/process.md +10 -0
- package/.agents/skills/bmad-deep-recon/references/run.md +73 -0
- package/.agents/skills/bmad-deep-recon/references/selection.md +13 -0
- package/.agents/skills/bmad-deep-recon/references/synthesis.md +16 -0
- package/.agents/skills/bmad-deep-recon/references/verification.md +29 -0
- package/.agents/skills/bmad-deep-recon/scripts/recon_kit.py +322 -0
- package/.agents/skills/bmad-deep-recon/scripts/tests/test_recon_kit.py +144 -0
- package/.agents/skills/bmad-deep-recon/types/academic-lit.md +19 -0
- package/.agents/skills/bmad-deep-recon/types/competitive.md +19 -0
- package/.agents/skills/bmad-deep-recon/types/domain.md +19 -0
- package/.agents/skills/bmad-deep-recon/types/market.md +19 -0
- package/.agents/skills/bmad-deep-recon/types/technical.md +19 -0
- package/.agents/skills/bmad-deep-recon/types/user-voice.md +19 -0
- package/.agents/skills/bmad-forge-idea/SKILL.md +107 -0
- package/.agents/skills/bmad-forge-idea/customize.toml +41 -0
- package/.agents/skills/bmad-forge-idea/scripts/resolve_personas.py +277 -0
- package/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py +160 -0
- package/.agents/skills/bmad-help/SKILL.md +77 -0
- package/.agents/skills/bmad-party-mode/SKILL.md +60 -0
- package/.agents/skills/bmad-party-mode/customize.toml +211 -0
- package/.agents/skills/bmad-party-mode/references/create-party.md +70 -0
- package/.agents/skills/bmad-party-mode/references/mode-agent-team.md +13 -0
- package/.agents/skills/bmad-party-mode/references/mode-auto.md +13 -0
- package/.agents/skills/bmad-party-mode/references/mode-subagent.md +31 -0
- package/.agents/skills/bmad-party-mode/references/party-memory.md +51 -0
- package/.agents/skills/bmad-party-mode/scripts/resolve_party.py +284 -0
- package/.agents/skills/bmad-party-mode/scripts/tests/test_resolve_party.py +168 -0
- package/.agents/skills/bmad-prd/SKILL.md +94 -0
- package/.agents/skills/bmad-prd/assets/headless-schemas.md +76 -0
- package/.agents/skills/bmad-prd/assets/prd-template.md +165 -0
- package/.agents/skills/bmad-prd/assets/prd-validation-checklist.md +135 -0
- package/.agents/skills/bmad-prd/assets/validation-report-template.html +325 -0
- package/.agents/skills/bmad-prd/customize.toml +148 -0
- package/.agents/skills/bmad-prd/references/headless.md +39 -0
- package/.agents/skills/bmad-prd/references/validate.md +97 -0
- package/.agents/skills/bmad-prfaq/SKILL.md +135 -0
- package/.agents/skills/bmad-prfaq/agents/artifact-analyzer.md +60 -0
- package/.agents/skills/bmad-prfaq/agents/web-researcher.md +49 -0
- package/.agents/skills/bmad-prfaq/assets/prfaq-template.md +62 -0
- package/.agents/skills/bmad-prfaq/bmad-manifest.json +16 -0
- package/.agents/skills/bmad-prfaq/customize.toml +39 -0
- package/.agents/skills/bmad-prfaq/references/customer-faq.md +55 -0
- package/.agents/skills/bmad-prfaq/references/internal-faq.md +51 -0
- package/.agents/skills/bmad-prfaq/references/press-release.md +60 -0
- package/.agents/skills/bmad-prfaq/references/verdict.md +83 -0
- package/.agents/skills/bmad-product-brief/SKILL.md +91 -0
- package/.agents/skills/bmad-product-brief/assets/brief-template.md +41 -0
- package/.agents/skills/bmad-product-brief/customize.toml +100 -0
- package/.agents/skills/bmad-project-context/SKILL.md +121 -0
- package/.agents/skills/bmad-project-context/customize.toml +24 -0
- package/.agents/skills/bmad-project-context/references/best-practices.md +84 -0
- package/.agents/skills/bmad-project-context/references/template.md +55 -0
- package/.agents/skills/bmad-qa-generate-e2e-tests/SKILL.md +176 -0
- package/.agents/skills/bmad-qa-generate-e2e-tests/checklist.md +33 -0
- package/.agents/skills/bmad-qa-generate-e2e-tests/customize.toml +39 -0
- package/.agents/skills/bmad-retrospective/SKILL.md +94 -0
- package/.agents/skills/bmad-retrospective/customize.toml +39 -0
- package/.agents/skills/bmad-retrospective/references/acceptance-verdict.md +55 -0
- package/.agents/skills/bmad-retrospective/references/aggregate-views.md +17 -0
- package/.agents/skills/bmad-retrospective/references/evidence-gathering.md +30 -0
- package/.agents/skills/bmad-retrospective/references/retro-document.md +84 -0
- package/.agents/skills/bmad-retrospective/references/team-discussion.md +22 -0
- package/.agents/skills/bmad-retrospective/scripts/git_evidence.py +304 -0
- package/.agents/skills/bmad-retrospective/scripts/sprint_status.py +746 -0
- package/.agents/skills/bmad-retrospective/scripts/tests/fixtures/sprint-status-template.yaml +71 -0
- package/.agents/skills/bmad-retrospective/scripts/tests/test_git_evidence.py +750 -0
- package/.agents/skills/bmad-retrospective/scripts/tests/test_sprint_status.py +1579 -0
- package/.agents/skills/bmad-review/SKILL.md +50 -0
- package/.agents/skills/bmad-review/customize.toml +141 -0
- package/.agents/skills/bmad-review/references/editorial-common.md +56 -0
- package/.agents/skills/bmad-review/references/lens-adversarial.md +19 -0
- package/.agents/skills/bmad-review/references/lens-edge-case-hunter.md +72 -0
- package/.agents/skills/bmad-review/references/lens-prose.md +7 -0
- package/.agents/skills/bmad-review/references/lens-structure.md +9 -0
- package/.agents/skills/bmad-review/references/lens-verification-gap.md +92 -0
- package/.agents/skills/bmad-review/references/structure-models.md +44 -0
- package/.agents/skills/bmad-review/scripts/tests/test_word_metrics.py +62 -0
- package/.agents/skills/bmad-review/scripts/word_metrics.py +102 -0
- package/.agents/skills/bmad-spec/SKILL.md +160 -0
- package/.agents/skills/bmad-spec/assets/headless-schemas.md +33 -0
- package/.agents/skills/bmad-spec/assets/spec-template.md +49 -0
- package/.agents/skills/bmad-spec/assets/stories-schema.md +44 -0
- package/.agents/skills/bmad-spec/customize.toml +52 -0
- package/.agents/skills/bmad-sprint-planning/SKILL.md +62 -0
- package/.agents/skills/bmad-sprint-planning/customize.toml +39 -0
- package/.agents/skills/bmad-sprint-planning/references/fix-sprint-status.md +30 -0
- package/.agents/skills/bmad-sprint-planning/references/generate-tracking.md +25 -0
- package/.agents/skills/bmad-sprint-planning/references/readiness-gate.md +20 -0
- package/.agents/skills/bmad-sprint-planning/references/status-view.md +14 -0
- package/.agents/skills/bmad-sprint-planning/references/validate.md +10 -0
- package/.agents/skills/bmad-sprint-planning/scripts/sprint_plan.py +697 -0
- package/.agents/skills/bmad-sprint-planning/scripts/tests/test_sprint_plan.py +524 -0
- package/.agents/skills/bmad-sprint-planning/sprint-status-template.yaml +71 -0
- package/.agents/skills/bmad-ux/SKILL.md +90 -0
- package/.agents/skills/bmad-ux/assets/color-themes.md +9 -0
- package/.agents/skills/bmad-ux/assets/design-directions.md +9 -0
- package/.agents/skills/bmad-ux/assets/design-example-editorial.md +158 -0
- package/.agents/skills/bmad-ux/assets/design-example-mobile.md +93 -0
- package/.agents/skills/bmad-ux/assets/design-example-shadcn.md +109 -0
- package/.agents/skills/bmad-ux/assets/excalidraw-wireframe.md +19 -0
- package/.agents/skills/bmad-ux/assets/experience-example-mobile.md +112 -0
- package/.agents/skills/bmad-ux/assets/experience-example-shadcn.md +133 -0
- package/.agents/skills/bmad-ux/assets/headless-schemas.md +84 -0
- package/.agents/skills/bmad-ux/assets/key-screens.md +29 -0
- package/.agents/skills/bmad-ux/assets/validation-report-template.html +319 -0
- package/.agents/skills/bmad-ux/customize.toml +100 -0
- package/.agents/skills/bmad-ux/references/creative-tools.md +19 -0
- package/.agents/skills/bmad-ux/references/design-md-spec.md +50 -0
- package/.agents/skills/bmad-ux/references/headless.md +37 -0
- package/.agents/skills/bmad-ux/references/validate.md +115 -0
- package/.agents/skills/bmad-walkthrough/SKILL.md +68 -0
- package/.agents/skills/bmad-walkthrough/customize.toml +39 -0
- package/.agents/skills/bmad-walkthrough/generate-trail.md +38 -0
- package/.agents/skills/bmad-walkthrough/step-01-orientation.md +105 -0
- package/.agents/skills/bmad-walkthrough/step-02-walkthrough.md +89 -0
- package/.agents/skills/bmad-walkthrough/step-03-detail-pass.md +106 -0
- package/.agents/skills/bmad-walkthrough/step-04-testing.md +74 -0
- package/.agents/skills/bmad-walkthrough/step-05-wrapup.md +30 -0
- package/README.md +111 -0
- package/bin/pcgf.js +8 -0
- package/installer/clean.js +137 -0
- package/installer/cli.js +479 -0
- package/installer/deps.js +160 -0
- package/installer/fs-utils.js +58 -0
- package/installer/install.js +201 -0
- package/installer/paths.js +17 -0
- package/installer/scaffold.js +274 -0
- package/installer/tools.js +38 -0
- package/package.json +37 -0
- package/plugins/phaser-casual-game-factory/.codex-plugin/plugin.json +27 -0
- package/plugins/phaser-casual-game-factory/PROGRESS.md +120 -0
- package/plugins/phaser-casual-game-factory/README.md +79 -0
- package/plugins/phaser-casual-game-factory/assets/sfx/README.md +8 -0
- package/plugins/phaser-casual-game-factory/assets/sfx/ui_click.mp3 +0 -0
- package/plugins/phaser-casual-game-factory/assets/sfx/ui_close.mp3 +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/README.md +9 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_DarkGray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Mint.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Pink.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Sky.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_White_Light1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_White_Light2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_l_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_DarkGray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Flat.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Mint.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_PInk.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Sky.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_White_Light1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_White_Light2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button01_s_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle118.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle120.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle122.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle74_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle74_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Circle82.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_LeftFlush_Dark.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_LeftFlush_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_LeftFlush_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round01_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round01_White_Light1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round01_White_Light2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round01_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round02_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round02_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round02_White_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round03_Dark.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round03_WhiteBg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round03_White_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round04_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round04_Oblique.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round05.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round06_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round06_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round07.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round08.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round09.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round10_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Round10_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtnMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_Dark.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_SkillBtn_White_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Tapered_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Tapered_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Tapered_White3.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Button_Tapered_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Menu_BottomBtn_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Menu_BottomBtn_TabFocus.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Menu_BottomBtn_TabFocus_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Menu_MiddleBtn_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Button/Menu_MiddleBtn_TabFocus.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_InnerBg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_InnerLine.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_Pattern.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_01~02_Pattern.psd +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_03_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_03_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_04~06_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_04~06_BgLight.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_04~06_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame00_04~06_Pattern.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame03_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame04_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame05_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame06_Demo_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame06_Demo__Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BannerFrame07.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Circle160.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Hexagon87.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Oval44.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Oval50.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Round12.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Round17.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Round20.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BasicFrame_Round24.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Circle60.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Circle75_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Circle75_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Circle78.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_Demo_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_Demo_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_Demo_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_White_BgGradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_White_BgLine01.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Flag_White_BgLine02.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Oval46_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Oval46_InnerLine.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Oval58.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Rhombus_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Rhombus_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round18_Transparent.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round20_Demo_Dark.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round20_Demo_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round20_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round20_White_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round24.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Round30.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Squrare_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BorderFrame_Squrare_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_BgArrow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_BgShadow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Hexagon_Bg_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Hexagon_Bg_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Hexagon_Bg_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Hexagon_FocusBorder.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame01_Hexagon_FocusGlow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame02_Arrow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame02_BgShadow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame03_Arrow_Left.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame03_Arrow_Right.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame03_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame04_Blue_Arrow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame04_Blue_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame04_White_Arrow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame04_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_InnerBg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_InnerBorder.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_Left_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_Left_BgShadow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_Right_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/BubbleFrame05_Right_BgShadow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Bg_d.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Bg_d_Pattern.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Bg_n.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Bottom.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Glow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Gradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame01_Gradient_Hologram.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_d_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_d_Bg_Pattern.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_d_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_n_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_n_Bottom.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame02_n_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame03_d.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame03_n_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame03_n_InnerBg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame03_n_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_Bg_DividerLine.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_Bg_Gradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_FocusBorder.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_FocusGlow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame04_Glow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_Bg_Corner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_FocusBorder.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_FocusGlow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame05_Glow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_Demo_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_Demo_Bg_Glow_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_Demo_Deco_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_Demo_Frame_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_White_Bg_Glow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_White_Deco.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/CardFrame06_White_Frame.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_BgGlow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_BgLight.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_Bg_Hologram.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_CornerDeco.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame00~03_FocusLine.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Hologram1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Hologram2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Navy.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_OffWhite.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame01_Demo_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Hologram1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Hologram2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Navy.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_OffWhite.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame02_Demo_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Hologram.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Navy.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ItemFrame03_Demo_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_01~02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_01~02_BgInner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_01~02_Oblique.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_03~04_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_03~04_BgInner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame00_03~04_Dim.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame04_Demo_f_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ListFrame04_Demo_f_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame01_Line.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame02.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame03_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame03_Oblique.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame04_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame04_OutTilte1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/PanelFrame04_OutTilte2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame01_l_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame01_l_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame01_m~s_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame01_m~s_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame02_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame_Circle275_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/ProfileFrame_Circle275_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_l~m_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_l~m_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_l~m_Empty.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_s_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_s_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Frame/SkillFrame_s_Empty.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_brz.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_chn.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_cze.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_deu.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_eng.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_esp.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_fra.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_gbr.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_gre.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_ind.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_ita.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_jpn.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_kor.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_pol.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_prt.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_rou.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_rsa.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_rus.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_swe.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_tha.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_tur.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_twn.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_ukr.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_Flag/Small/Icon_Flag_usa.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Beginner.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Bronze.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Challenger.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Diamond.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Grandmaster.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Iron.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Master.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Platinum.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_GradeBadge/256/Icon_GradeBadge_Silver.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Badge_Crown.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Badge_Gold.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Bag_Brown.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Bag_Gray.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Battle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Book_1_Purple.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Book_1_Wine.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Calendar.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Calendar_Check.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Chat.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Chest_Gem.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Chest_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Chest_Premium.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Chest_Wood.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Clover_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Clover_Green.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Damage.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Dungeon.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Earth.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Energy_Blue.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Friend.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Armor_Bottom.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Armor_Top.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Boots.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Hat_Witch.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Ring.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gear_Sword.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gem_Circle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gem_Diamond_Purple.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gem_Ellipse_Red.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gem_Star_Blue.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gift_Blue.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gift_Green.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Gift_Red.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Heart_Dimmed.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Heart_Red.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Key_Gold.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Mail.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Map.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Meat.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Bronze_1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Bronze_2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Gold_1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Gold_2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Silver_1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medal_Silver_2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Medalstand.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_MemoPad.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Money_Bill.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Money_Coin.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Pot.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Shop.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Skull.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Blue.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Bronze.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Purple.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Red.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Star_Silver.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_TV_AdBlock.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Ticket_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Ticket_Red.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Trophy_Bronze.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Trophy_Gold.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Trophy_Silver.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_ItemIcons/256/ItemIcon_Video.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Again_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Again_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Aiming_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Aiming_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Alarm.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Anchor.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Archer.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Armor.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Down.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Left_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Left_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Left_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Right_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Right_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Right_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Arrow_Up.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_At.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Attack.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Ax.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Ax_Double.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Back_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Back_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Badge.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bag.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bank.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Basket.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Battery_Charge.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Battle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bell.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bell_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bell_On.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bell_Sleep.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Blacksmith.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Block.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bluetooth.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bomb_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bomb_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Book_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Book_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Book_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Boots.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Boss.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bow.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Brief_Bag.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Brush.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bulb.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bulb_Charge.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Bullet.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Calendar.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Camera.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Camera_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Cap.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Card_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Card_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Cart_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Cart_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Castle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Caution.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Certification.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Change.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Chat_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Chat_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Check_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Check_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Chest.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Chisel.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_A.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_B.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_C.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_D.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_S.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Class_Ss.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Clock_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Clock_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Closet.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Clothes.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Coin.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Coin_Star.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Compass.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Console_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Console_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Contraction.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Cooking.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Copy.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Costume.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Critical_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Critical_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Critical_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Crown_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Crown_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Crystal.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Delete.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Diamond.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Dice.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Direction_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Direction_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Discount.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Dollar_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Dollar_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Download.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Earth.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Earth_Pin.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Effect.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Energy_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Energy_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Exit.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Exit_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Exit_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Exp.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Expansion.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Face.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Faint.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Female.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Fire.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Firework.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Fish.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Fishing.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Flag.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Float.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Food.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Freezee.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Friends.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Gallery.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Game.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Gear.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Gift.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Glasses.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Globe.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Graduation_Cap.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hammer.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hammer_Claw.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hand_Touch.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hanger.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hat.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Headset.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Heart.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Heart_Add.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Heart_Empty.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Helmet_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Helmet_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Help_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Help_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_History.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Home_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Home_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Hp.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Icecream.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Illuminati.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Infinity.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Info_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Info_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Info_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Info_4.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Key.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Kitchen_Knife.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Layer_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Layer_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Leaf.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Link.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Lock_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Lock_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Lock_Open.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Magic.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Magic_Ball.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Mail_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Mail_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Male.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Map_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Map_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Map_Pin.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Meal.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Medal_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Medal_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Megaphone.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_4.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_5.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Menu_6.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Merge.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Message_Bottle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Minus_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Minus_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Mission.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Money_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Money_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Money_Pouch.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Movie.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Mushroom.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Music_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Music_1_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Music_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Music_2_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Necklace.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Night.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Note.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Object.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Page_Next.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Page_Prev.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Paper_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Paper_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Path.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pause_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pause_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Paw.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pen.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pen_Feather.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pencil.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Phone.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Photo_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Photo_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pick.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pickax.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Plants.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Play_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Play_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Plus_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Plus_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Potion_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Potion_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Potion_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Pouch.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Power_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Power_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Power_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Rampart.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Rank_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Rank_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Recommendation.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Recycle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Refresh_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Refresh_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Refresh_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Refresh_4.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Ring.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Roulette.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Safebox.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sandglass.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Saw.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Scale.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Scroll_Old.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Search.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Security.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Setting.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Share.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sheos.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sheos_Wing.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sheriff.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shield_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shield_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shield_Viking.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Ship.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shop_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shop_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shop_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Shovel.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sickle.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sign.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Skull.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sound.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sound_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Star_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Star_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Star_3.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Star_Empty.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Step.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Stopwatch_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Stopwatch_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Storage.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sun.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Switch.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sword_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Sword_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Tag.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Target.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Telescope.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Temple.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Ticket.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Tool_Fix.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Top.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Trophy_1.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Trophy_2.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Tv.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Typhoon.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Under.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_User.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_User_Add.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_User_Info.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Video.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_View.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_View_Off.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Vr.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Warehouse.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Water.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Wing.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Wood.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_World.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Zoom_In.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_PictoIcons/256/PictoIcon_Zoom_Out.Png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_3.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_4.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_5.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Icon_TutorialHand/256/tutorial_hand_6.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Badge01_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Badge01_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Badge01_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Badge01_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Badge02.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Bubble_Arrow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Bubble_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Hologram.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_White_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Parallelogram_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Ribbon_Hologram.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Ribbon_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Tail_Demo_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Tail_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Label_Tail_White_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_LIne04_Under.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Line01_Divider_Left.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Line01_Divider_Right.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Line02_Divider_Left.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Line02_Divider_Right.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Line03_Divider.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Oval.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Magenta.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Navy.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Peacock.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Plum.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Purple.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Sky.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon01_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon02_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon02_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon02_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon03_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon03_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon03_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon04_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Ribbon05.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Tapered01.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Tapered02.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Label/Title_Tapered03.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/PACK.md +6 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup01_Basic_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup01_Basic_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup01_Basic_White_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup02~09_Topber_Demo_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup02~09_Topber_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup02~09_Topber_White_BgTop.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup02~09_Topber_White_BgTopLight.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup03_Gradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup06_Glow_Bottom.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup06_Pattern.psd +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup09_Topber_White_Label_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup09_Topber_White_Label_Inner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Chat_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Chat_BgLight.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Chat_TabFocus.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_FullWidth_Dark.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_FullWidth_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_List_VerticalLayout.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_OutTitle_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_OutTitle_Bg_Title.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_OutTitle_Inner_Bottom.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_OutTitle_Inner_Top.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Ticket_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Ticket_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Ticket_BottomPattern.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Popup/Popup_Ticket_Gradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Bg_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Bg_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Bg_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Fill_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Fill_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Fill_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic01_Fill_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_Fill_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_Fill_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_Fill_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic02_Fill_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Bg_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Bg_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Bg_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Fill_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Fill_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Fill_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic03_Fill_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic04_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic04_Fill_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic04_Fill_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic04_White_Fill1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Basic04_White_Fill2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_Fill_Pink.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_Fill_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_Fill_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Handle_Handle.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_Fill_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_Fill_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_Icon1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon01_Icon2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Badge1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Badge2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Fill_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Fill_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Icon02_Icon1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level01_Badge_l.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level01_Badge_s.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level01_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level01_Fill.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level01_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Bg_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Bg_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Bg_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill01_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill01_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill01_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill02_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill02_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Fill02_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Icon_Badge_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Icon_Badge_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Icon_Up_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level02_Icon_Up_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level03_Badge1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level03_Badge2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level03_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level03_Fill1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Level03_Fill2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Panel_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Panel_Fill1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Panel_Fill2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Play01_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Play01_Fill.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Play01_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Play02_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Play02_FillMask.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_l_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_l_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_l_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_l_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_l_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_s_Blue.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_s_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_s_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageHorizontal_Icon_s_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageVertical_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageVertical_Icon1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_StageVertical_Icon2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Wave_Badge1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Wave_Badge2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Wave_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/Slider_Wave_Fill.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/_Slider_Basic_R6_Fill_Orange.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/_Slider_Round6_01_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/Slider/_Slider_Round6_01_White_Fill.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Circle_Icon_Exclamation.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Circle_l_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Circle_l_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Circle_s_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Circle_s_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Dot_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Dot_Border.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Alert_Dot_Light.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Bg_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Bg_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Bg_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Bg_White3.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Icon_Lock.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField01_Icon_Mail.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField02_Demo.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField02_White1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField02_White2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField03.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/InputField04.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Blue1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Blue2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Purple1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Purple2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Yellow1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Btn_Yellow2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Icon_Coin.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Icon_Energy.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Icon_Gem.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_Demo_Icon_Monster.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Btn1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Btn2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Btn3.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Icon1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ResourceBar_White_Icon2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_Demo_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_Demo_Fill.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_Demo_Handle.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_White_BgInner.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_White_Fill1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_White_Fill2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Switch_White_Handle.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Bg_Gray.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Bg_Green.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Bg_Red.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Bg_White.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Bg_Yellow.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Gradient.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Light1.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/ToastMessage_Light2.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Toggle_Check_Demo_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Toggle_Check_Demo_Icon.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Toggle_Check_White_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Toggle_Check_White_BgLight.png +0 -0
- package/plugins/phaser-casual-game-factory/assets/ui-packs/super-casual/UI_Etc/Toggle_Check_White_Icon.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/README.md +44 -0
- package/plugins/phaser-casual-game-factory/examples/economy-demo-config.ts +255 -0
- package/plugins/phaser-casual-game-factory/examples/economy-demo.ts +89 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/index.html +342 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/package-lock.json +1293 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/package.json +21 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/playwright.config.ts +26 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/sfx/ui_click.mp3 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/sfx/ui_close.mp3 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/ui/BG_lobby.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/ui/Bar_Bg.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/ui/progress_inner.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/assets/ui/progress_outer.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-400-latin-OEyTajQY.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-400-viet-SOx6iaFb.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-600-latin-xAC4kEK0.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-600-viet-DbGrrtCq.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-700-latin-CPfR8Jz_.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-700-viet-DptIoWwl.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-800-latin-B5VTH9An.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-800-viet-BEUwTqXl.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-900-latin-B6esVQUu.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/fonts/bvp-900-viet-DUJ3fpCl.woff2 +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/public/logo-frog.png +0 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/brand/BootLoadingScreen.js +7 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/brand/SplashFullscreenBg.js +4 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/brand-shims.d.ts +33 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/demo-scenes.ts +12 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/demo-tools.ts +34 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/main.ts +1358 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/scenes/BootScene.ts +236 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/scenes/GameScene.ts +152 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/scenes/HomeScene.ts +21 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/scenes/scene-hooks.ts +12 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/styles.css +623 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/src/ui-audio.ts +156 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/tests/browser-smoke.spec.ts +170 -0
- package/plugins/phaser-casual-game-factory/examples/factory-browser-demo/vite.config.ts +23 -0
- package/plugins/phaser-casual-game-factory/examples/leveling-demo-config.ts +107 -0
- package/plugins/phaser-casual-game-factory/references/condition-service.md +38 -0
- package/plugins/phaser-casual-game-factory/references/core-contracts.md +39 -0
- package/plugins/phaser-casual-game-factory/references/daily-login-service.md +32 -0
- package/plugins/phaser-casual-game-factory/references/economy-service.md +192 -0
- package/plugins/phaser-casual-game-factory/references/leveling-service.md +56 -0
- package/plugins/phaser-casual-game-factory/references/loading-view.md +181 -0
- package/plugins/phaser-casual-game-factory/references/time-service.md +42 -0
- package/plugins/phaser-casual-game-factory/scripts/new-phaser-casual-game.ps1 +152 -0
- package/plugins/phaser-casual-game-factory/scripts/run-browser-demo.ps1 +13 -0
- package/plugins/phaser-casual-game-factory/scripts/run-economy-demo.ps1 +4 -0
- package/plugins/phaser-casual-game-factory/scripts/test-all.ps1 +11 -0
- package/plugins/phaser-casual-game-factory/scripts/test-browser.ps1 +10 -0
- package/plugins/phaser-casual-game-factory/scripts/test-economy.ps1 +4 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/SKILL.md +846 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/.env.example +19 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/bgremove.py +127 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/codex_extract.py +123 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/codex_gen.sh +172 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/envfile.py +121 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/gemini_image_mcp.py +1870 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/imglib.py +2138 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/remote_backend.py +498 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/remote_codex.py +59 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/remote_proto.py +135 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/requirements-client.txt +22 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/test_imglib.py +1647 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/test_restyle_tools.py +256 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/tools/restyle/styles/unscrew-casual.refs/ref-lose.jpg +0 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/tools/restyle/styles/unscrew-casual.refs/ref-welcome.jpg +0 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/tools/restyle/styles/unscrew-casual.refs/ref-win.jpg +0 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/client/upscale.py +289 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/reference/client-guide.md +180 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/reference/mcp-image-input.md +148 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/reference/prompt-template.md +216 -0
- package/plugins/phaser-casual-game-factory/skills/game-art/reference/remote-lan.md +224 -0
- package/plugins/phaser-casual-game-factory/skills/pcgf-git-merge-request/SKILL.md +96 -0
- package/plugins/phaser-casual-game-factory/skills/pcgf-ui-reskin/SKILL.md +144 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-adaptive-loading/SKILL.md +33 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-casual-game-factory/SKILL.md +225 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-condition-service/SKILL.md +21 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-daily-login-service/SKILL.md +20 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-economy-service/SKILL.md +72 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-foundation/SKILL.md +60 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-leveling-service/SKILL.md +39 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-loading-view/SKILL.md +167 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-studio25-boot-brand/SKILL.md +107 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-time-service/SKILL.md +26 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-ui-motion/SKILL.md +161 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-ui-motion/fix-off-canvas-press.md +198 -0
- package/plugins/phaser-casual-game-factory/skills/phaser-ui-sfx/SKILL.md +83 -0
- package/plugins/phaser-casual-game-factory/skills/theme-cream-casual/SKILL.md +136 -0
- package/plugins/phaser-casual-game-factory/skills/theme-dark-casual/SKILL.md +23 -0
- package/plugins/phaser-casual-game-factory/skills/tool-demo-qa/SKILL.md +264 -0
- package/plugins/phaser-casual-game-factory/templates/adaptive-loading/adaptive-loading-manager.ts +103 -0
- package/plugins/phaser-casual-game-factory/templates/adaptive-loading/device-profile.ts +76 -0
- package/plugins/phaser-casual-game-factory/templates/adaptive-loading/device-tier-session.ts +133 -0
- package/plugins/phaser-casual-game-factory/templates/adaptive-loading/index.ts +4 -0
- package/plugins/phaser-casual-game-factory/templates/adaptive-loading/types.ts +27 -0
- package/plugins/phaser-casual-game-factory/templates/boot/brand/BootLoadingScreen.js +370 -0
- package/plugins/phaser-casual-game-factory/templates/boot/brand/SplashFullscreenBg.js +18 -0
- package/plugins/phaser-casual-game-factory/templates/boot/brand/brand-defaults.js +36 -0
- package/plugins/phaser-casual-game-factory/templates/boot/brand-shims.d.ts +40 -0
- package/plugins/phaser-casual-game-factory/templates/boot/close-styles.ts +26 -0
- package/plugins/phaser-casual-game-factory/templates/boot/index.ts +32 -0
- package/plugins/phaser-casual-game-factory/templates/boot/iris-close.ts +85 -0
- package/plugins/phaser-casual-game-factory/templates/boot/map-dom-rect-to-game.ts +53 -0
- package/plugins/phaser-casual-game-factory/templates/boot/play-boot-loading-view.ts +124 -0
- package/plugins/phaser-casual-game-factory/templates/commerce/commerce-service.ts +22 -0
- package/plugins/phaser-casual-game-factory/templates/commerce/index.ts +1 -0
- package/plugins/phaser-casual-game-factory/templates/commerce/types.ts +6 -0
- package/plugins/phaser-casual-game-factory/templates/condition/condition-service.ts +166 -0
- package/plugins/phaser-casual-game-factory/templates/condition/index.ts +2 -0
- package/plugins/phaser-casual-game-factory/templates/condition/types.ts +69 -0
- package/plugins/phaser-casual-game-factory/templates/core/events.ts +71 -0
- package/plugins/phaser-casual-game-factory/templates/core/gameplay.ts +15 -0
- package/plugins/phaser-casual-game-factory/templates/core/index.ts +9 -0
- package/plugins/phaser-casual-game-factory/templates/core/layout.ts +25 -0
- package/plugins/phaser-casual-game-factory/templates/core/loading.ts +33 -0
- package/plugins/phaser-casual-game-factory/templates/core/service-registry.ts +28 -0
- package/plugins/phaser-casual-game-factory/templates/core/services.ts +19 -0
- package/plugins/phaser-casual-game-factory/templates/core/storage.ts +7 -0
- package/plugins/phaser-casual-game-factory/templates/core/time.ts +70 -0
- package/plugins/phaser-casual-game-factory/templates/core/types.ts +21 -0
- package/plugins/phaser-casual-game-factory/templates/daily-login/daily-login-service.ts +136 -0
- package/plugins/phaser-casual-game-factory/templates/daily-login/index.ts +3 -0
- package/plugins/phaser-casual-game-factory/templates/daily-login/reward-service.ts +108 -0
- package/plugins/phaser-casual-game-factory/templates/daily-login/types.ts +39 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/demo-device-tier.ts +73 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/demo-perf.ts +232 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/demo-tools.css +355 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/demo-tools.ts +305 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/index.ts +7 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/init-demo-qa-tools.ts +101 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/tool-param-fields.ts +214 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/tool-sections.ts +238 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/tool-shell.html +57 -0
- package/plugins/phaser-casual-game-factory/templates/demo-tools/tool-shell.ts +141 -0
- package/plugins/phaser-casual-game-factory/templates/economy/default-registry.ts +14 -0
- package/plugins/phaser-casual-game-factory/templates/economy/economy-service.ts +65 -0
- package/plugins/phaser-casual-game-factory/templates/economy/exchange-handlers.ts +58 -0
- package/plugins/phaser-casual-game-factory/templates/economy/grant-handler.ts +58 -0
- package/plugins/phaser-casual-game-factory/templates/economy/index.ts +15 -0
- package/plugins/phaser-casual-game-factory/templates/economy/inventory-service.ts +170 -0
- package/plugins/phaser-casual-game-factory/templates/economy/item-service.ts +220 -0
- package/plugins/phaser-casual-game-factory/templates/economy/item-utils.ts +126 -0
- package/plugins/phaser-casual-game-factory/templates/economy/merge-handler.ts +42 -0
- package/plugins/phaser-casual-game-factory/templates/economy/operation-handler.ts +44 -0
- package/plugins/phaser-casual-game-factory/templates/economy/package-handler.ts +41 -0
- package/plugins/phaser-casual-game-factory/templates/economy/random.ts +33 -0
- package/plugins/phaser-casual-game-factory/templates/economy/repository.ts +64 -0
- package/plugins/phaser-casual-game-factory/templates/economy/state-utils.ts +221 -0
- package/plugins/phaser-casual-game-factory/templates/economy/types.ts +309 -0
- package/plugins/phaser-casual-game-factory/templates/economy/ui-view-models.ts +79 -0
- package/plugins/phaser-casual-game-factory/templates/entitlement/entitlement-service.ts +29 -0
- package/plugins/phaser-casual-game-factory/templates/entitlement/index.ts +1 -0
- package/plugins/phaser-casual-game-factory/templates/entitlement/types.ts +26 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/condition-evaluator.ts +17 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/config-validator.ts +63 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/index.ts +5 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/leveling-service.ts +306 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/types.ts +80 -0
- package/plugins/phaser-casual-game-factory/templates/leveling/view-model.ts +52 -0
- package/plugins/phaser-casual-game-factory/templates/loading-view/index.ts +4 -0
- package/plugins/phaser-casual-game-factory/templates/loading-view/loading-view-model.ts +203 -0
- package/plugins/phaser-casual-game-factory/templates/loading-view/presets.ts +26 -0
- package/plugins/phaser-casual-game-factory/templates/loading-view/progress.ts +30 -0
- package/plugins/phaser-casual-game-factory/templates/loading-view/types.ts +49 -0
- package/plugins/phaser-casual-game-factory/templates/motion/index.ts +2 -0
- package/plugins/phaser-casual-game-factory/templates/motion/phaser-ui-motion.ts +363 -0
- package/plugins/phaser-casual-game-factory/templates/motion/types.ts +21 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/browser-storage-adapter.ts +91 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/design-size.ts +34 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/foundation-scene.ts +39 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/hybrid-loading-layer.css +46 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/loading-overlay-scene.ts +653 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/phaser-event-bus.ts +35 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/scene-keys.ts +12 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/scene-registration.ts +28 -0
- package/plugins/phaser-casual-game-factory/templates/phaser/system-time-adapter.ts +33 -0
- package/plugins/phaser-casual-game-factory/templates/time/index.ts +2 -0
- package/plugins/phaser-casual-game-factory/templates/time/time-service.ts +184 -0
- package/plugins/phaser-casual-game-factory/templates/ui/audio-settings.ts +148 -0
- package/plugins/phaser-casual-game-factory/templates/ui/bind-factory-dom-press.ts +108 -0
- package/plugins/phaser-casual-game-factory/templates/ui/factory-cream-casual.css +380 -0
- package/plugins/phaser-casual-game-factory/templates/ui/factory-dark-casual.css +11 -0
- package/plugins/phaser-casual-game-factory/templates/ui/index.ts +5 -0
- package/plugins/phaser-casual-game-factory/templates/ui/settings-popup-dom.ts +349 -0
- package/plugins/phaser-casual-game-factory/templates/ui/settings-popup-phaser.ts +284 -0
- package/plugins/phaser-casual-game-factory/templates/ui/ui-sfx.ts +131 -0
- package/plugins/phaser-casual-game-factory/templates/ui-reskin/compare.html +235 -0
- package/plugins/phaser-casual-game-factory/tests/README.md +29 -0
- package/plugins/phaser-casual-game-factory/tests/condition.test.ts +92 -0
- package/plugins/phaser-casual-game-factory/tests/daily-login-reward.test.ts +45 -0
- package/plugins/phaser-casual-game-factory/tests/daily-login.test.ts +73 -0
- package/plugins/phaser-casual-game-factory/tests/economy.test.ts +258 -0
- package/plugins/phaser-casual-game-factory/tests/entitlement.test.ts +18 -0
- package/plugins/phaser-casual-game-factory/tests/leveling.test.ts +158 -0
- package/plugins/phaser-casual-game-factory/tests/loading-view.test.ts +39 -0
- package/plugins/phaser-casual-game-factory/tests/time.test.ts +60 -0
|
@@ -0,0 +1,1647 @@
|
|
|
1
|
+
"""Test cho imglib. KHÔNG dùng pytest (môi trường không có).
|
|
2
|
+
Chạy: python test_imglib.py
|
|
3
|
+
"""
|
|
4
|
+
import sys
|
|
5
|
+
import traceback
|
|
6
|
+
from PIL import Image, ImageDraw, ImageFilter
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
import imglib as L
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _solid(size, rgba):
|
|
13
|
+
return Image.new("RGBA", size, rgba)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_hex_roundtrip():
|
|
17
|
+
assert L.hex_to_rgb("#00FF00") == (0, 255, 0)
|
|
18
|
+
assert L.hex_to_rgb("00ff00") == (0, 255, 0)
|
|
19
|
+
assert L.rgb_to_hex((0, 255, 0)) == "#00FF00"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_color_dist_zero_for_same_color():
|
|
23
|
+
assert L.color_dist((10, 20, 30), (10, 20, 30)) == 0.0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_color_dist_green_vs_white_is_large():
|
|
27
|
+
assert L.color_dist((0, 255, 0), (255, 255, 255)) > 400
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_dist_map_agrees_with_color_dist():
|
|
31
|
+
"""_dist_map() là bản vector hoá của color_dist() — mọi ngưỡng trong hệ thống
|
|
32
|
+
(t_low/t_high của chroma_key, BAD_BORDER_DIST, GREEN_SAFE_THRESHOLD/MIN_KEY_MARGIN)
|
|
33
|
+
đều giả định hai hàm cho ra CÙNG một con số trên cùng một cặp màu. Không có test nào
|
|
34
|
+
khoá điều đó lại trước đây — một thay đổi vô tình làm lệch một trong hai hàm sẽ khiến
|
|
35
|
+
mọi ngưỡng hiệu chỉnh bằng color_dist() không còn khớp với dữ liệu _dist_map() thực sự
|
|
36
|
+
dùng để quyết định alpha/impurity, mà không test nào bắt được.
|
|
37
|
+
"""
|
|
38
|
+
key = (0, 255, 0)
|
|
39
|
+
samples = [
|
|
40
|
+
(0, 255, 0), (255, 255, 255), (200, 30, 40), (128, 190, 128),
|
|
41
|
+
(255, 0, 255), (0, 0, 0), (10, 250, 10), (140, 70, 50),
|
|
42
|
+
]
|
|
43
|
+
for c in samples:
|
|
44
|
+
scalar = L.color_dist(c, key)
|
|
45
|
+
vec = L._dist_map(np.array([[c]], dtype=np.uint8), key)[0, 0]
|
|
46
|
+
assert abs(scalar - vec) < 1e-6, f"color_dist={scalar} != _dist_map={vec} cho {c}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_extract_palette_finds_dominant_color():
|
|
50
|
+
img = _solid((20, 20), (200, 30, 40, 255))
|
|
51
|
+
pal = L.extract_palette(img, n=4)
|
|
52
|
+
assert pal[0][0] == "#C81E28"
|
|
53
|
+
assert pal[0][1] > 0.99
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_extract_palette_ignores_transparent_pixels():
|
|
57
|
+
img = Image.new("RGBA", (20, 20), (0, 255, 0, 0)) # xanh lá nhưng TRONG SUỐT
|
|
58
|
+
img.paste((200, 30, 40, 255), (5, 5, 15, 15))
|
|
59
|
+
hexes = [h for h, _ in L.extract_palette(img, n=4)]
|
|
60
|
+
assert "#00FF00" not in hexes
|
|
61
|
+
assert "#C81E28" in hexes
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_extract_palette_empty_for_fully_transparent():
|
|
65
|
+
assert L.extract_palette(Image.new("RGBA", (8, 8), (0, 0, 0, 0))) == []
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_pick_key_prefers_green_when_asset_has_no_green():
|
|
69
|
+
img = _solid((16, 16), (200, 30, 40, 255)) # đỏ
|
|
70
|
+
key, margin = L.pick_key_color(img)
|
|
71
|
+
assert key == "#00FF00"
|
|
72
|
+
assert margin > L.GREEN_SAFE_THRESHOLD
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_pick_key_avoids_green_when_asset_is_green():
|
|
76
|
+
img = _solid((16, 16), (0, 200, 0, 255)) # xanh lá đậm — sát màu key
|
|
77
|
+
key, _ = L.pick_key_color(img)
|
|
78
|
+
assert key != "#00FF00"
|
|
79
|
+
assert key in L.KEY_CANDIDATES
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_pick_key_falls_back_to_green_when_image_empty():
|
|
83
|
+
key, _ = L.pick_key_color(Image.new("RGBA", (8, 8), (0, 0, 0, 0)))
|
|
84
|
+
assert key == "#00FF00"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_pick_key_avoids_green_even_when_green_has_largest_raw_margin():
|
|
88
|
+
"""Regression test for Finding 1: green must be excluded from fallback selection.
|
|
89
|
+
|
|
90
|
+
Multi-hue asset where extracted palette has colors near magenta, cyan, and blue
|
|
91
|
+
(making those candidates unsafe with small margins) plus dark green (making green
|
|
92
|
+
unsafe with margin ~110 < GREEN_SAFE_THRESHOLD). Green has largest margin among
|
|
93
|
+
candidates, but fallback must exclude it and pick a non-green candidate.
|
|
94
|
+
"""
|
|
95
|
+
img = Image.new("RGBA", (20, 20), (0, 200, 0, 255)) # dark green base
|
|
96
|
+
img.paste((255, 0, 200, 255), (0, 0, 5, 20)) # magenta-ish
|
|
97
|
+
img.paste((0, 255, 200, 255), (5, 0, 10, 20)) # cyan-ish
|
|
98
|
+
img.paste((0, 0, 255, 255), (10, 0, 15, 20)) # blue
|
|
99
|
+
|
|
100
|
+
key, margin = L.pick_key_color(img)
|
|
101
|
+
# The function must NOT return green, even though green margin (~110) is largest.
|
|
102
|
+
# The fallback must exclude green and pick among remaining candidates.
|
|
103
|
+
assert key != "#00FF00", f"Should have excluded green, but got {key} (margin {margin})"
|
|
104
|
+
assert key in L.KEY_CANDIDATES
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_pick_key_rejects_green_with_marginal_but_previously_accepted_margin():
|
|
108
|
+
"""Regression cho Finding I1: asset màu (0,230,70) có margin ~131 tới #00FF00.
|
|
109
|
+
|
|
110
|
+
Dưới ngưỡng CŨ (GREEN_SAFE_THRESHOLD=120), margin 131 được coi là "an toàn" và
|
|
111
|
+
green được chọn — nhưng chroma_key()'s t_high mặc định = 170: alpha chỉ đạt 255 ở
|
|
112
|
+
khoảng cách >= 170. Ở margin 131 (< t_high), pixel màu (0,230,70) của CHÍNH chủ thể
|
|
113
|
+
chỉ đạt alpha ~169 (đo thực tế) — chủ thể bị bào mờ dù `plan` báo "an toàn". Với
|
|
114
|
+
MIN_KEY_MARGIN=190 (> t_high), margin 131 giờ bị từ chối, ép fallback sang key khác.
|
|
115
|
+
"""
|
|
116
|
+
img = Image.new("RGBA", (16, 16), (0, 230, 70, 255))
|
|
117
|
+
key, margin = L.pick_key_color(img)
|
|
118
|
+
assert key != "#00FF00", f"margin {margin:.1f} phải bị từ chối là không an toàn cho xanh lá"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_pick_key_avoid_folds_extra_colors_into_scoring():
|
|
122
|
+
"""`avoid` (dùng bởi CLI `plan --avoid`) phải gộp được màu NGOÀI palette nguồn vào
|
|
123
|
+
chấm điểm — cần cho Finding I1's phần "structural": chroma key chạy trên ẢNH ĐÃ
|
|
124
|
+
RESTYLE, có palette MỚI (style preset) khác hẳn palette của asset gốc mà hàm này tự
|
|
125
|
+
đọc. Asset gốc ở đây thuần đỏ (không hề có xanh lá) nên mặc định sẽ chọn xanh lá;
|
|
126
|
+
truyền một màu xanh lá neon vào `avoid` (giả lập palette style preset) phải đẩy lựa
|
|
127
|
+
chọn ra khỏi xanh lá.
|
|
128
|
+
"""
|
|
129
|
+
img = _solid((16, 16), (200, 30, 40, 255)) # đỏ, không hề có xanh lá
|
|
130
|
+
key_default, _ = L.pick_key_color(img)
|
|
131
|
+
assert key_default == "#00FF00"
|
|
132
|
+
|
|
133
|
+
key_avoided, margin_avoided = L.pick_key_color(img, avoid=[(10, 250, 10)])
|
|
134
|
+
assert key_avoided != "#00FF00", "avoid màu gần key phải đẩy lựa chọn ra khỏi green"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _subject_on_key(size=(64, 64), key=(0, 255, 0), subject=(200, 30, 40), box=None):
|
|
138
|
+
"""Ảnh giả lập output Gemini: khối chủ thể đặc, đặt trên nền key phẳng.
|
|
139
|
+
|
|
140
|
+
`box` cho phép chỉnh TỈ LỆ chủ thể — cần để test riêng ca cùng tỉ lệ với bbox gốc
|
|
141
|
+
và ca lệch tỉ lệ.
|
|
142
|
+
"""
|
|
143
|
+
img = Image.new("RGB", size, key)
|
|
144
|
+
if box is None:
|
|
145
|
+
w, h = size
|
|
146
|
+
box = (w // 4, h // 4, w * 3 // 4, h * 3 // 4)
|
|
147
|
+
img.paste(subject, box)
|
|
148
|
+
return img
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_chroma_key_makes_background_transparent():
|
|
152
|
+
keyed = L.chroma_key(_subject_on_key(), "#00FF00")
|
|
153
|
+
assert keyed.mode == "RGBA"
|
|
154
|
+
assert keyed.getpixel((2, 2))[3] == 0 # góc = nền = trong suốt
|
|
155
|
+
assert keyed.getpixel((32, 32))[3] == 255 # tâm = chủ thể = đục
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def test_chroma_key_leaves_no_key_coloured_pixels():
|
|
159
|
+
keyed = L.despill(L.chroma_key(_subject_on_key(), "#00FF00"), "#00FF00")
|
|
160
|
+
arr = np.asarray(keyed)
|
|
161
|
+
visible = arr[arr[..., 3] > L.ALPHA_FLOOR][:, :3]
|
|
162
|
+
worst = min(L.color_dist(px, (0, 255, 0)) for px in visible)
|
|
163
|
+
assert worst > 40, f"còn pixel ám màu key, khoảng cách gần nhất = {worst:.1f}"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_chroma_key_produces_soft_edge():
|
|
167
|
+
"""Ngưỡng mềm phải cho ra alpha trung gian trên một dải blend biết trước.
|
|
168
|
+
|
|
169
|
+
KHÔNG dựng mép bằng cách resize phóng to rồi thu nhỏ (LANCZOS) và hy vọng
|
|
170
|
+
bộ resample để lại pixel blend rơi đúng vào khoảng (t_low, t_high): khoảng
|
|
171
|
+
cách redmean giữa xanh lá key và màu đỏ chủ thể ở đây rất lớn (~550), nên
|
|
172
|
+
một pixel do resample tạo ra bão hoà về alpha 0 hoặc 255 chỉ sau một phần
|
|
173
|
+
nhỏ tỉ lệ pha trộn — test kiểu đó thực chất đang kiểm tra bộ resampler chứ
|
|
174
|
+
không kiểm tra chroma_key. Thay vào đó, dựng TRỰC TIẾP một dải cột là blend
|
|
175
|
+
tuyến tính ĐÃ BIẾT giữa màu key và màu chủ thể (p chạy từ 0.0 đến 1.0), rồi
|
|
176
|
+
kiểm tra alpha có giá trị nằm strictly giữa 0 và 255 hay không — chứng
|
|
177
|
+
minh ramp smoothstep thực sự tồn tại ở ngưỡng đã khai báo, vì một ngưỡng
|
|
178
|
+
cứng nhị phân sẽ phá hỏng mép anti-alias mà Gemini vẽ ra.
|
|
179
|
+
"""
|
|
180
|
+
key = (0, 255, 0)
|
|
181
|
+
subject = (200, 30, 40)
|
|
182
|
+
width, height = 101, 4
|
|
183
|
+
|
|
184
|
+
p = np.linspace(0.0, 1.0, width)
|
|
185
|
+
key_arr = np.array(key, dtype=np.float64)
|
|
186
|
+
subj_arr = np.array(subject, dtype=np.float64)
|
|
187
|
+
row = np.round(
|
|
188
|
+
(1 - p)[:, None] * key_arr[None, :] + p[:, None] * subj_arr[None, :]
|
|
189
|
+
).astype(np.uint8)
|
|
190
|
+
arr = np.tile(row[None, :, :], (height, 1, 1))
|
|
191
|
+
img = Image.fromarray(arr, "RGB")
|
|
192
|
+
|
|
193
|
+
keyed = L.chroma_key(img, "#00FF00")
|
|
194
|
+
alphas = np.asarray(keyed)[..., 3].ravel().tolist()
|
|
195
|
+
assert any(0 < a < 255 for a in alphas), "không có alpha trung gian -> mép sẽ răng cưa"
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_despill_removes_green_fringe():
|
|
199
|
+
"""Pixel xám ám xanh (128,190,128), alpha=0 (nền/mép trong suốt hoàn toàn) phải bị
|
|
200
|
+
kéo kênh G về mức của R/B.
|
|
201
|
+
|
|
202
|
+
alpha=0 -> weight=(1-0/255)*1.0=1.0 -> đúng công thức kẹp CŨ (không suy giảm theo
|
|
203
|
+
alpha) — đây là ca "weight tối đa", dùng để pin phần lõi toán học của công thức kẹp
|
|
204
|
+
vẫn hoạt động đúng sau khi Finding C1 nhân thêm hệ số weight vào.
|
|
205
|
+
"""
|
|
206
|
+
img = Image.new("RGBA", (4, 4), (128, 190, 128, 0))
|
|
207
|
+
out = L.despill(img, "#00FF00")
|
|
208
|
+
r, g, b, a = out.getpixel((1, 1))
|
|
209
|
+
assert g <= 130, f"green chưa được khử: {g}"
|
|
210
|
+
assert (r, b) == (128, 128), "kênh không phải key bị đụng vào"
|
|
211
|
+
assert a == 0, "despill không được đụng vào alpha"
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def test_despill_magenta_key_touches_r_and_b_only():
|
|
215
|
+
"""Rewrite cho Finding C1 (CRITICAL). Bản CŨ của test này assert r<=105 và b<=105
|
|
216
|
+
cho một pixel ĐỤC HOÀN TOÀN (alpha=255) — tức là nó khẳng định phần bị phá màu là
|
|
217
|
+
ĐÚNG, chính là bug: despill từng kẹp kênh trên MỌI pixel bất kể alpha, ăn cả màu hợp
|
|
218
|
+
lệ của chủ thể. Bản mới assert đúng hành vi: một pixel ĐỤC (chủ thể thật, không có
|
|
219
|
+
mép để mà despill) phải được giữ NGUYÊN xi.
|
|
220
|
+
"""
|
|
221
|
+
img = Image.new("RGBA", (4, 4), (200, 100, 200, 255))
|
|
222
|
+
r, g, b, a = L.despill(img, "#FF00FF").getpixel((1, 1))
|
|
223
|
+
assert (r, g, b, a) == (200, 100, 200, 255), (
|
|
224
|
+
f"pixel đục (alpha=255) không được đụng vào, ra {(r, g, b, a)}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def test_despill_never_touches_opaque_subject_pixels():
|
|
229
|
+
"""Test hồi quy cho Finding C1 (CRITICAL): despill() từng là một phép CRUSH KÊNH
|
|
230
|
+
TOÀN CỤC áp lên MỌI pixel bất kể alpha, không phải sửa mép anti-alias. Đo được trên
|
|
231
|
+
code cũ (trước fix):
|
|
232
|
+
key=#00FF00, chủ thể vàng #FFD700 (255,215,0) -> ra (255,128,0) cam
|
|
233
|
+
key=#00FF00, chủ thể cỏ (110,190,80) -> ra (110,95,80) bùn
|
|
234
|
+
key=#FF00FF, chủ thể đỏ (200,30,40) -> ra (30,30,30) gần đen
|
|
235
|
+
key=#FF00FF, chủ thể hồng (230,90,200) -> ra (90,90,90) xám
|
|
236
|
+
|
|
237
|
+
Mỗi pixel dưới đây có alpha=255 (chủ thể đục hoàn toàn, không phải mép) — với công
|
|
238
|
+
thức weight=(1-alpha/255)*strength, weight=0, nên RGB PHẢI ra nguyên vẹn, không đổi
|
|
239
|
+
một chút nào. Nếu test này FAIL, ai đó đã revert phần nhân weight trong despill().
|
|
240
|
+
"""
|
|
241
|
+
cases = [
|
|
242
|
+
("#00FF00", (255, 215, 0)), # vàng gold trên key xanh lá
|
|
243
|
+
("#00FF00", (110, 190, 80)), # cỏ trên key xanh lá
|
|
244
|
+
("#FF00FF", (200, 30, 40)), # đỏ trên key hồng/magenta
|
|
245
|
+
("#FF00FF", (230, 90, 200)), # hồng trên key hồng/magenta
|
|
246
|
+
]
|
|
247
|
+
for key_hex, subject in cases:
|
|
248
|
+
img = Image.new("RGBA", (4, 4), (*subject, 255))
|
|
249
|
+
out = L.despill(img, key_hex)
|
|
250
|
+
got = out.getpixel((1, 1))
|
|
251
|
+
assert got == (*subject, 255), (
|
|
252
|
+
f"key={key_hex} subject={subject}: pixel ĐỤC (alpha=255) bị đổi màu -> {got} "
|
|
253
|
+
"— đây chính là Finding C1"
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def test_despill_still_removes_edge_fringe():
|
|
258
|
+
"""Pixel MÉP bán trong suốt (alpha=128, giữa nền và chủ thể) mang ám màu key VẪN
|
|
259
|
+
phải được sửa — chỉ chủ thể ĐỤC mới được miễn, không phải toàn bộ ảnh.
|
|
260
|
+
|
|
261
|
+
weight = (1 - 128/255) * 1.0 ~= 0.498 -> sửa MỘT PHẦN, không sửa full (khác test
|
|
262
|
+
test_despill_removes_green_fringe dùng alpha=0 -> weight=1.0 sửa full).
|
|
263
|
+
"""
|
|
264
|
+
img = Image.new("RGBA", (4, 4), (128, 190, 128, 128))
|
|
265
|
+
out = L.despill(img, "#00FF00")
|
|
266
|
+
r, g, b, a = out.getpixel((1, 1))
|
|
267
|
+
assert a == 128, "despill không được đụng vào alpha"
|
|
268
|
+
assert (r, b) == (128, 128), "kênh không phải key bị đụng vào"
|
|
269
|
+
assert g < 190, f"mép bán trong suốt vẫn phải được sửa ít nhiều: g={g}"
|
|
270
|
+
assert g > 128, f"weight<1 nên KHÔNG được sửa full về limit: g={g}"
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_alpha_coverage():
|
|
274
|
+
assert L.alpha_coverage(Image.new("RGBA", (10, 10), (0, 0, 0, 255))) == 1.0
|
|
275
|
+
assert L.alpha_coverage(Image.new("RGBA", (10, 10), (0, 0, 0, 0))) == 0.0
|
|
276
|
+
half = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
|
|
277
|
+
half.paste((9, 9, 9, 255), (0, 0, 10, 5))
|
|
278
|
+
assert abs(L.alpha_coverage(half) - 0.5) < 1e-9
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _fake_src(canvas=(144, 144), box=(20, 30, 120, 110)):
|
|
282
|
+
"""Asset 'gốc' giả: canvas cố định, nội dung nằm LỆCH TÂM trong bbox biết trước."""
|
|
283
|
+
img = Image.new("RGBA", canvas, (0, 0, 0, 0))
|
|
284
|
+
img.paste((10, 20, 200, 255), box)
|
|
285
|
+
return img
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def test_content_bbox_finds_content():
|
|
289
|
+
assert L.content_bbox(_fake_src()) == (20, 30, 120, 110)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def test_content_bbox_none_when_empty():
|
|
293
|
+
assert L.content_bbox(Image.new("RGBA", (8, 8), (0, 0, 0, 0))) is None
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def test_hole_ratio_zero_for_solid_subject():
|
|
297
|
+
"""Chủ thể đặc, không lỗ -> hole_ratio phải bằng 0."""
|
|
298
|
+
img = Image.new("RGBA", (100, 100), (0, 0, 0, 0))
|
|
299
|
+
img.paste((200, 30, 40, 255), (10, 10, 90, 90))
|
|
300
|
+
assert L.hole_ratio(img) == 0.0
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def test_hole_ratio_flags_interior_hole():
|
|
304
|
+
"""Regression cho Finding I2: một 'viên ngọc' màu sát key bị chroma-key khoét thành
|
|
305
|
+
lỗ trong suốt GIỮA chủ thể — coverage (toàn cục), solid_ratio (trên nội dung) và
|
|
306
|
+
border_impurity (vành ngoài) đều KHÔNG nhìn vào giữa bbox nên không thấy gì, báo
|
|
307
|
+
'ok' dù asset có một lỗ thủng giữa thân. hole_ratio() phải bắt được ca này.
|
|
308
|
+
"""
|
|
309
|
+
img = Image.new("RGBA", (100, 100), (0, 0, 0, 0))
|
|
310
|
+
img.paste((200, 30, 40, 255), (10, 10, 90, 90)) # chủ thể đặc 80x80 = 6400px
|
|
311
|
+
img.paste((0, 0, 0, 0), (35, 35, 65, 65)) # lỗ thủng giữa: 30x30=900/6400=14.1%
|
|
312
|
+
ratio = L.hole_ratio(img)
|
|
313
|
+
assert ratio > L.BAD_HOLE_RATIO, f"lỗ thủng giữa chủ thể phải vượt ngưỡng: {ratio}"
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def test_hole_ratio_tolerates_legit_hollow_shape():
|
|
317
|
+
"""Art hollow HỢP LỆ (nhẫn, chữ O, khung ảnh, donut) không được báo bad_holes — chỉ
|
|
318
|
+
một lỗ khoét CHIẾM ĐA SỐ diện tích giữa mới đáng ngờ. Dựng một hình 'nhẫn' có lỗ giữa
|
|
319
|
+
chiếm tỉ lệ vừa phải (6.25%, dưới BAD_HOLE_RATIO=10%) để pin ranh giới trade-off này —
|
|
320
|
+
xem docstring hole_ratio() về việc ngưỡng này KHÔNG hoàn hảo với hollow rất lớn.
|
|
321
|
+
"""
|
|
322
|
+
img = Image.new("RGBA", (100, 100), (0, 0, 0, 0))
|
|
323
|
+
img.paste((200, 30, 40, 255), (10, 10, 90, 90)) # vành nhẫn 80x80 = 6400px
|
|
324
|
+
img.paste((0, 0, 0, 0), (40, 40, 60, 60)) # lỗ giữa nhẫn: 20x20=400/6400=6.25%
|
|
325
|
+
ratio = L.hole_ratio(img)
|
|
326
|
+
assert ratio < L.BAD_HOLE_RATIO, f"nhẫn mỏng hợp lệ không được vượt ngưỡng: {ratio}"
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def test_resize_keeps_edge_colour_clean():
|
|
330
|
+
"""TEST GIẢ ĐỊNH: pin hành vi của Pillow mà pipeline đang DỰA VÀO.
|
|
331
|
+
|
|
332
|
+
Pillow tự premultiply bên trong resize(): RGBA -> "RGBa" -> resize -> RGBA
|
|
333
|
+
(Image.py). Nhờ vậy RGB của pixel trong suốt (ở đây là màu key xanh lá còn sót)
|
|
334
|
+
KHÔNG rỉ vào pixel mép. Ta gọi thẳng resize() và dựa vào đúng tính chất này.
|
|
335
|
+
|
|
336
|
+
KHÔNG được premultiply BẰNG TAY trước khi gọi resize(): Pillow sẽ nhân lần thứ hai.
|
|
337
|
+
Ở alpha thấp, giá trị premultiplied bị lượng tử hoá về uint8 (alpha=2: RGB 255 -> 2),
|
|
338
|
+
Pillow nhân tiếp (2 * 2/255 -> 0.02 -> làm tròn thành 0), và un-premultiply không
|
|
339
|
+
cứu lại được. Đo thực tế trên dải alpha 2..40: R 255 -> R min = 0, R mean 177.8.
|
|
340
|
+
Tức là premultiply thủ công PHÁ HỎNG đúng những mép anti-alias mảnh mà dự án này
|
|
341
|
+
quan tâm nhất (line-art, râu mèo). Vì thế resize_premul() đã bị xoá.
|
|
342
|
+
|
|
343
|
+
HÌNH HỌC PHẢI LỆCH LƯỚI (65x65, box (17,15,47,51) -> 31x31). Với hình học chia chẵn
|
|
344
|
+
đúng 2x và mép trùng lưới (64x64, box (16,16,48,48) -> 32x32), kernel LANCZOS nhảy
|
|
345
|
+
alpha thẳng từ ~14 lên ~228 trong đúng một pixel: KHÔNG có mẫu nào rơi vào dải alpha
|
|
346
|
+
một phần, test không chạm được vào mép và trở thành vô nghĩa. Guard `len(edge) > 0`
|
|
347
|
+
bên dưới là để chặn ca đó.
|
|
348
|
+
"""
|
|
349
|
+
# Pixel trong suốt mang màu KEY (xanh lá) — đúng ca thật sau khi chroma key.
|
|
350
|
+
img = Image.new("RGBA", (65, 65), (0, 255, 0, 0))
|
|
351
|
+
img.paste((255, 0, 0, 255), (17, 15, 47, 51))
|
|
352
|
+
small = img.resize((31, 31), Image.LANCZOS)
|
|
353
|
+
arr = np.asarray(small).astype(int)
|
|
354
|
+
edge = arr[(arr[..., 3] > 40) & (arr[..., 3] < 220)]
|
|
355
|
+
assert len(edge) > 0, "test vô nghĩa nếu không có pixel mép"
|
|
356
|
+
assert edge[:, 0].min() > 180, f"mép bị ngả đen, R nhỏ nhất = {edge[:, 0].min()}"
|
|
357
|
+
# Đây mới là assertion sẽ nổ nếu Pillow thôi không premultiply nội bộ nữa:
|
|
358
|
+
assert edge[:, 1].max() < 40, f"mép bị rỉ màu key, G lớn nhất = {edge[:, 1].max()}"
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def test_postprocess_matches_source_geometry():
|
|
362
|
+
"""Bám gốc, chủ thể CÙNG tỉ lệ với bbox gốc -> output TRÙNG size và TRÙNG bbox."""
|
|
363
|
+
src = _fake_src() # bbox (20,30,120,110) = 100x80 (5:4)
|
|
364
|
+
gen = _subject_on_key(size=(256, 256), box=(28, 48, 228, 208)) # 200x160 = 5:4
|
|
365
|
+
out, report = L.postprocess(gen, "#00FF00", src=src)
|
|
366
|
+
|
|
367
|
+
assert report["status"] == "ok"
|
|
368
|
+
assert out.size == src.size == (144, 144)
|
|
369
|
+
sb, ob = L.content_bbox(src), L.content_bbox(out)
|
|
370
|
+
for i in range(4):
|
|
371
|
+
assert abs(sb[i] - ob[i]) <= 1, f"bbox lệch: gốc={sb} out={ob}"
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def test_postprocess_contains_and_centres_when_aspect_differs():
|
|
375
|
+
"""Chủ thể VUÔNG, bbox gốc chữ nhật -> KHÔNG bóp méo.
|
|
376
|
+
|
|
377
|
+
Hợp đồng thật là 'contain + căn giữa trong bbox gốc', không phải 'lấp kín bbox gốc'.
|
|
378
|
+
Thà chừa lề còn hơn kéo méo asset.
|
|
379
|
+
"""
|
|
380
|
+
src = _fake_src() # bbox 100x80
|
|
381
|
+
gen = _subject_on_key(size=(256, 256)) # chủ thể vuông 128x128
|
|
382
|
+
out, _ = L.postprocess(gen, "#00FF00", src=src)
|
|
383
|
+
|
|
384
|
+
sb, ob = (20, 30, 120, 110), L.content_bbox(out)
|
|
385
|
+
assert ob[0] >= sb[0] and ob[1] >= sb[1] and ob[2] <= sb[2] and ob[3] <= sb[3], \
|
|
386
|
+
f"tràn ra ngoài bbox gốc: {ob}"
|
|
387
|
+
assert ob[3] - ob[1] == 80, "chiều bị ràng buộc (cao) phải lấp đầy bbox gốc"
|
|
388
|
+
left, right = ob[0] - sb[0], sb[2] - ob[2]
|
|
389
|
+
assert abs(left - right) <= 1, f"không căn giữa: lề trái={left} lề phải={right}"
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def test_postprocess_handles_bbox_touching_canvas_edge():
|
|
393
|
+
"""Ca thật: cell_base.png có bbox phủ KÍN canvas. Không được crash / lệch."""
|
|
394
|
+
src = _fake_src(canvas=(249, 249), box=(0, 0, 249, 249))
|
|
395
|
+
out, report = L.postprocess(_subject_on_key(size=(256, 256)), "#00FF00", src=src)
|
|
396
|
+
assert report["status"] == "ok"
|
|
397
|
+
assert out.size == (249, 249)
|
|
398
|
+
assert L.content_bbox(out) == (0, 0, 249, 249)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def test_postprocess_non_square_source():
|
|
402
|
+
"""Asset thật hay không vuông (346x78). Phải giữ đúng, không ép về vuông."""
|
|
403
|
+
src = _fake_src(canvas=(346, 78), box=(2, 0, 344, 78))
|
|
404
|
+
out, _ = L.postprocess(_subject_on_key(size=(256, 256)), "#00FF00", src=src)
|
|
405
|
+
assert out.size == (346, 78)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def test_postprocess_explicit_size_overrides_source():
|
|
409
|
+
out, report = L.postprocess(
|
|
410
|
+
_subject_on_key(size=(256, 256)), "#00FF00", src=_fake_src(), size=(64, 64)
|
|
411
|
+
)
|
|
412
|
+
assert out.size == (64, 64)
|
|
413
|
+
assert report["size"] == (64, 64)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def test_postprocess_flags_unkeyed_background():
|
|
417
|
+
"""Gemini vẽ nền KHÔNG phải màu key -> không tách được -> phải báo bad_background."""
|
|
418
|
+
gen = Image.new("RGB", (64, 64), (120, 120, 130)) # nền xám, không có xanh lá
|
|
419
|
+
out, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
420
|
+
assert report["status"] == "bad_background"
|
|
421
|
+
assert report["coverage"] > L.BAD_HIGH
|
|
422
|
+
# bad_background vẫn phải TRẢ ẢNH — người duyệt cần thấy defect trong contact sheet,
|
|
423
|
+
# chỉ bad_subject mới được trả None.
|
|
424
|
+
assert out is not None
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def test_postprocess_flags_eaten_subject():
|
|
428
|
+
"""Chủ thể trùng màu key -> bị ăn thủng -> phải báo bad_subject, không trả ảnh rác."""
|
|
429
|
+
gen = Image.new("RGB", (64, 64), (0, 255, 0)) # toàn màu key
|
|
430
|
+
out, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
431
|
+
assert report["status"] == "bad_subject"
|
|
432
|
+
assert out is None
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def test_postprocess_sparse_but_solid_glyph_is_not_bad_subject():
|
|
436
|
+
"""Regression cho Finding I3: coverage thấp một mình KHÔNG còn nghĩa là 'hỏng'.
|
|
437
|
+
|
|
438
|
+
Trước fix, một icon/line-art nhỏ như nút X 12px nét (đo thực tế trên canvas ~1024^2:
|
|
439
|
+
coverage=0.0161 < BAD_LOW=0.02, solid_ratio=1.0, border_impurity=0.0 — một bản sinh
|
|
440
|
+
HOÀN HẢO) bị `postprocess` vứt bỏ (trả None) vì coverage thấp bị đánh đồng với
|
|
441
|
+
'hỏng', và SKILL.md khuyên 'sinh lại với màu key khác' — vô nghĩa, màu key chưa từng
|
|
442
|
+
là vấn đề ở đây. Không có `--force`, icon/glyph mảnh đơn giản KHÔNG dùng được qua tool.
|
|
443
|
+
|
|
444
|
+
Dựng glyph chữ X mảnh, đặc (numpy trực tiếp, không qua ImageDraw, để kiểm soát chính
|
|
445
|
+
xác tỉ lệ diện tích thay vì phụ thuộc anti-alias của bộ vẽ) — coverage đo được ở đây
|
|
446
|
+
(~0.0078 trên canvas 256x256) cùng bậc với ca thật của reviewer, dưới BAD_LOW.
|
|
447
|
+
"""
|
|
448
|
+
n = 256
|
|
449
|
+
key = (0, 255, 0)
|
|
450
|
+
subject = (20, 20, 20)
|
|
451
|
+
yy, xx = np.mgrid[0:n, 0:n]
|
|
452
|
+
mask = (np.abs(xx - yy) == 0) | (np.abs(xx + yy - (n - 1)) == 0)
|
|
453
|
+
arr = np.zeros((n, n, 3), dtype=np.uint8)
|
|
454
|
+
arr[...] = key
|
|
455
|
+
arr[mask] = subject
|
|
456
|
+
gen = Image.fromarray(arr, "RGB")
|
|
457
|
+
|
|
458
|
+
out, report = L.postprocess(gen, "#00FF00", size=(n, n))
|
|
459
|
+
|
|
460
|
+
assert report["coverage"] < L.BAD_LOW, f"glyph phải nhỏ hơn BAD_LOW: {report['coverage']}"
|
|
461
|
+
assert report["solid_ratio"] == 1.0, "glyph không AA -> phải đục hoàn toàn"
|
|
462
|
+
assert out is not None, "chủ thể nhỏ nhưng ĐẶC không được vứt bỏ — người duyệt cần thấy nó"
|
|
463
|
+
assert "bad_subject" not in report["flags"], report["flags"]
|
|
464
|
+
assert "sparse" in report["flags"], report["flags"]
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def test_postprocess_flags_interior_hole():
|
|
468
|
+
"""Tái hiện repro của reviewer cho Finding I2: chủ thể đỏ-nâu với một 'viên ngọc' màu
|
|
469
|
+
sát key nằm GIỮA thân bị chroma-key khoét thành lỗ trong suốt. Trước fix,
|
|
470
|
+
coverage/solid_ratio/border_impurity đều 'sạch' -> status: ok, flags: [] dù output có
|
|
471
|
+
alpha=0 ngay giữa chủ thể. Sau fix: report luôn có `hole_ratio`, và `bad_holes` phải
|
|
472
|
+
xuất hiện vì lỗ đủ lớn (16% diện tích bbox, trên BAD_HOLE_RATIO=10%) — nhưng ảnh vẫn
|
|
473
|
+
được ghi ra (bad_holes chỉ tham khảo, không phải gate cứng).
|
|
474
|
+
"""
|
|
475
|
+
size = (120, 120)
|
|
476
|
+
key = (0, 255, 0)
|
|
477
|
+
subject = (140, 70, 50) # đỏ-nâu, cách key rất xa -> đục hoàn toàn
|
|
478
|
+
gem = (20, 235, 10) # gần key -> bị chroma-key khoét thủng hoàn toàn
|
|
479
|
+
|
|
480
|
+
arr = np.full((size[1], size[0], 3), key, dtype=np.uint8)
|
|
481
|
+
arr[10:110, 10:110, :] = subject # chủ thể đặc 100x100 = 10000px
|
|
482
|
+
arr[35:75, 35:75, :] = gem # viên ngọc giữa: 40x40=1600/10000=16%
|
|
483
|
+
gen = Image.fromarray(arr, "RGB")
|
|
484
|
+
|
|
485
|
+
out, report = L.postprocess(gen, "#00FF00", size=size)
|
|
486
|
+
|
|
487
|
+
assert out is not None, "bad_holes chỉ tham khảo — vẫn phải ghi ảnh ra"
|
|
488
|
+
assert report["hole_ratio"] > L.BAD_HOLE_RATIO, report["hole_ratio"]
|
|
489
|
+
assert "bad_holes" in report["flags"], report["flags"]
|
|
490
|
+
assert "bad_subject" not in report["flags"], report["flags"]
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def test_solid_ratio_full_for_opaque_subject():
|
|
494
|
+
img = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
|
|
495
|
+
img.paste((10, 20, 30, 255), (2, 2, 8, 8))
|
|
496
|
+
assert L.solid_ratio(img) == 1.0
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def test_solid_ratio_zero_for_ghost_subject():
|
|
500
|
+
"""Chủ thể chỉ còn alpha 40 -> có mặt nhưng KHÔNG đục -> solid_ratio phải = 0."""
|
|
501
|
+
img = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
|
|
502
|
+
img.paste((10, 20, 30, 40), (2, 2, 8, 8))
|
|
503
|
+
assert L.alpha_coverage(img) > 0.3 # coverage vẫn "bình thường"...
|
|
504
|
+
assert L.solid_ratio(img) == 0.0 # ...nhưng không đục chút nào
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def test_solid_ratio_zero_for_empty_image():
|
|
508
|
+
assert L.solid_ratio(Image.new("RGBA", (8, 8), (0, 0, 0, 0))) == 0.0
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def test_postprocess_flags_translucent_ghost():
|
|
512
|
+
"""Màu key sát màu chủ thể -> chủ thể bị bào thành bóng ma.
|
|
513
|
+
|
|
514
|
+
Đây là ca mà coverage KHÔNG bắt được: pixel vẫn tồn tại nên coverage nằm trong dải
|
|
515
|
+
"ok", nhưng chúng gần như trong suốt. Không có solid_ratio thì asset mờ tịt sẽ lọt lưới.
|
|
516
|
+
"""
|
|
517
|
+
# redmean nhân kênh G với hệ số 4, nên chỉ lệch G thì d = 2*|dg|.
|
|
518
|
+
# Chủ thể (0, 207, 0): d = 2*48 = 96 -> nằm giữa t_low=70 và t_high=170
|
|
519
|
+
# -> smoothstep cho alpha ~43. Chủ thể "có mặt" nhưng gần như trong suốt.
|
|
520
|
+
gen = _subject_on_key(size=(256, 256), subject=(0, 207, 0))
|
|
521
|
+
out, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
522
|
+
|
|
523
|
+
assert L.BAD_LOW < report["coverage"] < L.BAD_HIGH, "coverage phải nằm trong dải 'ok'"
|
|
524
|
+
assert report["solid_ratio"] < L.BAD_SOLID_RATIO
|
|
525
|
+
assert report["status"] == "bad_translucent"
|
|
526
|
+
# bad_translucent vẫn phải TRẢ ẢNH — người duyệt cần thấy defect trong contact sheet,
|
|
527
|
+
# chỉ bad_subject mới được trả None.
|
|
528
|
+
assert out is not None
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def test_postprocess_ok_reports_solid_ratio():
|
|
532
|
+
"""solid_ratio luôn có mặt trong report, kể cả khi status ok."""
|
|
533
|
+
_, report = L.postprocess(_subject_on_key(size=(256, 256)), "#00FF00", src=_fake_src())
|
|
534
|
+
assert report["status"] == "ok"
|
|
535
|
+
assert report["solid_ratio"] > 0.9
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def test_border_impurity_zero_on_flat_key_background():
|
|
539
|
+
"""Vành ngoài là màu key thuần (ca bình thường) -> border_impurity phải bằng 0 tuyệt đối."""
|
|
540
|
+
img = _subject_on_key(size=(64, 64), key=(0, 255, 0), subject=(200, 30, 40))
|
|
541
|
+
assert L.border_impurity(img, "#00FF00") == 0.0
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def test_border_impurity_high_when_background_not_key():
|
|
545
|
+
"""Nền xám phủ toàn khung (không hề có màu key) -> vành ngoài lệch xa màu key."""
|
|
546
|
+
img = Image.new("RGB", (64, 64), (120, 120, 130))
|
|
547
|
+
assert L.border_impurity(img, "#00FF00") > L.BAD_BORDER_DIST
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def test_postprocess_flags_partial_background_failure():
|
|
551
|
+
"""Tái hiện chính xác ca của reviewer: nền hỏng MỘT PHẦN thì coverage và solid_ratio
|
|
552
|
+
đều bị qua mặt cùng lúc, chỉ có border_impurity mới bắt được — đây là cái lỗ hổng mà
|
|
553
|
+
Finding 1 yêu cầu vá.
|
|
554
|
+
|
|
555
|
+
Bố cục canvas 100x100 (tổng 10000px):
|
|
556
|
+
- 40 hàng trên cùng (0..39), toàn bộ chiều rộng: một MẢNG XÁM ĐẶC chưa từng được key
|
|
557
|
+
hoá (Gemini vẽ bóng đổ/panel/vignette đè lên nền thay vì để trống) -> sau chroma_key
|
|
558
|
+
vẫn đục hoàn toàn (khoảng cách tới key ~390, > t_high=170 -> alpha=255, solid).
|
|
559
|
+
4000/10000 px = 40% diện tích.
|
|
560
|
+
- 60 hàng dưới (40..99): nền màu key THUẦN, TRỪ một dải cột giữa (25..74) là CHỦ THỂ
|
|
561
|
+
BÓNG MA màu (0,207,0) sát màu key (0,255,0) -> khoảng cách redmean = 96, nằm giữa
|
|
562
|
+
t_low=70/t_high=170 -> smoothstep cho alpha ~43 (có nội dung, nhưng không đục).
|
|
563
|
+
Phần còn lại của 60 hàng dưới là nền key thuần -> alpha=0 (không tính là nội dung).
|
|
564
|
+
|
|
565
|
+
Tính tay: coverage = (4000 xám + 3000 bóng ma) / 10000 = 0.70 -> nằm NGUYÊN trong dải
|
|
566
|
+
"ok" (0.02, 0.95), vì alpha_coverage không phân biệt được "đục vì nền hỏng" với "đục
|
|
567
|
+
vì chủ thể thật". solid_ratio = 4000 đục thật / 7000 có-nội-dung = 0.571 -> CŨNG vượt
|
|
568
|
+
qua BAD_SOLID_RATIO=0.25, chính vì mảng xám hỏng đó bơm phồng "đục thật" giả. Cả hai
|
|
569
|
+
tín hiệu cũ đều bị qua mặt y hệt ca reviewer báo cáo (coverage 0.63, solid_ratio 0.65
|
|
570
|
+
trên input của họ) -> asset ghosted lọt lưới với status "ok".
|
|
571
|
+
|
|
572
|
+
Chỉ có border_impurity, đo trực tiếp vành ngoài 4px, mới thấy được mảng xám: phần lớn
|
|
573
|
+
vành ngoài của ảnh này (viền trên hoàn toàn, phần lớn viền trái/phải) nằm trong mảng
|
|
574
|
+
xám chưa key, nên khoảng cách trung bình của vành >> BAD_BORDER_DIST=60.
|
|
575
|
+
"""
|
|
576
|
+
size = (100, 100)
|
|
577
|
+
arr = np.full((size[1], size[0], 3), (0, 255, 0), dtype=np.uint8) # nền key thuần
|
|
578
|
+
arr[0:40, :, :] = (120, 120, 130) # mảng xám chưa key, 40% diện tích, KHÔNG bị chroma-key
|
|
579
|
+
arr[40:100, 25:75, :] = (0, 207, 0) # chủ thể bóng ma, sát màu key
|
|
580
|
+
gen = Image.fromarray(arr, "RGB")
|
|
581
|
+
|
|
582
|
+
_, report = L.postprocess(gen, "#00FF00", src=_fake_src(canvas=size, box=(10, 10, 90, 90)))
|
|
583
|
+
|
|
584
|
+
assert L.BAD_LOW < report["coverage"] < L.BAD_HIGH, (
|
|
585
|
+
f"coverage phải nằm trong dải 'ok' (bị qua mặt): {report['coverage']}"
|
|
586
|
+
)
|
|
587
|
+
assert report["solid_ratio"] > L.BAD_SOLID_RATIO, (
|
|
588
|
+
f"solid_ratio cũng phải bị qua mặt, bơm phồng bởi mảng xám: {report['solid_ratio']}"
|
|
589
|
+
)
|
|
590
|
+
assert report["status"] != "ok", "lỗ hổng cũ: bản sinh hỏng lọt lưới với status=ok"
|
|
591
|
+
assert "bad_background" in report["flags"], "border_impurity phải bắt được mảng xám chưa key"
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def test_postprocess_ok_has_empty_flags():
|
|
595
|
+
"""Bản sinh sạch: không cờ nào được set, border_impurity gần như bằng 0."""
|
|
596
|
+
gen = _subject_on_key(size=(256, 256))
|
|
597
|
+
_, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
598
|
+
assert report["status"] == "ok"
|
|
599
|
+
assert report["flags"] == []
|
|
600
|
+
assert report["border_impurity"] == 0.0
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def test_postprocess_ok_reports_hole_ratio():
|
|
604
|
+
"""`hole_ratio` phải luôn có mặt trong report, kể cả khi status ok (không lỗ nào)."""
|
|
605
|
+
gen = _subject_on_key(size=(256, 256))
|
|
606
|
+
_, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
607
|
+
assert report["hole_ratio"] == 0.0
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
def test_border_impurity_false_positive_when_subject_touches_edge():
|
|
611
|
+
"""Ghim CA FALSE POSITIVE ĐÃ BIẾT VÀ CHẤP NHẬN của border_impurity — không phải bug.
|
|
612
|
+
|
|
613
|
+
border_impurity giả định Gemini luôn chừa một lề nền quanh chủ thể. Test này dựng
|
|
614
|
+
đúng ca giả định đó bị PHÁ VỠ: chủ thể (200,30,40) phủ box=(0,0,64,64) — tức là
|
|
615
|
+
TOÀN BỘ canvas 64x64, không chừa một pixel lề key nào. Đây là hình dạng thật của
|
|
616
|
+
asset `cell_base.png` trong game (bbox phủ kín canvas 249x249) — một model được
|
|
617
|
+
yêu cầu restyle nó hoàn toàn có thể vẽ tràn mép y hệt thế này.
|
|
618
|
+
|
|
619
|
+
Vành ngoài lúc này toàn màu chủ thể, cách màu key rất xa (đo thực tế ~549.8, so
|
|
620
|
+
với ngưỡng BAD_BORDER_DIST=60) -> border_impurity báo cao NGẤT, và postprocess báo
|
|
621
|
+
bad_background — dù thực chất "nền" ở đây không hề tồn tại để mà hỏng.
|
|
622
|
+
|
|
623
|
+
Đây KHÔNG phải lỗi cần vá. Đây là đánh đổi có chủ đích: false positive (báo hỏng
|
|
624
|
+
nhầm một bản sinh có thể vẫn ổn) chỉ tốn một lần sinh lại; false negative (bỏ lọt
|
|
625
|
+
một bản sinh thật sự ma/lỗi) mới là thứ khiến asset hỏng lọt vào game. Test này tồn
|
|
626
|
+
tại để nếu sau này ai đó đổi hành vi (nới lỏng border_impurity, hoặc thêm ngoại lệ
|
|
627
|
+
cho "chủ thể phủ kín canvas"), họ phải chủ động sửa test này chứ không phát hiện ra
|
|
628
|
+
sự thay đổi khi asset ma đã lọt vào production.
|
|
629
|
+
"""
|
|
630
|
+
gen = _subject_on_key(size=(64, 64), key=(0, 255, 0), subject=(200, 30, 40), box=(0, 0, 64, 64))
|
|
631
|
+
impurity = L.border_impurity(gen, "#00FF00")
|
|
632
|
+
assert impurity > L.BAD_BORDER_DIST, (
|
|
633
|
+
f"vành ngoài toàn chủ thể phải cách xa màu key: {impurity}"
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
src = _fake_src(canvas=(64, 64), box=(0, 0, 64, 64))
|
|
637
|
+
_, report = L.postprocess(gen, "#00FF00", src=src)
|
|
638
|
+
assert report["border_impurity"] == impurity
|
|
639
|
+
assert "bad_background" in report["flags"], (
|
|
640
|
+
"false positive CHẤP NHẬN ĐƯỢC: chủ thể tràn mép -> báo hỏng nền dù nền "
|
|
641
|
+
"không hề tồn tại; đây là đánh đổi cố ý, không phải điều cần sửa"
|
|
642
|
+
)
|
|
643
|
+
assert report["status"] == "bad_background"
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
def test_postprocess_reports_multiple_flags_at_once():
|
|
647
|
+
"""Ghim cấu trúc if/if (KHÔNG PHẢI if/elif) của postprocess — Finding 2.
|
|
648
|
+
|
|
649
|
+
postprocess() được cố ý đổi từ if/elif sang các khối if ĐỘC LẬP để một bản sinh
|
|
650
|
+
hỏng NHIỀU KIỂU cùng lúc báo ĐỦ tất cả cờ trong `flags`, không chỉ cờ đầu tiên khớp.
|
|
651
|
+
Nhưng test_postprocess_flags_partial_background_failure (fix round 3) không thực sự
|
|
652
|
+
kiểm chứng điều đó: solid_ratio ở test đó (0.5714) vẫn nằm TRÊN BAD_SOLID_RATIO, nên
|
|
653
|
+
flags của nó chỉ có đúng 1 phần tử ('bad_background') — một regression âm thầm đổi
|
|
654
|
+
if thứ hai trở lại thành elif vẫn sẽ lọt qua toàn bộ suite. Test này dựng một ca
|
|
655
|
+
hỏng THẬT SỰ 2 kiểu cùng lúc để bắt đúng regression đó.
|
|
656
|
+
|
|
657
|
+
Tính tay trên canvas 100x100 (10000px), BORDER_PX=4:
|
|
658
|
+
- VÀNH NGOÀI (đúng dải mà border_impurity đo: 4px trên/dưới/trái/phải) = màu xám
|
|
659
|
+
(120,120,130), CHƯA từng được key hoá -> 1536px xám, đục hoàn toàn sau chroma-key
|
|
660
|
+
(cách màu key ~389.5, đo thực tế, vượt xa t_high=170 nên alpha=255 và vượt xa
|
|
661
|
+
BAD_BORDER_DIST=60) -> bad_background.
|
|
662
|
+
- PHẦN LỚN vùng bên trong vành (92x92, trừ một dải cột hẹp) = màu (0,207,0), CHỦ
|
|
663
|
+
THỂ BÓNG MA sát màu key (0,255,0) -> cách màu key = 96.0 (nằm giữa t_low=70 và
|
|
664
|
+
t_high=170) -> alpha ~43 sau chroma-key: CÓ nội dung (>ALPHA_FLOOR=8) nhưng KHÔNG
|
|
665
|
+
đục (<SOLID_ALPHA=200). Vùng này chiếm 92 hàng x 82 cột = 7544px — DOMINANT so
|
|
666
|
+
với 1536px xám, nên nó mới là thứ quyết định solid_ratio.
|
|
667
|
+
- Một dải cột hẹp còn lại bên trong vành (92 hàng x 10 cột = 920px, sát cạnh phải
|
|
668
|
+
nhưng KHÔNG chạm vành) vẫn là màu key thuần -> alpha=0, không tính vào nội dung.
|
|
669
|
+
Dải này tồn tại chỉ để giữ coverage không tràn lên 1.0 (không cần thiết cho hai
|
|
670
|
+
cờ mục tiêu, nhưng cho coverage một khoảng đệm rõ ràng dưới BAD_HIGH=0.95).
|
|
671
|
+
|
|
672
|
+
Số đo tay: coverage = (1536 xám + 7544 bóng ma) / 10000 = 0.908 -> nằm trong dải ok
|
|
673
|
+
(0.02, 0.95), không đủ cao để tự nó kích bad_background qua nhánh coverage, không đủ
|
|
674
|
+
thấp để kích bad_subject — cờ bad_background ở đây đến từ border_impurity, đúng như
|
|
675
|
+
Finding 1 mô tả. solid_ratio = 1536 xám (đục) / 9080 nội dung = 0.16916 -> DƯỚI
|
|
676
|
+
BAD_SOLID_RATIO=0.25 vì mảng bóng ma 7544px áp đảo mảng xám 1536px trong mẫu số.
|
|
677
|
+
|
|
678
|
+
Test dựng thẳng bằng numpy (không qua _subject_on_key) để kiểm soát chính xác vành
|
|
679
|
+
ngoài trùng khít với dải mà border_impurity thực sự đọc — xem imglib.border_impurity:
|
|
680
|
+
rgb[:b], rgb[-b:], rgb[b:-b,:b], rgb[b:-b,-b:].
|
|
681
|
+
"""
|
|
682
|
+
size = (100, 100)
|
|
683
|
+
key = (0, 255, 0)
|
|
684
|
+
grey = (120, 120, 130)
|
|
685
|
+
ghost = (0, 207, 0)
|
|
686
|
+
|
|
687
|
+
arr = np.full((size[1], size[0], 3), key, dtype=np.uint8)
|
|
688
|
+
arr[4:96, 4:86, :] = ghost # chủ thể bóng ma, chiếm áp đảo (7544px)
|
|
689
|
+
arr[0:4, :, :] = grey # vành trên
|
|
690
|
+
arr[-4:, :, :] = grey # vành dưới
|
|
691
|
+
arr[:, 0:4, :] = grey # vành trái
|
|
692
|
+
arr[:, -4:, :] = grey # vành phải (cùng với 3 dòng trên: đúng 1536px vành)
|
|
693
|
+
gen = Image.fromarray(arr, "RGB")
|
|
694
|
+
|
|
695
|
+
src = _fake_src(canvas=size, box=(10, 10, 90, 90))
|
|
696
|
+
_, report = L.postprocess(gen, "#00FF00", src=src)
|
|
697
|
+
|
|
698
|
+
assert L.BAD_LOW < report["coverage"] < L.BAD_HIGH, (
|
|
699
|
+
f"coverage phải nằm trong dải ok để bad_subject KHÔNG bật: {report['coverage']}"
|
|
700
|
+
)
|
|
701
|
+
assert report["border_impurity"] > L.BAD_BORDER_DIST, (
|
|
702
|
+
f"vành xám phải kích bad_background: {report['border_impurity']}"
|
|
703
|
+
)
|
|
704
|
+
assert report["solid_ratio"] < L.BAD_SOLID_RATIO, (
|
|
705
|
+
f"bóng ma áp đảo phải kéo solid_ratio xuống dưới ngưỡng: {report['solid_ratio']}"
|
|
706
|
+
)
|
|
707
|
+
assert "bad_background" in report["flags"], report["flags"]
|
|
708
|
+
assert "bad_translucent" in report["flags"], report["flags"]
|
|
709
|
+
assert "bad_subject" not in report["flags"], report["flags"]
|
|
710
|
+
assert report["status"] == "bad_background", (
|
|
711
|
+
"cờ nặng nhất (bad_background, đứng trước trong thứ tự append) phải thắng status"
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
def test_make_sheet_layout():
|
|
716
|
+
"""3 hàng nền x N cột, cộng dải nhãn phía trên."""
|
|
717
|
+
cells = [
|
|
718
|
+
("original", _fake_src()),
|
|
719
|
+
("v1", _fake_src(box=(10, 10, 100, 100))),
|
|
720
|
+
("v2", _fake_src(box=(30, 30, 130, 130))),
|
|
721
|
+
]
|
|
722
|
+
sheet = L.make_sheet(cells, cell=64, pad=8)
|
|
723
|
+
assert sheet.mode == "RGB"
|
|
724
|
+
# 3 cột x (64 + 8) + 8 mép
|
|
725
|
+
assert sheet.width == 3 * (64 + 8) + 8
|
|
726
|
+
# 3 hàng nền x (64 + 8) + 8 mép + 20 dải nhãn
|
|
727
|
+
assert sheet.height == 3 * (64 + 8) + 8 + 20
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def test_make_sheet_backgrounds_differ():
|
|
731
|
+
"""Hàng nền sáng và hàng nền tối phải KHÁC nhau — nếu giống thì sheet vô dụng."""
|
|
732
|
+
sheet = L.make_sheet([("a", _fake_src())], cell=64, pad=8)
|
|
733
|
+
light = sheet.getpixel((10, 20 + 8 + 2)) # góc ô hàng 1
|
|
734
|
+
dark = sheet.getpixel((10, 20 + 8 + 64 + 8 + 2)) # góc ô hàng 2
|
|
735
|
+
assert light != dark
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def test_make_sheet_checker_row_alternates():
|
|
739
|
+
"""Checker row (row 2) reveals semi-transparent subjects and alternates properly.
|
|
740
|
+
|
|
741
|
+
The checker row is the final gate before an asset is written into the game —
|
|
742
|
+
it alone reveals semi-transparent/ghosted subjects that would hide in solid rows.
|
|
743
|
+
Without this test, a future refactor collapsing _checker() to a solid fill or
|
|
744
|
+
breaking the alternation would pass silently and the sheet would stop exposing
|
|
745
|
+
the exact defect it exists to expose.
|
|
746
|
+
"""
|
|
747
|
+
sheet = L.make_sheet([("test", _fake_src())], cell=160, pad=12)
|
|
748
|
+
|
|
749
|
+
# Row 2 y-offset from layout arithmetic: LABEL_H + pad + 2 * (cell + pad)
|
|
750
|
+
row2_y = L.LABEL_H + 12 + 2 * (160 + 12) # 20 + 12 + 344 = 376
|
|
751
|
+
x = 12 # pad
|
|
752
|
+
|
|
753
|
+
# Sample two points one checker square apart in the transparent cell corner.
|
|
754
|
+
# _fake_src() has transparent margins, so corners read the background, not content.
|
|
755
|
+
px1 = sheet.getpixel((x + 2, row2_y + 2))
|
|
756
|
+
px2 = sheet.getpixel((x + 2 + L.CHECKER_SIZE, row2_y + 2))
|
|
757
|
+
|
|
758
|
+
# Checker must alternate: samples one square apart must differ
|
|
759
|
+
assert px1 != px2, f"checker not alternating: {px1} vs {px2}"
|
|
760
|
+
|
|
761
|
+
# Checker colors must be from SHEET_CHECKER, not solid light/dark fill
|
|
762
|
+
assert px1 in L.SHEET_CHECKER, f"checker color {px1} not in SHEET_CHECKER"
|
|
763
|
+
assert px2 in L.SHEET_CHECKER, f"checker color {px2} not in SHEET_CHECKER"
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
def test_make_sheet_empty_cells_is_safe():
|
|
767
|
+
sheet = L.make_sheet([], cell=64, pad=8)
|
|
768
|
+
assert sheet.size[0] > 0 and sheet.size[1] > 0
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
def test_despeckle_removes_gemini_watermark():
|
|
772
|
+
"""Ca THẬT, đo từ một lần gọi Gemini thật — không phải fixture bịa.
|
|
773
|
+
|
|
774
|
+
Gemini đóng dấu watermark ✦ lên góc dưới-phải MỌI ảnh nó sinh. Watermark đó có màu
|
|
775
|
+
(81,249,77) — xanh lá hơi lệch key, cách #00FF00 đúng ~176 trên thang redmean, tức là
|
|
776
|
+
NHỈNH HƠN t_high=170 — nên chroma_key coi nó là chủ thể và giữ lại ĐỤC HOÀN TOÀN.
|
|
777
|
+
Kết quả: mọi asset xuất ra đều dính một chấm xanh. Chỉ có chạy thật mới phát hiện được.
|
|
778
|
+
"""
|
|
779
|
+
gen = Image.new("RGB", (256, 256), (0, 255, 0))
|
|
780
|
+
gen.paste((200, 30, 40), (64, 64, 192, 192)) # chủ thể
|
|
781
|
+
gen.paste((81, 249, 77), (238, 238, 250, 250)) # watermark Gemini (đo thật)
|
|
782
|
+
|
|
783
|
+
keyed = L.despill(L.chroma_key(gen, "#00FF00"), "#00FF00")
|
|
784
|
+
assert keyed.getpixel((244, 244))[3] > 200, "test vô nghĩa nếu watermark không sống sót key"
|
|
785
|
+
|
|
786
|
+
cleaned, removed = L.despeckle(keyed)
|
|
787
|
+
assert removed == 1, f"phải xoá đúng 1 mảng rác, xoá {removed}"
|
|
788
|
+
assert cleaned.getpixel((244, 244))[3] == 0, "watermark vẫn còn"
|
|
789
|
+
assert cleaned.getpixel((128, 128))[3] == 255, "chủ thể bị xoá oan"
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def test_despeckle_keeps_main_subject_when_nothing_to_clean():
|
|
793
|
+
gen = Image.new("RGB", (128, 128), (0, 255, 0))
|
|
794
|
+
gen.paste((200, 30, 40), (32, 32, 96, 96))
|
|
795
|
+
keyed = L.despill(L.chroma_key(gen, "#00FF00"), "#00FF00")
|
|
796
|
+
cleaned, removed = L.despeckle(keyed)
|
|
797
|
+
assert removed == 0
|
|
798
|
+
assert L.content_bbox(cleaned) == L.content_bbox(keyed)
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def test_despeckle_keeps_comparable_sized_parts():
|
|
802
|
+
"""Asset nhiều mảnh rời cỡ tương đương (vd đống xu) KHÔNG được mất mảnh nào."""
|
|
803
|
+
img = Image.new("RGBA", (128, 128), (0, 0, 0, 0))
|
|
804
|
+
for box in [(10, 10, 50, 50), (70, 10, 110, 50), (10, 70, 50, 110)]:
|
|
805
|
+
img.paste((200, 30, 40, 255), box)
|
|
806
|
+
cleaned, removed = L.despeckle(img)
|
|
807
|
+
assert removed == 0, "ba mảng cỡ bằng nhau, không được xoá cái nào"
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
def test_postprocess_reports_speckles_removed():
|
|
811
|
+
gen = _subject_on_key(size=(256, 256))
|
|
812
|
+
gen.paste((81, 249, 77), (240, 240, 250, 250)) # watermark
|
|
813
|
+
_, report = L.postprocess(gen, "#00FF00", src=_fake_src())
|
|
814
|
+
assert report["speckles_removed"] == 1
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
# ── unwatermark_gemini: đảo lớp phủ ✦ của Gemini ────────────────────────────────────────
|
|
818
|
+
# Ảnh thử luôn phải ĐỦ TO cho hình học đã hiệu chuẩn (48x48 cách cạnh phải/dưới 96px),
|
|
819
|
+
# nên dùng 400x300 chứ không phải 256x256 như các test khác.
|
|
820
|
+
_WM_W, _WM_H = 400, 300
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
def _wm_bake(bg_rgb, size=(_WM_W, _WM_H)):
|
|
824
|
+
"""Dán watermark ✦ ĐÚNG như Gemini: phủ trắng alpha cố định lên ảnh nền cho trước."""
|
|
825
|
+
a = L._wm_alpha()
|
|
826
|
+
arr = np.asarray(Image.new("RGB", size, bg_rgb)).astype(float)
|
|
827
|
+
W, H = size
|
|
828
|
+
x0, y0 = W - 144, H - 144
|
|
829
|
+
reg = arr[y0:y0 + 48, x0:x0 + 48]
|
|
830
|
+
arr[y0:y0 + 48, x0:x0 + 48] = reg * (1 - a[..., None]) + 255 * a[..., None]
|
|
831
|
+
return Image.fromarray(np.clip(np.rint(arr), 0, 255).astype("uint8"), "RGB"), (x0, y0)
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
def _wm_box_px(img, x0, y0):
|
|
835
|
+
return np.asarray(img.convert("RGB")).astype(int)[y0:y0 + 48, x0:x0 + 48]
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def test_unwatermark_restores_flat_background_exactly():
|
|
839
|
+
"""Phép đảo phải trả lại ĐÚNG màu nền — sai số chỉ do lượng tử hoá (<=1 mức)."""
|
|
840
|
+
for bg in [(0, 0, 0), (128, 128, 128), (60, 90, 200), (250, 250, 250)]:
|
|
841
|
+
wm, (x0, y0) = _wm_bake(bg)
|
|
842
|
+
assert _wm_box_px(wm, x0, y0).std() > 0, f"nền {bg}: watermark không dán được"
|
|
843
|
+
out, info = L.unwatermark_gemini(wm)
|
|
844
|
+
assert info is not None and info["box"] == (x0, y0, 48, 48)
|
|
845
|
+
err = np.abs(_wm_box_px(out, x0, y0) - np.array(bg)).max()
|
|
846
|
+
assert err <= 1, f"nền {bg}: sai số phục hồi {err} > 1"
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
def test_unwatermark_verify_detects_real_watermark():
|
|
850
|
+
wm, _ = _wm_bake((40, 40, 40))
|
|
851
|
+
_, info = L.unwatermark_gemini(wm, verify=True)
|
|
852
|
+
assert info is not None and info["gain"] > 0.5
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
def test_unwatermark_verify_skips_clean_image():
|
|
856
|
+
"""Ảnh KHÔNG có watermark phải được bỏ qua — đảo bừa sẽ đóng ngôi sao TỐI vào ảnh sạch."""
|
|
857
|
+
for bg in [(0, 0, 0), (128, 128, 128), (255, 255, 255), (200, 30, 30)]:
|
|
858
|
+
clean = Image.new("RGB", (_WM_W, _WM_H), bg)
|
|
859
|
+
out, info = L.unwatermark_gemini(clean, verify=True)
|
|
860
|
+
assert info is None, f"nền {bg}: xoá bừa trên ảnh sạch"
|
|
861
|
+
assert np.array_equal(np.asarray(out), np.asarray(clean))
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
def test_unwatermark_verify_is_idempotent():
|
|
865
|
+
"""Chạy lần hai không được đục thêm — chống xoá hai lần khi ảnh qua nhiều bước."""
|
|
866
|
+
wm, _ = _wm_bake((70, 70, 70))
|
|
867
|
+
once, info1 = L.unwatermark_gemini(wm, verify=True)
|
|
868
|
+
twice, info2 = L.unwatermark_gemini(once, verify=True)
|
|
869
|
+
assert info1 is not None and info2 is None
|
|
870
|
+
assert np.array_equal(np.asarray(once), np.asarray(twice))
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
def test_unwatermark_rejects_star_with_different_alpha():
|
|
874
|
+
"""Ngôi sao THẬT do người vẽ (alpha khác) không được nhận nhầm là watermark."""
|
|
875
|
+
a = L._wm_alpha()
|
|
876
|
+
arr = np.asarray(Image.new("RGB", (_WM_W, _WM_H), (60, 60, 60))).astype(float)
|
|
877
|
+
x0, y0 = _WM_W - 144, _WM_H - 144
|
|
878
|
+
reg = arr[y0:y0 + 48, x0:x0 + 48]
|
|
879
|
+
arr[y0:y0 + 48, x0:x0 + 48] = reg * (1 - 0.6 * a[..., None]) + 255 * 0.6 * a[..., None]
|
|
880
|
+
img = Image.fromarray(np.clip(np.rint(arr), 0, 255).astype("uint8"), "RGB")
|
|
881
|
+
_, info = L.unwatermark_gemini(img, verify=True)
|
|
882
|
+
assert info is None
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
def test_unwatermark_skips_image_smaller_than_geometry():
|
|
886
|
+
"""Ảnh nhỏ hơn cả lề 96px thì không phải khung Gemini gốc -> không được chạm vào."""
|
|
887
|
+
small = Image.new("RGB", (100, 80), (10, 20, 30))
|
|
888
|
+
out, info = L.unwatermark_gemini(small)
|
|
889
|
+
assert info is None and np.array_equal(np.asarray(out), np.asarray(small))
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
def test_unwatermark_keeps_alpha_channel():
|
|
893
|
+
"""Ảnh RGBA phải giữ nguyên mode và kênh alpha (chỉ sửa RGB)."""
|
|
894
|
+
wm, (x0, y0) = _wm_bake((50, 50, 50))
|
|
895
|
+
rgba = wm.convert("RGBA")
|
|
896
|
+
rgba.putalpha(Image.new("L", rgba.size, 123))
|
|
897
|
+
out, info = L.unwatermark_gemini(rgba)
|
|
898
|
+
assert info is not None and out.mode == "RGBA"
|
|
899
|
+
assert np.asarray(out)[..., 3].min() == 123
|
|
900
|
+
err = np.abs(_wm_box_px(out, x0, y0) - 50).max()
|
|
901
|
+
assert err <= 1
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
def test_unwatermark_leaves_rest_of_image_untouched():
|
|
905
|
+
"""Chỉ ô 48x48 được sửa — không được lan ra phần còn lại của ảnh."""
|
|
906
|
+
wm, (x0, y0) = _wm_bake((90, 120, 60))
|
|
907
|
+
out, _ = L.unwatermark_gemini(wm)
|
|
908
|
+
a, b = np.asarray(wm).astype(int), np.asarray(out).astype(int)
|
|
909
|
+
diff = np.abs(a - b).sum(axis=2)
|
|
910
|
+
diff[y0:y0 + 48, x0:x0 + 48] = 0
|
|
911
|
+
assert diff.max() == 0
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
# ── Tách nền đa phương pháp: modal_border_color / unmix / score / best_cutout ───────────
|
|
915
|
+
|
|
916
|
+
def _plate(size=(120, 200), bg=(251, 14, 224), fg=(120, 170, 40), horizon=90, aa=2):
|
|
917
|
+
"""Ảnh NỀN full-bleed: nửa trên là màu nền, nửa dưới là 'thảm cỏ' tràn ra TẬN VÀNH.
|
|
918
|
+
|
|
919
|
+
Đây là hình dạng mà `sample_border_color` (dùng mean) không xử lý được, và là hình dạng
|
|
920
|
+
thật của ảnh nền game: home_grass/gpt1.png. `aa` là bề rộng dải anti-alias ở chân trời —
|
|
921
|
+
tham số hoá để test được việc dò bề rộng tự động (đo thật: 2px ở bản GPT, 7–8px ở Gemini).
|
|
922
|
+
"""
|
|
923
|
+
w, h = size
|
|
924
|
+
arr = np.zeros((h, w, 3), dtype=np.float64)
|
|
925
|
+
arr[:horizon] = bg
|
|
926
|
+
arr[horizon + aa:] = fg
|
|
927
|
+
for i in range(aa): # dải blend tuyến tính giữa nền và tiền cảnh
|
|
928
|
+
t = (i + 1) / (aa + 1)
|
|
929
|
+
arr[horizon + i] = np.array(bg) * (1 - t) + np.array(fg) * t
|
|
930
|
+
return Image.fromarray(np.rint(arr).clip(0, 255).astype(np.uint8), "RGB")
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
def test_modal_border_color_survives_half_subject_border():
|
|
934
|
+
"""MODE trên vành chịu được vành nửa-nền-nửa-chủ-thể; MEAN thì không.
|
|
935
|
+
|
|
936
|
+
Đây là lý do tồn tại của modal_border_color. Đo thật trên home_grass/gpt1.png:
|
|
937
|
+
sample_border_color trả #AC4978 với purity 0.0002 — bùn tím, không phải màu nào có thật
|
|
938
|
+
trong ảnh — nên cửa `purity >= _AUTOKEY_MIN_PURITY` trong MCP không bao giờ mở và cả
|
|
939
|
+
pipeline rơi về màu key yêu cầu. Mode trên cùng ảnh đó trả #FB0EE0, đúng màu đã vẽ.
|
|
940
|
+
"""
|
|
941
|
+
bg = (251, 14, 224)
|
|
942
|
+
img = _plate(bg=bg)
|
|
943
|
+
|
|
944
|
+
mode_hex, share = L.modal_border_color(img, key_hex="#FF00FF")
|
|
945
|
+
assert L.color_dist(L.hex_to_rgb(mode_hex), bg) < 20.0, mode_hex
|
|
946
|
+
assert share >= L.CUTOUT_MIN_BORDER_SHARE, share
|
|
947
|
+
|
|
948
|
+
mean_hex, purity = L.sample_border_color(img)
|
|
949
|
+
assert purity < 0.5, f"mean phải tỏ ra 'không thuần' trên vành trộn: {purity}"
|
|
950
|
+
assert L.color_dist(L.hex_to_rgb(mean_hex), bg) > 100.0, (
|
|
951
|
+
f"mean trộn hai nửa thành màu không có thật: {mean_hex}"
|
|
952
|
+
)
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
def test_modal_border_color_without_key_can_pick_the_subject():
|
|
956
|
+
"""Ghim VÌ SAO phải truyền `key_hex`: mode TOÀN CỤC có thể trả về màu CHỦ THỂ.
|
|
957
|
+
|
|
958
|
+
`_plate` có nền xanh PHẲNG tràn ra vành: đếm tay trên vành 4px của canvas 120x200 —
|
|
959
|
+
xanh 1312 px so với hồng 1168 px, nên mode toàn cục chọn XANH, tức màu chủ thể. Key
|
|
960
|
+
theo nó sẽ xoá mất chính chủ thể. Mode toàn cục chỉ đúng trên ảnh thật NHỜ MAY: nền key
|
|
961
|
+
phẳng còn thảm cỏ có vân nên không bin xanh nào áp đảo. Lọc theo màu key thì hết may rủi.
|
|
962
|
+
"""
|
|
963
|
+
bg = (251, 14, 224)
|
|
964
|
+
fg = (120, 170, 40)
|
|
965
|
+
img = _plate(bg=bg, fg=fg)
|
|
966
|
+
|
|
967
|
+
loose, _ = L.modal_border_color(img) # không truyền key
|
|
968
|
+
assert L.color_dist(L.hex_to_rgb(loose), fg) < 20.0, (
|
|
969
|
+
f"ghim hành vi đã biết: mode toàn cục bám màu chủ thể, {loose}"
|
|
970
|
+
)
|
|
971
|
+
tight, _ = L.modal_border_color(img, key_hex="#FF00FF") # có truyền key
|
|
972
|
+
assert L.color_dist(L.hex_to_rgb(tight), bg) < 20.0, tight
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
def test_unmix_roundtrip_reconstructs_original():
|
|
976
|
+
"""(F, α) của unmix phải là một PHÂN RÃ HỢP LỆ: ghép lại lên màu nền ra đúng ảnh gốc.
|
|
977
|
+
|
|
978
|
+
Đây là kiểm chứng ground-truth thật sự, không phải so sánh tương đối: nếu F và α cùng
|
|
979
|
+
đúng thì F·α + BG·(1−α) phải tái tạo được O. Đo thật trên gpt1.png dải mềm: unmix 0.228
|
|
980
|
+
so với 25.09 của region-grow+despill và 16.45 của chroma_key+despill.
|
|
981
|
+
"""
|
|
982
|
+
bg = (251, 14, 224)
|
|
983
|
+
img = _plate(bg=bg, aa=3)
|
|
984
|
+
out, info = L.unmix_cutout(img, L.rgb_to_hex(bg))
|
|
985
|
+
|
|
986
|
+
O = np.asarray(img, dtype=np.float64)
|
|
987
|
+
arr = np.asarray(out, dtype=np.float64)
|
|
988
|
+
a = (arr[..., 3] / 255.0)[..., None]
|
|
989
|
+
recomp = arr[..., :3] * a + np.array(bg, dtype=np.float64) * (1 - a)
|
|
990
|
+
assert np.abs(recomp - O).mean() < 1.0, np.abs(recomp - O).mean()
|
|
991
|
+
assert info["soft_px"] > 0, "phải có pixel dải AA được giải"
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
def test_unmix_band_width_adapts_to_source():
|
|
995
|
+
"""Bề rộng dải AA phải ĐO TỪ ẢNH, không phải hằng số.
|
|
996
|
+
|
|
997
|
+
Bug thật gặp trong lúc phát triển: bản đầu cố định dải 2px, chạy sạch trên ảnh GPT
|
|
998
|
+
(AA 2px) nhưng để lại 433 px viền hồng ĐỤC trên ảnh Gemini (AA 7–8px, chân trời vẽ
|
|
999
|
+
nhoè). Hằng số cố định thì hoặc sót viền hoặc gặm chủ thể — không có giá trị nào đúng cả.
|
|
1000
|
+
"""
|
|
1001
|
+
bg = (251, 14, 224)
|
|
1002
|
+
narrow = L.unmix_cutout(_plate(bg=bg, aa=1), L.rgb_to_hex(bg))[1]["band_w"]
|
|
1003
|
+
wide = L.unmix_cutout(_plate(bg=bg, aa=7), L.rgb_to_hex(bg))[1]["band_w"]
|
|
1004
|
+
assert wide > narrow, f"dải phải nới theo ảnh: hẹp={narrow} rộng={wide}"
|
|
1005
|
+
assert narrow <= 3, narrow
|
|
1006
|
+
assert wide >= 5, wide
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
def test_unmix_leaves_no_background_tint_on_kept_pixels():
|
|
1010
|
+
"""Không một pixel GIỮ LẠI nào còn ám màu nền — chỉ tiêu chính của cả việc này."""
|
|
1011
|
+
bg = (251, 14, 224)
|
|
1012
|
+
img = _plate(bg=bg, aa=3)
|
|
1013
|
+
out, _ = L.unmix_cutout(img, L.rgb_to_hex(bg))
|
|
1014
|
+
m = L.score_cutout(img, out, L.rgb_to_hex(bg))
|
|
1015
|
+
assert m["cast"] == 0, m
|
|
1016
|
+
assert m["f_err"] < 2.0, m["f_err"]
|
|
1017
|
+
assert not m["disqualify"], m["disqualify"]
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
def test_unmix_keeps_interior_art_of_background_colour():
|
|
1021
|
+
"""Ràng buộc LIÊN THÔNG: vùng trùng màu nền nằm trong lòng chủ thể KHÔNG bị xoá.
|
|
1022
|
+
|
|
1023
|
+
Cùng lý lẽ với strip_bg_residue: muốn bị coi là nền, một vùng phải nối được ra tới vành
|
|
1024
|
+
ảnh. Không có ràng buộc này thì art tình cờ trùng màu key bị khoét thủng.
|
|
1025
|
+
"""
|
|
1026
|
+
bg = (251, 14, 224)
|
|
1027
|
+
arr = np.full((120, 120, 3), (120, 170, 40), dtype=np.uint8)
|
|
1028
|
+
arr[:20, :, :] = bg # nền thật, chạm vành trên
|
|
1029
|
+
arr[60:80, 60:80, :] = bg # 'viên ngọc' trùng màu nền, nằm giữa thân
|
|
1030
|
+
img = Image.fromarray(arr, "RGB")
|
|
1031
|
+
out, _ = L.unmix_cutout(img, L.rgb_to_hex(bg))
|
|
1032
|
+
al = np.asarray(out)[..., 3]
|
|
1033
|
+
assert al[70, 70] == 255, "art trong lòng chủ thể không được xoá"
|
|
1034
|
+
assert al[5, 60] == 0, "nền chạm vành phải bị xoá"
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
def test_score_cutout_disqualifies_method_that_eats_subject():
|
|
1038
|
+
"""fg_loss phải LOẠI THẲNG cách ăn vào lòng chủ thể — ca BEN2 trên ảnh nền full-bleed.
|
|
1039
|
+
|
|
1040
|
+
Đo thật: BEN2 trên home_grass/gpt1.png ăn mất 8.99% thảm cỏ và làm mép nhoè thành dải
|
|
1041
|
+
77.425 px. Không có cửa này thì nó vẫn có thể thắng điểm nhờ cast thấp.
|
|
1042
|
+
"""
|
|
1043
|
+
bg = (251, 14, 224)
|
|
1044
|
+
img = _plate(bg=bg, aa=2)
|
|
1045
|
+
good, _ = L.unmix_cutout(img, L.rgb_to_hex(bg))
|
|
1046
|
+
|
|
1047
|
+
arr = np.asarray(good).copy()
|
|
1048
|
+
arr[150:190, :, 3] = 60 # bào mờ một dải giữa lòng 'thảm cỏ'
|
|
1049
|
+
eaten = Image.fromarray(arr, "RGBA")
|
|
1050
|
+
|
|
1051
|
+
m_ok = L.score_cutout(img, good, L.rgb_to_hex(bg))
|
|
1052
|
+
m_bad = L.score_cutout(img, eaten, L.rgb_to_hex(bg))
|
|
1053
|
+
assert m_bad["fg_loss"] > L.CUTOUT_BAD_FG_LOSS, m_bad["fg_loss"]
|
|
1054
|
+
assert "an_chu_the" in m_bad["disqualify"], m_bad["disqualify"]
|
|
1055
|
+
assert not m_ok["disqualify"], m_ok["disqualify"]
|
|
1056
|
+
assert m_bad["score"] > m_ok["score"]
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
def test_score_cutout_catches_opaque_fringe_that_f_err_cannot():
|
|
1060
|
+
"""`cast` bắt được ca mà `f_err` một mình bị qua mặt — vì sao cần CẢ HAI.
|
|
1061
|
+
|
|
1062
|
+
Cách nào để alpha=255 khắp dải AA sẽ có f_err≈0 HIỂN NHIÊN, vì khi α=1 thì nghịch đảo
|
|
1063
|
+
đại số F_ideal ≡ O, tức 'màu đúng' chính là màu đã bị nền trộn vào. Chỉ `cast` mới thấy
|
|
1064
|
+
viền còn ám màu nền đó. Đo thật: region-nofeather có f_err thấp nhưng cast 391.
|
|
1065
|
+
"""
|
|
1066
|
+
bg = (251, 14, 224)
|
|
1067
|
+
img = _plate(bg=bg, aa=4)
|
|
1068
|
+
hard_edge = np.asarray(img.convert("RGBA")).copy()
|
|
1069
|
+
hard_edge[:90, :, 3] = 0 # cắt cứng đúng chân trời, giữ NGUYÊN dải AA đục
|
|
1070
|
+
blunt = Image.fromarray(hard_edge, "RGBA")
|
|
1071
|
+
|
|
1072
|
+
m = L.score_cutout(img, blunt, L.rgb_to_hex(bg))
|
|
1073
|
+
assert m["f_err"] < 1.0, f"f_err bị qua mặt như dự đoán: {m['f_err']}"
|
|
1074
|
+
assert m["cast"] > 0, "cast phải bắt được dải AA còn ám màu nền"
|
|
1075
|
+
|
|
1076
|
+
clean, _ = L.unmix_cutout(img, L.rgb_to_hex(bg))
|
|
1077
|
+
assert L.score_cutout(img, clean, L.rgb_to_hex(bg))["score"] < m["score"]
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
def test_best_cutout_picks_unmix_and_reports_full_table():
|
|
1081
|
+
"""best_cutout phải trả tên cách thắng VÀ bảng điểm đủ mọi ứng viên."""
|
|
1082
|
+
bg = (251, 14, 224)
|
|
1083
|
+
img = _plate(bg=bg, aa=3)
|
|
1084
|
+
out, rep = L.best_cutout(img, "#FF00FF")
|
|
1085
|
+
|
|
1086
|
+
assert rep["cutout_method"] == "unmix", rep["cutout_method"]
|
|
1087
|
+
assert rep["bg_source"] == "mode_vien", rep["bg_source"]
|
|
1088
|
+
assert L.color_dist(L.hex_to_rgb(rep["bg_color_used"]), bg) < 20.0
|
|
1089
|
+
assert len(rep["cutout_table"]) >= 2, rep["cutout_table"]
|
|
1090
|
+
assert all("score" in r or r.get("error") for r in rep["cutout_table"])
|
|
1091
|
+
assert not rep["all_disqualified"]
|
|
1092
|
+
assert L.score_cutout(img, out, rep["bg_color_used"])["cast"] == 0
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
def test_best_cutout_rejects_measured_colour_when_subject_fills_border():
|
|
1096
|
+
"""Cửa gác MIN_KEY_MARGIN: vành toàn CHỦ THỂ thì màu đo được phải bị TỪ CHỐI.
|
|
1097
|
+
|
|
1098
|
+
Vành có thể 'thuần một màu' mà vẫn không phải nền — khi chủ thể tràn kín canvas thì màu
|
|
1099
|
+
đo được là màu chủ thể, key theo nó sẽ xoá mất chính chủ thể. Ngưỡng 190 là ĐO ĐƯỢC:
|
|
1100
|
+
độ lệch model-vẽ-so-với-yêu-cầu trên 6 bản sinh nằm trong 6.0–96.5, còn khoảng cách từ
|
|
1101
|
+
màu key tới màu chủ thể thật là 353–536.
|
|
1102
|
+
"""
|
|
1103
|
+
img = Image.new("RGB", (64, 64), (200, 30, 40)) # đỏ kín khung, không có nền
|
|
1104
|
+
_, rep = L.best_cutout(img, "#00FF00")
|
|
1105
|
+
assert rep["bg_color_used"] == "#00FF00", rep["bg_color_used"]
|
|
1106
|
+
assert rep["bg_source"] == "khong_thay_mau_key_o_vien", rep["bg_source"]
|
|
1107
|
+
assert rep["bg_mode_share"] == 0.0, rep["bg_mode_share"]
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
def test_score_cutout_ignores_fg_loss_when_no_key_field_exists():
|
|
1111
|
+
"""Không có phông key -> `far` vô nghĩa, KHÔNG được dùng fg_loss để loại.
|
|
1112
|
+
|
|
1113
|
+
Bug thật đã gặp và đã sửa: với ảnh KHÔNG có màu key ở vành (tranh nền thật, ảnh chụp),
|
|
1114
|
+
`hard` rỗng nên `far` biến thành TOÀN ẢNH, và fg_loss quay ra đo "bao nhiêu phần ảnh
|
|
1115
|
+
không đục" — tức phạt đúng cách vừa tách nền THÀNH CÔNG. Đo thật lúc đó: cutout tách
|
|
1116
|
+
đúng chủ thể (coverage 0.156 so với diện tích thật 0.181) nhưng bị loại với fg_loss
|
|
1117
|
+
0.8484, và bản KHÔNG LÀM GÌ CẢ thắng — giao ra ảnh nguyên vẹn, nền còn nguyên.
|
|
1118
|
+
"""
|
|
1119
|
+
rng = np.random.default_rng(7)
|
|
1120
|
+
arr = rng.integers(60, 200, size=(120, 120, 3), dtype=np.int16).astype(np.uint8)
|
|
1121
|
+
arr[40:80, 40:80] = (190, 60, 55) # 'chủ thể' 40x40 giữa khung
|
|
1122
|
+
img = Image.fromarray(arr, "RGB")
|
|
1123
|
+
|
|
1124
|
+
seg = np.zeros((120, 120, 4), dtype=np.uint8) # cutout LÝ TƯỞNG: đúng ô chủ thể
|
|
1125
|
+
seg[..., :3] = arr
|
|
1126
|
+
seg[40:80, 40:80, 3] = 255
|
|
1127
|
+
good = Image.fromarray(seg, "RGBA")
|
|
1128
|
+
|
|
1129
|
+
regions = L._cutout_regions(img, "#00FF00")
|
|
1130
|
+
assert not regions["hard"].any(), "ảnh này không được có vùng màu key nào"
|
|
1131
|
+
|
|
1132
|
+
m = L.score_cutout(img, good, "#00FF00", regions)
|
|
1133
|
+
assert m["fg_loss_valid"] is False, m
|
|
1134
|
+
assert m["fg_loss"] == 0.0, m["fg_loss"]
|
|
1135
|
+
assert "an_chu_the" not in m["disqualify"], m["disqualify"]
|
|
1136
|
+
|
|
1137
|
+
# còn bản KHÔNG LÀM GÌ (đục hết khung) vẫn phải bị loại — bởi `coverage`, không phải fg_loss
|
|
1138
|
+
untouched = img.convert("RGBA")
|
|
1139
|
+
m_bad = L.score_cutout(img, untouched, "#00FF00", regions)
|
|
1140
|
+
assert "phu_bat_thuong" in m_bad["disqualify"], m_bad["disqualify"]
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
def test_best_cutout_lets_cutout_model_win_when_there_is_no_key_field():
|
|
1144
|
+
"""Ảnh không có phông key -> ứng viên `cutout` (BEN2) phải THẮNG, không bị loại oan."""
|
|
1145
|
+
rng = np.random.default_rng(11)
|
|
1146
|
+
arr = rng.integers(60, 200, size=(120, 120, 3), dtype=np.int16).astype(np.uint8)
|
|
1147
|
+
arr[40:80, 40:80] = (190, 60, 55)
|
|
1148
|
+
img = Image.fromarray(arr, "RGB")
|
|
1149
|
+
|
|
1150
|
+
def fake_ben2(im):
|
|
1151
|
+
seg = np.zeros((120, 120, 4), dtype=np.uint8)
|
|
1152
|
+
seg[..., :3] = np.asarray(im.convert("RGB"))
|
|
1153
|
+
seg[38:82, 38:82, 3] = 255 # rộng hơn 2px để _erode_alpha(1) không ăn mất
|
|
1154
|
+
return Image.fromarray(seg, "RGBA")
|
|
1155
|
+
|
|
1156
|
+
_, rep = L.best_cutout(img, "#00FF00", cutout=fake_ben2)
|
|
1157
|
+
assert rep["cutout_method"] == "ben2", rep["cutout_table"]
|
|
1158
|
+
assert rep["bg_source"] == "khong_thay_mau_key_o_vien", rep["bg_source"]
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
def test_postprocess_multi_reports_method_and_does_not_despill_unmix():
|
|
1162
|
+
"""postprocess(multi=True) phải báo cách đã dùng, và KHÔNG despill lại bản unmix.
|
|
1163
|
+
|
|
1164
|
+
despill chỉ chạm pixel alpha<255 — tức đúng dải AA mà unmix vừa giải chính xác — nên
|
|
1165
|
+
chạy nó lần nữa sẽ kéo nghiệm đúng lệch về phía heuristic kẹp kênh.
|
|
1166
|
+
"""
|
|
1167
|
+
bg = (251, 14, 224)
|
|
1168
|
+
img = _plate(size=(120, 200), bg=bg, aa=3)
|
|
1169
|
+
out, rep = L.postprocess(img, "#FF00FF", size=(120, 200))
|
|
1170
|
+
|
|
1171
|
+
assert out is not None, rep
|
|
1172
|
+
assert rep["cutout_method"] == "unmix", rep["cutout_method"]
|
|
1173
|
+
assert "cutout_table" in rep and "cutout_score" in rep
|
|
1174
|
+
assert "out_coverage" in rep and "out_solid_ratio" in rep
|
|
1175
|
+
assert L.score_cutout(img, out, rep["bg_color_used"])["f_err"] < 2.0, "dấu hiệu bị despill lại"
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
def test_postprocess_multi_can_be_turned_off():
|
|
1179
|
+
"""`multi=False` phải giữ NGUYÊN đường đơn phương pháp đời cũ — không có khoá báo cáo mới."""
|
|
1180
|
+
img = _plate(bg=(251, 14, 224), aa=2)
|
|
1181
|
+
_, rep = L.postprocess(img, "#FF00FF", size=(120, 200), multi=False)
|
|
1182
|
+
assert "cutout_method" not in rep
|
|
1183
|
+
assert "cutout_table" not in rep
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
# ── fit_thumb: thumbnail cửa hàng, đúng số pixel ────────────────────────────────────────
|
|
1187
|
+
def test_fit_thumb_hits_exact_target_from_real_gemini_sizes():
|
|
1188
|
+
"""Ba size Gemini ĐO ĐƯỢC thật phải ra đúng 3 size cửa hàng, cắt bù dưới 1%."""
|
|
1189
|
+
cases = [((1024, 1024), "1:1"), ((864, 1216), "5:7"), ((1376, 768), "16:9")]
|
|
1190
|
+
for src, preset in cases:
|
|
1191
|
+
target = L.THUMB_PRESETS[preset]
|
|
1192
|
+
out, info = L.fit_thumb(Image.new("RGB", src, (10, 20, 30)), target)
|
|
1193
|
+
assert out.size == target, f"{preset}: ra {out.size}, cần {target}"
|
|
1194
|
+
assert info["lost_frac"] < 0.01, f"{preset}: cắt mất {info['lost_frac']:.3%}"
|
|
1195
|
+
assert not info["upscaled"]
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
def test_fit_thumb_anchor_top_keeps_top_edge():
|
|
1199
|
+
"""Thumb dọc hay có logo ở trên — anchor='top' phải giữ nguyên hàng pixel đầu."""
|
|
1200
|
+
_, info = L.fit_thumb(Image.new("RGB", (864, 1216)), (540, 756), anchor="top")
|
|
1201
|
+
assert info["crop"][1] == 0
|
|
1202
|
+
_, mid = L.fit_thumb(Image.new("RGB", (864, 1216)), (540, 756))
|
|
1203
|
+
assert mid["crop"][1] > 0 # center thì phải cắt cả hai đầu
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
def test_fit_thumb_flags_upscale():
|
|
1207
|
+
"""Nguồn nhỏ hơn đích -> phải BÁO, vì thumb phóng to sẽ mềm."""
|
|
1208
|
+
_, info = L.fit_thumb(Image.new("RGB", (300, 300)), (1024, 1024))
|
|
1209
|
+
assert info["upscaled"] and info["scale"] > 1
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
def test_fit_thumb_extreme_ratio_still_exact():
|
|
1213
|
+
"""Tỉ lệ nguồn lệch xa mục tiêu vẫn phải ra ĐÚNG size (chỉ cắt nhiều hơn)."""
|
|
1214
|
+
out, info = L.fit_thumb(Image.new("RGB", (2000, 400)), (540, 756))
|
|
1215
|
+
assert out.size == (540, 756)
|
|
1216
|
+
assert info["lost_frac"] > 0.5 # panorama -> 5:7 thì mất rất nhiều, đúng như kỳ vọng
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
def test_fit_thumb_rejects_bad_target():
|
|
1220
|
+
for bad in [(0, 100), (100, 0), (-5, 10)]:
|
|
1221
|
+
try:
|
|
1222
|
+
L.fit_thumb(Image.new("RGB", (100, 100)), bad)
|
|
1223
|
+
except ValueError:
|
|
1224
|
+
continue
|
|
1225
|
+
raise AssertionError(f"target {bad} phải bị từ chối")
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
# ── strip_bg_residue / bg_residue: dọn nền SÓT theo màu nền ĐO ĐƯỢC ─────────────────────
|
|
1229
|
+
def _film(size=(200, 200), bg=(11, 208, 9), subject=(210, 170, 60)):
|
|
1230
|
+
"""Ảnh RGBA mô phỏng ca hỏng thật: nền còn nguyên dưới dạng màng BÁN TRONG SUỐT.
|
|
1231
|
+
|
|
1232
|
+
Đúng thứ đo được khi chroma-key theo màu key YÊU CẦU trong lúc model vẽ nền sắc độ khác:
|
|
1233
|
+
alpha>8 phủ 100% khung, chủ thể đục ở giữa.
|
|
1234
|
+
"""
|
|
1235
|
+
w, h = size
|
|
1236
|
+
arr = np.zeros((h, w, 4), np.uint8)
|
|
1237
|
+
arr[..., :3] = bg
|
|
1238
|
+
arr[..., 3] = 60 # màng nền: bán trong suốt, KHÔNG phải 0
|
|
1239
|
+
arr[h // 4:3 * h // 4, w // 4:3 * w // 4, :3] = subject
|
|
1240
|
+
arr[h // 4:3 * h // 4, w // 4:3 * w // 4, 3] = 255
|
|
1241
|
+
return Image.fromarray(arr, "RGBA")
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
def test_bg_residue_sees_film_that_border_impurity_cannot():
|
|
1245
|
+
img = _film()
|
|
1246
|
+
assert L.bg_residue(img, "#0BD009") > 0.5
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
def test_strip_bg_residue_removes_film_and_keeps_subject():
|
|
1250
|
+
img = _film()
|
|
1251
|
+
out, killed = L.strip_bg_residue(img, "#0BD009")
|
|
1252
|
+
a = np.asarray(out)
|
|
1253
|
+
assert killed > 0
|
|
1254
|
+
assert L.bg_residue(out, "#0BD009") < 0.01
|
|
1255
|
+
# chủ thể còn nguyên vẹn, đục hoàn toàn
|
|
1256
|
+
assert (a[60:140, 60:140, 3] == 255).all()
|
|
1257
|
+
# bbox co về đúng chủ thể thay vì cả khung
|
|
1258
|
+
assert L.content_bbox(out) == (50, 50, 150, 150)
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
def test_strip_bg_residue_keeps_interior_art_of_bg_colour():
|
|
1262
|
+
"""Chi tiết art TRÙNG màu nền nhưng nằm KÍN trong chủ thể phải sống.
|
|
1263
|
+
|
|
1264
|
+
Đây là ràng buộc liên thông — bản thử xoá theo màu/hue KHÔNG kèm liên thông đã gặm mép
|
|
1265
|
+
thành rỗ. Muốn bị xoá, một vùng phải nối được ra tới nền thật.
|
|
1266
|
+
"""
|
|
1267
|
+
img = _film()
|
|
1268
|
+
a = np.array(img)
|
|
1269
|
+
a[95:105, 95:105, :3] = (11, 208, 9) # đốm màu-nền giữa lòng chủ thể
|
|
1270
|
+
a[95:105, 95:105, 3] = 255
|
|
1271
|
+
out, _ = L.strip_bg_residue(Image.fromarray(a, "RGBA"), "#0BD009")
|
|
1272
|
+
assert (np.asarray(out)[95:105, 95:105, 3] == 255).all()
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
def test_strip_bg_residue_noop_when_already_clean():
|
|
1276
|
+
img = Image.new("RGBA", (200, 200), (0, 0, 0, 0))
|
|
1277
|
+
img.paste(Image.new("RGBA", (80, 80), (210, 170, 60, 255)), (60, 60))
|
|
1278
|
+
out, killed = L.strip_bg_residue(img, "#0BD009")
|
|
1279
|
+
assert killed == 0
|
|
1280
|
+
assert np.array_equal(np.asarray(out), np.asarray(img))
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
def test_postprocess_uses_bg_hex_over_requested_key():
|
|
1284
|
+
"""Đo thật: model vẽ nền #0BD009 khi được yêu cầu #00FF00. Key theo màu YÊU CẦU để lại
|
|
1285
|
+
NGUYÊN nền; key theo màu ĐO ĐƯỢC thì sạch.
|
|
1286
|
+
|
|
1287
|
+
Test này ghim ca đó trên đường ĐƠN PHƯƠNG PHÁP (`multi=False`) — nơi lỗi gốc tồn tại và
|
|
1288
|
+
nơi `bg_hex` là thứ duy nhất cứu được nó. Số đo tay: chủ thể 80x80 trên canvas 200x200
|
|
1289
|
+
= 6400/40000 = 0.16, nên coverage đúng phải là 0.16; key theo #00FF00 cho 1.0000, tức
|
|
1290
|
+
TOÀN BỘ nền sống sót thành "nội dung".
|
|
1291
|
+
"""
|
|
1292
|
+
gen = Image.new("RGB", (200, 200), (11, 208, 9))
|
|
1293
|
+
gen.paste(Image.new("RGB", (80, 80), (210, 170, 60)), (60, 60))
|
|
1294
|
+
src = Image.new("RGBA", (64, 64), (0, 0, 0, 0))
|
|
1295
|
+
_, bad = L.postprocess(gen, "#00FF00", src=src, multi=False)
|
|
1296
|
+
_, good = L.postprocess(gen, "#00FF00", src=src, bg_hex="#0BD009", multi=False)
|
|
1297
|
+
assert bad["bg_color_used"] == "#00FF00"
|
|
1298
|
+
assert good["bg_color_used"] == "#0BD009"
|
|
1299
|
+
assert good["bg_residue"] <= bad["bg_residue"]
|
|
1300
|
+
assert good["coverage"] < bad["coverage"], ( # nền không còn bị tính là nội dung
|
|
1301
|
+
f"key theo màu yêu cầu phải để sót nền: {bad['coverage']} vs {good['coverage']}"
|
|
1302
|
+
)
|
|
1303
|
+
assert bad["coverage"] > 0.95, f"ca lỗi gốc: nền sống sót gần trọn khung, {bad['coverage']}"
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
def test_postprocess_multi_finds_drifted_key_without_being_told():
|
|
1307
|
+
"""Đường ĐA PHƯƠNG PHÁP phải tự dò ra màu nền lệch, KHÔNG cần ai truyền `bg_hex`.
|
|
1308
|
+
|
|
1309
|
+
Cùng ảnh với test trên. Đời cũ (`multi=False`, không `bg_hex`) đo được coverage 1.0000 —
|
|
1310
|
+
nền sống sót trọn khung. `multi=True` phải tự đo ra #0BD009 qua modal_border_color và
|
|
1311
|
+
cho ra ĐÚNG kết quả của nhánh được-truyền-tay (0.16), vì màu nền là thứ đo được chứ
|
|
1312
|
+
không phải thứ phải hỏi. Đây là lý do tồn tại của cả khối best_cutout.
|
|
1313
|
+
"""
|
|
1314
|
+
gen = Image.new("RGB", (200, 200), (11, 208, 9))
|
|
1315
|
+
gen.paste(Image.new("RGB", (80, 80), (210, 170, 60)), (60, 60))
|
|
1316
|
+
src = Image.new("RGBA", (64, 64), (0, 0, 0, 0))
|
|
1317
|
+
_, auto = L.postprocess(gen, "#00FF00", src=src) # multi bật mặc định
|
|
1318
|
+
_, told = L.postprocess(gen, "#00FF00", src=src, bg_hex="#0BD009")
|
|
1319
|
+
|
|
1320
|
+
assert auto["bg_color_used"] == "#0BD009", auto["bg_color_used"]
|
|
1321
|
+
assert auto["bg_source"] == "mode_vien", auto["bg_source"]
|
|
1322
|
+
assert abs(auto["coverage"] - told["coverage"]) < 1e-9, (
|
|
1323
|
+
f"tự dò phải ra đúng kết quả được-truyền-tay: {auto['coverage']} vs {told['coverage']}"
|
|
1324
|
+
)
|
|
1325
|
+
assert auto["coverage"] < 0.95, "không được để nền sống sót trọn khung như đời cũ"
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
# ── compare_sheet: trang HTML đối chiếu gốc↔mới ─────────────────────────────────────────
|
|
1329
|
+
def _cs_groups():
|
|
1330
|
+
o = Image.new("RGBA", (64, 64), (200, 160, 40, 255))
|
|
1331
|
+
v1 = Image.new("RGBA", (64, 64), (240, 200, 60, 255))
|
|
1332
|
+
v2 = Image.new("RGBA", (64, 64), (180, 140, 20, 255))
|
|
1333
|
+
cell = Image.new("RGBA", (80, 80), (200, 80, 80, 255))
|
|
1334
|
+
return [("coin", o, [("agy1", v1), ("gpt1", v2)]), ("cells", None, [("cell1", cell)])]
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
def test_compare_sheet_is_self_contained():
|
|
1338
|
+
"""Không được tham chiếu file/CDN ngoài — trang phải gửi đi một mình vẫn xem được."""
|
|
1339
|
+
html = L.compare_sheet(_cs_groups())
|
|
1340
|
+
import re
|
|
1341
|
+
assert not re.findall(r'(?:src|href)="(?!data:)([^"]+)', html)
|
|
1342
|
+
assert "base64," in html
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
def test_compare_sheet_groups_and_labels_present():
|
|
1346
|
+
html = L.compare_sheet(_cs_groups())
|
|
1347
|
+
for token in ["coin", "cells", "agy1", "gpt1", "cell1", "GỐC"]:
|
|
1348
|
+
assert token in html, f"thiếu {token!r}"
|
|
1349
|
+
assert html.count('class="grp"') == 2
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
def test_compare_sheet_embeds_original_once_per_group():
|
|
1353
|
+
"""Gốc nhúng 1 lần/nhóm, KHÔNG lặp trong từng thẻ — lô lớn mà lặp thì file phình vô ích."""
|
|
1354
|
+
html = L.compare_sheet(_cs_groups())
|
|
1355
|
+
# 1 thẻ gốc + 3 biến thể + 1 bản gốc trong bảng ORIG (nhóm 'cells' không có gốc)
|
|
1356
|
+
assert html.count("base64,") == 5
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
def test_compare_sheet_no_flip_when_original_missing():
|
|
1360
|
+
"""Nhóm không có gốc thì thẻ KHÔNG được có nút lật — không có gì để lật về."""
|
|
1361
|
+
html = L.compare_sheet([("cells", None, [("cell1", Image.new("RGBA", (32, 32), (1, 2, 3, 255)))])])
|
|
1362
|
+
assert 'data-g="0"' in html # vẫn dựng được section
|
|
1363
|
+
assert 'class="card can-flip"' not in html # nhưng không thẻ nào lật được
|
|
1364
|
+
assert 'class="ov"' not in html # và không có lớp ảnh gốc chờ lật
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
def test_compare_sheet_escapes_labels():
|
|
1368
|
+
"""Nhãn/tên asset đi thẳng vào HTML — phải escape, không để chèn thẻ."""
|
|
1369
|
+
evil = '<img src=x onerror=alert(1)>"'
|
|
1370
|
+
html = L.compare_sheet([(evil, None, [(evil, Image.new("RGBA", (8, 8), (0, 0, 0, 255)))])])
|
|
1371
|
+
# Chuỗi vẫn HIỆN ra dưới dạng chữ (đúng), nhưng phải mất khả năng thành thẻ/thoát attribute.
|
|
1372
|
+
assert "<img src=x" not in html, "nhãn chèn được thẻ <img> thật"
|
|
1373
|
+
assert "<img src=x" in html, "nhãn không được escape"
|
|
1374
|
+
assert """ in html, 'dấu " trong nhãn không được escape -> thoát được attribute alt'
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
# ------------------------------------------------------------------ PHÓNG TO (upscale)
|
|
1378
|
+
# Backend thật (Real-ESRGAN) cần torch + trọng số tải về, nên MỌI test ở đây dùng backend
|
|
1379
|
+
# GIẢ. Đó không phải né tránh: nó khoá đúng phần imglib chịu trách nhiệm — điều phối RGBA,
|
|
1380
|
+
# loang màu, chấm điểm, chọn bản — độc lập với chất lượng của model.
|
|
1381
|
+
|
|
1382
|
+
def _fake_x4(arr):
|
|
1383
|
+
"""Backend giả: nhân đôi pixel 4 lần (NEAREST). Sắc nét, không bịa gì."""
|
|
1384
|
+
return np.repeat(np.repeat(arr, 4, axis=0), 4, axis=1)
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
def _blur_x4(arr):
|
|
1388
|
+
"""Backend giả kiểu 'mềm': phóng NEAREST rồi làm mờ. Dùng để dựng ứng viên KÉM."""
|
|
1389
|
+
im = Image.fromarray(arr, "RGB").resize(
|
|
1390
|
+
(arr.shape[1] * 4, arr.shape[0] * 4), Image.BICUBIC
|
|
1391
|
+
).filter(ImageFilter.GaussianBlur(2.0))
|
|
1392
|
+
return np.asarray(im)
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
def _sprite(size=(40, 40)):
|
|
1396
|
+
"""Sprite RGBA có mép mềm, nằm giữa nền TRONG SUỐT nhưng RGB vẫn là màu key."""
|
|
1397
|
+
w, h = size
|
|
1398
|
+
# Nền: magenta ĐỤC trong kênh RGB nhưng alpha 0 — đúng thứ unmix_cutout để lại.
|
|
1399
|
+
a = np.zeros((h, w, 4), np.uint8)
|
|
1400
|
+
a[..., :3] = (255, 0, 255)
|
|
1401
|
+
yy, xx = np.mgrid[0:h, 0:w]
|
|
1402
|
+
r = np.sqrt((xx - w / 2) ** 2 + (yy - h / 2) ** 2)
|
|
1403
|
+
inside = r <= min(w, h) * 0.35
|
|
1404
|
+
a[inside, :3] = (40, 120, 220)
|
|
1405
|
+
a[inside, 3] = 255
|
|
1406
|
+
return Image.fromarray(a, "RGBA")
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
def test_bleed_removes_key_colour_from_transparent_area():
|
|
1410
|
+
"""_bleed_rgb phải QUÉT SẠCH màu nền khỏi vùng trong suốt trước khi phóng to.
|
|
1411
|
+
|
|
1412
|
+
Đây là bước dễ bỏ quên nhất của cả tính năng: sau tách nền, pixel nền vẫn mang màu key
|
|
1413
|
+
trong kênh RGB (alpha 0 nên vô hình). Model phóng to chỉ nhận RGB — nó thấy magenta
|
|
1414
|
+
thật và kéo vào mép, làm hỏng đúng cái viền mà đường tách nền vừa làm sạch.
|
|
1415
|
+
"""
|
|
1416
|
+
img = _sprite()
|
|
1417
|
+
a = np.asarray(img)
|
|
1418
|
+
opaque = a[..., 3] > 0
|
|
1419
|
+
filled = L._bleed_rgb(a[..., :3].astype(np.float32), opaque)
|
|
1420
|
+
key = np.array([255, 0, 255], np.float32)
|
|
1421
|
+
d = np.abs(filled - key).sum(axis=2)
|
|
1422
|
+
assert d.min() > 60.0, f"vẫn còn pixel màu key sau khi loang (min |Δ| = {d.min():.1f})"
|
|
1423
|
+
# Pixel ĐỤC phải giữ nguyên màu — loang chỉ được điền chỗ trong suốt.
|
|
1424
|
+
assert np.array_equal(filled[opaque], a[..., :3][opaque].astype(np.float32))
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
def test_upscale_rgba_does_not_pull_key_colour_into_edge():
|
|
1428
|
+
"""Hết đường: phóng to xong, mép sprite KHÔNG được ám màu nền."""
|
|
1429
|
+
img = _sprite()
|
|
1430
|
+
big = L.upscale_rgba(img, _fake_x4)
|
|
1431
|
+
assert big.size == (img.width * 4, img.height * 4)
|
|
1432
|
+
a = np.asarray(big)
|
|
1433
|
+
# Nhìn ở nơi MẮT THẤY: pixel có alpha đáng kể.
|
|
1434
|
+
vis = a[a[..., 3] > 40][:, :3].astype(np.float32)
|
|
1435
|
+
magenta_ish = (vis[:, 0] > 150) & (vis[:, 1] < 90) & (vis[:, 2] > 150)
|
|
1436
|
+
assert not magenta_ish.any(), f"{int(magenta_ish.sum())} px mép bị ám màu nền"
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
def test_upscale_rgba_routes_alpha_through_backend():
|
|
1440
|
+
"""Alpha phải đi QUA backend, không phải LANCZOS — đo được là sai số matte giảm hơn nửa.
|
|
1441
|
+
|
|
1442
|
+
Cách phân biệt: backend giả nhân đôi pixel (bậc thang cứng), còn LANCZOS nội suy mềm.
|
|
1443
|
+
Mép matte có giá trị trung gian hay không sẽ tố cáo đường nào đã chạy.
|
|
1444
|
+
"""
|
|
1445
|
+
img = _sprite()
|
|
1446
|
+
hard = np.asarray(L.upscale_rgba(img, _fake_x4, alpha_esrgan=True))[..., 3]
|
|
1447
|
+
soft = np.asarray(L.upscale_rgba(img, _fake_x4, alpha_esrgan=False))[..., 3]
|
|
1448
|
+
mid_hard = int(((hard > 20) & (hard < 235)).sum())
|
|
1449
|
+
mid_soft = int(((soft > 20) & (soft < 235)).sum())
|
|
1450
|
+
assert mid_hard < mid_soft, (
|
|
1451
|
+
f"alpha không đi qua backend: bậc trung gian {mid_hard} vs LANCZOS {mid_soft}")
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
def test_score_upscale_punishes_blur():
|
|
1455
|
+
"""Tiêu chí `blur` phải phạt bản mềm — đó là lý do cả tính năng tồn tại."""
|
|
1456
|
+
img = _sprite()
|
|
1457
|
+
sharp = L.upscale_rgba(img, _fake_x4)
|
|
1458
|
+
soft = img.resize(sharp.size, Image.LANCZOS).filter(ImageFilter.GaussianBlur(2.0))
|
|
1459
|
+
assert L.score_upscale(img, sharp)["blur"] < L.score_upscale(img, soft)["blur"]
|
|
1460
|
+
|
|
1461
|
+
|
|
1462
|
+
def test_score_upscale_ring_catches_overshoot():
|
|
1463
|
+
"""`ring` phải bắt quầng sáng — thứ `blur` chấm NGƯỢC (quầng làm gradient mạnh lên)."""
|
|
1464
|
+
img = _sprite()
|
|
1465
|
+
base = L.upscale_rgba(img, _fake_x4)
|
|
1466
|
+
a = np.asarray(base).astype(np.float32)
|
|
1467
|
+
a[..., :3] = np.clip((a[..., :3] - 128) * 2.2 + 128, 0, 255) # đẩy tương phản -> quầng
|
|
1468
|
+
over = Image.fromarray(a.astype(np.uint8), "RGBA")
|
|
1469
|
+
s_base, s_over = L.score_upscale(img, base), L.score_upscale(img, over)
|
|
1470
|
+
assert s_over["ring"] > s_base["ring"], "ring không thấy quầng"
|
|
1471
|
+
# Và đây là chỗ blur một mình sẽ chọn SAI: nó cho bản quầng điểm ngang hoặc tốt hơn.
|
|
1472
|
+
assert s_over["blur"] <= s_base["blur"] + 1e-9, (
|
|
1473
|
+
"tiền đề của test hỏng — bản quầng phải không hề 'mờ' hơn theo blur")
|
|
1474
|
+
assert s_over["score"] > s_base["score"], "tổng điểm vẫn chọn bản quầng"
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
def test_best_upscale_without_backend_still_returns_exact_size():
|
|
1478
|
+
"""Thiếu torch -> chỉ còn LANCZOS, nhưng KHÔNG được lỗi và size phải đúng tuyệt đối."""
|
|
1479
|
+
img = _sprite((30, 20))
|
|
1480
|
+
out, rep = L.best_upscale(img, (97, 65), backend=None)
|
|
1481
|
+
assert out.size == (97, 65)
|
|
1482
|
+
assert rep["upscale_method"] == "lanczos"
|
|
1483
|
+
assert rep["upscale_candidates"] == ["lanczos"]
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
def test_best_upscale_survives_broken_backend():
|
|
1487
|
+
"""Model nổ giữa chừng KHÔNG được làm hỏng cả pipeline — rơi về LANCZOS và ghi lại lỗi."""
|
|
1488
|
+
def boom(arr):
|
|
1489
|
+
raise RuntimeError("hết VRAM giả lập")
|
|
1490
|
+
|
|
1491
|
+
img = _sprite((24, 24))
|
|
1492
|
+
out, rep = L.best_upscale(img, (72, 72), backend=boom)
|
|
1493
|
+
assert out.size == (72, 72)
|
|
1494
|
+
assert rep["upscale_method"] == "lanczos"
|
|
1495
|
+
assert any("esrgan" in e for e in rep.get("upscale_errors", [])), rep
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
def test_best_upscale_picks_sharp_over_blurry_backend():
|
|
1499
|
+
"""Bộ chấm điểm phải CHỌN ĐƯỢC: backend sắc thắng, backend mềm thua LANCZOS."""
|
|
1500
|
+
img = _sprite((32, 32))
|
|
1501
|
+
_, rep_sharp = L.best_upscale(img, (128, 128), backend=_fake_x4)
|
|
1502
|
+
assert rep_sharp["upscale_method"] == "esrgan", rep_sharp["upscale_table"]
|
|
1503
|
+
_, rep_soft = L.best_upscale(img, (128, 128), backend=_blur_x4)
|
|
1504
|
+
assert rep_soft["upscale_method"] == "lanczos", rep_soft["upscale_table"]
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
def test_best_upscale_adds_pre_candidate_only_beyond_4x():
|
|
1508
|
+
"""`esrgan-pre` chỉ hợp lý khi đích > 4x. Dưới đó nó THU NHỎ nguồn trước khi phóng."""
|
|
1509
|
+
img = _sprite((16, 16))
|
|
1510
|
+
_, r3 = L.best_upscale(img, (48, 48), backend=_fake_x4)
|
|
1511
|
+
_, r6 = L.best_upscale(img, (96, 96), backend=_fake_x4)
|
|
1512
|
+
assert "esrgan-pre" not in r3["upscale_candidates"]
|
|
1513
|
+
assert "esrgan-pre" in r6["upscale_candidates"]
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
def test_score_upscale_disqualifies_a_different_image():
|
|
1517
|
+
"""Lưới an toàn: bản phóng ra ẢNH KHÁC HẲN phải bị loại thẳng, dù có sắc nét đến đâu."""
|
|
1518
|
+
img = _sprite((32, 32))
|
|
1519
|
+
other = Image.new("RGBA", (128, 128), (250, 240, 40, 255))
|
|
1520
|
+
m = L.score_upscale(img, other)
|
|
1521
|
+
assert "bia_noi_dung" in m["disqualified"], m
|
|
1522
|
+
|
|
1523
|
+
|
|
1524
|
+
def test_score_upscale_disqualifies_destroyed_matte():
|
|
1525
|
+
img = _sprite((32, 32))
|
|
1526
|
+
big = L.upscale_rgba(img, _fake_x4)
|
|
1527
|
+
a = np.asarray(big).copy()
|
|
1528
|
+
a[..., 3] = 255 # matte bị xoá sạch -> sprite thành khối vuông
|
|
1529
|
+
m = L.score_upscale(img, Image.fromarray(a, "RGBA"))
|
|
1530
|
+
assert "lech_matte" in m["disqualified"], m
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
def test_fit_into_upscales_only_when_enlarging():
|
|
1534
|
+
"""Chỉ gọi model khi PHÓNG TO. Thu nhỏ thì LANCZOS đã là tốt nhất — gọi model là phí."""
|
|
1535
|
+
calls = []
|
|
1536
|
+
|
|
1537
|
+
def spy(arr):
|
|
1538
|
+
calls.append(arr.shape)
|
|
1539
|
+
return _fake_x4(arr)
|
|
1540
|
+
|
|
1541
|
+
big = _sprite((80, 80))
|
|
1542
|
+
L.fit_into(big, (40, 40), (0, 0, 40, 40), upscale=spy)
|
|
1543
|
+
assert calls == [], "đã gọi model khi THU NHỎ"
|
|
1544
|
+
|
|
1545
|
+
small = _sprite((20, 20))
|
|
1546
|
+
rep: dict = {}
|
|
1547
|
+
out = L.fit_into(small, (80, 80), (0, 0, 80, 80), upscale=spy, report=rep)
|
|
1548
|
+
assert calls, "không gọi model khi PHÓNG TO"
|
|
1549
|
+
assert out.size == (80, 80)
|
|
1550
|
+
assert rep["upscale_method"] == "esrgan", rep
|
|
1551
|
+
assert rep["upscale_from"] == [20, 20] and rep["upscale_to"] == [80, 80]
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
def test_fit_into_without_upscaler_matches_old_behaviour():
|
|
1555
|
+
"""Không truyền backend -> hành vi y hệt đời cũ (LANCZOS), size và vị trí không đổi."""
|
|
1556
|
+
img = _sprite((20, 20))
|
|
1557
|
+
a = L.fit_into(img, (60, 60), (0, 0, 60, 60))
|
|
1558
|
+
b = img.convert("RGBA").resize((60, 60), Image.LANCZOS)
|
|
1559
|
+
canvas = Image.new("RGBA", (60, 60), (0, 0, 0, 0))
|
|
1560
|
+
canvas.paste(b, (0, 0))
|
|
1561
|
+
assert np.array_equal(np.asarray(a), np.asarray(canvas))
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
def test_fit_thumb_upscales_and_reports_method():
|
|
1565
|
+
img = _sprite((50, 50))
|
|
1566
|
+
out, info = L.fit_thumb(img, (200, 200), upscale=_fake_x4)
|
|
1567
|
+
assert out.size == (200, 200)
|
|
1568
|
+
assert info["upscaled"] is True
|
|
1569
|
+
assert info["upscale_method"] == "esrgan", info
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
def test_fit_thumb_downscale_untouched_by_upscaler():
|
|
1573
|
+
"""Thumb thu nhỏ (ca thường gặp) không được đổi hành vi khi có backend."""
|
|
1574
|
+
img = _sprite((400, 400))
|
|
1575
|
+
a, ia = L.fit_thumb(img, (100, 100), upscale=_fake_x4)
|
|
1576
|
+
b, ib = L.fit_thumb(img, (100, 100))
|
|
1577
|
+
assert np.array_equal(np.asarray(a), np.asarray(b))
|
|
1578
|
+
assert ia["upscaled"] is False and ia.get("upscale_method") is None
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
def _detailed_on_key(size=(48, 48), key=(0, 255, 0)):
|
|
1582
|
+
"""Như _subject_on_key nhưng chủ thể CÓ HOẠ TIẾT — cần cho mọi test về độ sắc.
|
|
1583
|
+
|
|
1584
|
+
Chủ thể màu đặc làm năng lượng gradient bằng 0, tức là không có gì để làm sắc, và mọi
|
|
1585
|
+
ứng viên phóng to đều tương đương (xem test_score_upscale_flat_source_is_not_called_blurry).
|
|
1586
|
+
"""
|
|
1587
|
+
img = Image.new("RGB", size, key)
|
|
1588
|
+
d = ImageDraw.Draw(img)
|
|
1589
|
+
w, h = size
|
|
1590
|
+
d.rectangle((w // 4, h // 4, w * 3 // 4, h * 3 // 4), fill=(200, 30, 40))
|
|
1591
|
+
for i in range(w // 4 + 2, w * 3 // 4 - 1, 3):
|
|
1592
|
+
d.line((i, h // 4 + 2, i, h * 3 // 4 - 2), fill=(250, 230, 60))
|
|
1593
|
+
return img
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
def test_score_upscale_flat_source_is_not_called_blurry():
|
|
1597
|
+
"""Ảnh nguồn PHẲNG: không có cạnh nào để làm sắc -> blur phải là 0, không phải 1.
|
|
1598
|
+
|
|
1599
|
+
Không có nhánh riêng cho ca này thì e_nn ~ 0 biến sharp thành 0/0, blur = 1.0 cho MỌI
|
|
1600
|
+
ứng viên, điểm hoà hết, và bản 'thắng' rơi vào tay thứ tự dict — chọn bừa mà vẫn báo
|
|
1601
|
+
cáo như một quyết định có cơ sở.
|
|
1602
|
+
"""
|
|
1603
|
+
flat = Image.new("RGBA", (24, 24), (200, 30, 40, 255))
|
|
1604
|
+
for cand in (flat.resize((96, 96), Image.LANCZOS), L.upscale_rgba(flat, _fake_x4)):
|
|
1605
|
+
m = L.score_upscale(flat, cand)
|
|
1606
|
+
assert m["blur"] == 0.0, m
|
|
1607
|
+
assert m["score"] < 0.5, m
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
def test_postprocess_reports_upscale_when_target_bigger():
|
|
1611
|
+
"""Đường end-to-end: bản sinh nhỏ hơn khung đích -> report phải nói đã phóng bằng cách nào."""
|
|
1612
|
+
gen = _detailed_on_key()
|
|
1613
|
+
out, rep = L.postprocess(gen, "#00FF00", size=(200, 200), upscale=_fake_x4)
|
|
1614
|
+
assert out is not None and out.size == (200, 200)
|
|
1615
|
+
assert rep.get("upscale_method") == "esrgan", {
|
|
1616
|
+
k: v for k, v in rep.items() if k.startswith("upscale")}
|
|
1617
|
+
assert rep["upscale_factor"] > 1.0
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
def test_postprocess_without_upscaler_reports_no_method():
|
|
1621
|
+
gen = _detailed_on_key()
|
|
1622
|
+
out, rep = L.postprocess(gen, "#00FF00", size=(200, 200))
|
|
1623
|
+
assert out is not None and out.size == (200, 200)
|
|
1624
|
+
assert rep.get("upscale_method") == "lanczos", rep.get("upscale_table")
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
def main():
|
|
1628
|
+
tests = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
|
|
1629
|
+
failed = 0
|
|
1630
|
+
for t in tests:
|
|
1631
|
+
try:
|
|
1632
|
+
t()
|
|
1633
|
+
print(f" PASS {t.__name__}")
|
|
1634
|
+
except Exception:
|
|
1635
|
+
failed += 1
|
|
1636
|
+
print(f" FAIL {t.__name__}")
|
|
1637
|
+
traceback.print_exc()
|
|
1638
|
+
print(f"\n{len(tests) - failed}/{len(tests)} passed")
|
|
1639
|
+
# Minor fix: trả về SỐ LƯỢNG test fail thật sự, không phải cờ 0/1. cmd_selftest()
|
|
1640
|
+
# cộng trực tiếp giá trị trả về của test_imglib.main() và test_restyle.main() để ra
|
|
1641
|
+
# tổng số fail — nếu hàm này chỉ trả cờ 1/0, "TOTAL: N failed" sẽ SAI bất cứ khi nào
|
|
1642
|
+
# có từ 2 test trở lên cùng fail ở đây (chỉ cộng thêm 1, không phải N).
|
|
1643
|
+
return failed
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
if __name__ == "__main__":
|
|
1647
|
+
sys.exit(main())
|