後端(apps/api/src/tachie/):立繪 manifest(身體姿勢/服裝/表情眉眼口/ 效果層/微動態的資產目錄,服裝目錄有 M-1 登錄時優先採用);表情解析依 情緒引擎六狀態對照眉/眼/口/效果/姿勢,依 RelationshipStage 分層解鎖 (陌生~認識/朋友/摯友/羈絆,哭臉限羈絆才會出現),依角色外顯度縮放 差分幅度(magnitude = expressiveness × 情緒強度);emotionTag(實際 套用)與 rawEmotionTag(情緒引擎真實判定)分離,讓文字生成與表情解析 維持兩條獨立資料流,「文字與立繪故意不一致」是這個設計的自然結果, 不需要額外邏輯;視線方向依思考/迴避/警戒切換。 前端(apps/web/components/TachieStage.tsx):以 PixiJS 實作分層合成 與眨眼/呼吸微動態,預留 TachieRenderer 介面供未來 Live2D Cubism SDK 實作(未引入任何 Live2D 相依或授權,純架構佔位);接上 ChatView 取代 H 群組的佔位立繪,聊天回應後先查詢表情、延遲約 220ms 才顯示文字, 在非串流架構下盡力模擬「表情先變化、文字後出現」。 以 scratchpad 暫裝 playwright-core 實測瀏覽器行為(本環境無 chromium-cli),確認情緒變化即時反映在立繪、微動態持續運作。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
32 lines
1.0 KiB
TypeScript
32 lines
1.0 KiB
TypeScript
import { Controller, Get, Param, Query } from "@nestjs/common";
|
|
import { ManifestService } from "./manifest.service.js";
|
|
import { ExpressionResolverService } from "./expression-resolver.service.js";
|
|
|
|
@Controller("tachie")
|
|
export class TachieController {
|
|
constructor(
|
|
private readonly manifest: ManifestService,
|
|
private readonly expression: ExpressionResolverService,
|
|
) {}
|
|
|
|
@Get(":characterId/manifest")
|
|
async getManifest(@Param("characterId") characterId: string) {
|
|
return this.manifest.getManifest(characterId);
|
|
}
|
|
|
|
@Get(":characterId/:userId/expression")
|
|
async getExpression(
|
|
@Param("characterId") characterId: string,
|
|
@Param("userId") userId: string,
|
|
@Query("now") now?: string,
|
|
@Query("isThinking") isThinking?: string,
|
|
@Query("isDeflecting") isDeflecting?: string,
|
|
) {
|
|
return this.expression.resolveExpression(characterId, userId, {
|
|
now: now ? new Date(now) : undefined,
|
|
isThinking: isThinking === "true",
|
|
isDeflecting: isDeflecting === "true",
|
|
});
|
|
}
|
|
}
|