feat(*): 画布助手 - 新增 Live2D 配置导入与模型渲染支持

This commit is contained in:
ddCat committed 2026-09-21 14:11:29 +08:00
1 parent b8eefdad70
commit c5b81f696c
40 files changed
+1668 -59

No files matched your search

@@ -6,33 +6,33 @@ export const AGENT_LAUNCHER_POSITION_KEY = "canvas:agent-launcher-position:v1";
export const AGENT_LAUNCHER_SIZE = 76;
const MARGIN = 20; // Includes the label below the orb.
export function clampAgentLauncherPosition(position: AgentLauncherPosition, viewport: AgentLauncherViewport): AgentLauncherPosition {
const clamp = (value: number, extent: number) => {
const available = Math.max(0, extent - AGENT_LAUNCHER_SIZE);
export function clampAgentLauncherPosition(position: AgentLauncherPosition, viewport: AgentLauncherViewport, size = { width: AGENT_LAUNCHER_SIZE, height: AGENT_LAUNCHER_SIZE }): AgentLauncherPosition {
const clamp = (value: number, extent: number, dimension: number) => {
const available = Math.max(0, extent - dimension);
const margin = Math.min(MARGIN, available / 2);
return Math.min(Math.max(value, margin), available - margin);
};
return { right: clamp(position.right, viewport.width), bottom: clamp(position.bottom, viewport.height) };
return { right: clamp(position.right, viewport.width, size.width), bottom: clamp(position.bottom, viewport.height, size.height) };
}
export function restoreAgentLauncherPosition(raw: string | null, viewport: AgentLauncherViewport): AgentLauncherPosition {
export function restoreAgentLauncherPosition(raw: string | null, viewport: AgentLauncherViewport, size?: AgentLauncherViewport): AgentLauncherPosition {
if (raw) {
try {
const value = JSON.parse(raw);
if (value && Number.isFinite(value.right) && Number.isFinite(value.bottom)) return clampAgentLauncherPosition(value, viewport);
if (value && Number.isFinite(value.right) && Number.isFinite(value.bottom)) return clampAgentLauncherPosition(value, viewport, size);
} catch {
// Damaged UI preferences must not hide the launcher.
}
}
return clampAgentLauncherPosition({ right: MARGIN, bottom: MARGIN }, viewport);
return clampAgentLauncherPosition({ right: MARGIN, bottom: MARGIN }, viewport, size);
}
export function moveAgentLauncher(gesture: AgentLauncherGesture, x: number, y: number, viewport: AgentLauncherViewport) {
export function moveAgentLauncher(gesture: AgentLauncherGesture, x: number, y: number, viewport: AgentLauncherViewport, size?: AgentLauncherViewport) {
const dx = x - gesture.x;
const dy = y - gesture.y;
const dragged = gesture.dragged || Math.hypot(dx, dy) >= 6;
return {
dragged,
position: clampAgentLauncherPosition(dragged ? { right: gesture.start.right - dx, bottom: gesture.start.bottom - dy } : gesture.start, viewport),
position: clampAgentLauncherPosition(dragged ? { right: gesture.start.right - dx, bottom: gesture.start.bottom - dy } : gesture.start, viewport, size),
};
}