89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
/* =====================================================================
|
|
AvatarPreview — 서연 래스터 아바타 시각 튜닝용 dev 페이지 (인증 없음).
|
|
/dev/avatar-preview. 실 서비스 라우트 아님 — 컴포지션·애니메이션 점검 용도.
|
|
===================================================================== */
|
|
|
|
import { ClientAvatar, type AvatarExpression, type AvatarPersona } from "../components/avatar/ClientAvatar";
|
|
import { AVATAR_EXPRESSION_LIBRARY } from "../components/avatar/ClientAvatar";
|
|
import "./avatar-preview.css";
|
|
|
|
const SEOYEON: AvatarPersona = {
|
|
code: "P1",
|
|
label: "서연(가명) · 고2 · 우울/자살사고",
|
|
ageBand: "teen",
|
|
skinTone: "#F0DDC4",
|
|
hair: { style: "long-straight", color: "#5A4030" },
|
|
outfitColor: "#7C8A92",
|
|
eyeColor: "#7A5A3C",
|
|
accentColor: "#6B5E7D",
|
|
rasterArtSet: "seoyeon-live2d-psb",
|
|
realism: 0.4,
|
|
expressionBias: "sad",
|
|
};
|
|
|
|
// 대표 표정만 노출(28개 전체는 AvatarExpressionLab 참조)
|
|
const PREVIEW_EXPRS: AvatarExpression[] = [
|
|
"neutral",
|
|
"calm",
|
|
"warm",
|
|
"joy",
|
|
"sad",
|
|
"grief",
|
|
"anxious",
|
|
"tired",
|
|
"confused",
|
|
"startled",
|
|
"guarded",
|
|
"determined",
|
|
];
|
|
|
|
export default function AvatarPreview() {
|
|
const rig = typeof window === "undefined" ? "" : new URLSearchParams(window.location.search).get("rig");
|
|
const previewPersona: AvatarPersona = {
|
|
...SEOYEON,
|
|
rasterArtSet:
|
|
rig === "safe"
|
|
? "seoyeon"
|
|
: rig === "v3"
|
|
? "seoyeon-live2d-v3"
|
|
: SEOYEON.rasterArtSet,
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="ap"
|
|
data-avatar-preview="true"
|
|
data-avatar-rig={rig === "safe" ? "safe" : rig === "v3" ? "v3" : "psb"}
|
|
>
|
|
<header className="ap__head">
|
|
<h1>서연 아바타 미리보기 (raster / Live2D식)</h1>
|
|
<p>imagegen gpt-image-2 + BiRefNet 컷아웃 레이어 합성. 호흡·깜빡임·시선 모션 확인.</p>
|
|
</header>
|
|
|
|
<section className="ap__hero">
|
|
<ClientAvatar persona={previewPersona} state="speaking" affect="sad" size={220} />
|
|
<ClientAvatar persona={previewPersona} state="idle" affect="sad" size={220} />
|
|
<ClientAvatar persona={previewPersona} state="listening" affect="warm" size={220} />
|
|
<ClientAvatar persona={previewPersona} state="thinking" affect="anxious" size={220} />
|
|
</section>
|
|
|
|
<section className="ap__grid">
|
|
{PREVIEW_EXPRS.map((expr) => (
|
|
<figure className="ap__cell" key={expr}>
|
|
<ClientAvatar
|
|
persona={previewPersona}
|
|
state="idle"
|
|
affect={expr}
|
|
size={150}
|
|
animated={false}
|
|
showMeta={false}
|
|
/>
|
|
<figcaption>{expr}</figcaption>
|
|
</figure>
|
|
))}
|
|
</section>
|
|
|
|
<p className="ap__count">총 표정 수: {AVATAR_EXPRESSION_LIBRARY.length}</p>
|
|
</div>
|
|
);
|
|
}
|