feat: scene traps, material legends, and scene editor window
Add trap overlays with session state, material legend editor/panel, and a dedicated scene editor window wired through IPC and project persistence. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
/** Простые SVG-иконки ловушек (MVP). */
|
||||
|
||||
import type { SceneTrapStatus, SceneTrapType } from '../../shared/types';
|
||||
|
||||
const TYPE_COLOR: Record<SceneTrapType, string> = {
|
||||
mimic: '#c4783a',
|
||||
explosion: '#e85d3a',
|
||||
poison: '#6bcb5a',
|
||||
pit: '#5a5a6e',
|
||||
arrow: '#d4a017',
|
||||
laser: '#3ad0e8',
|
||||
freeform: '#a78bfa',
|
||||
};
|
||||
|
||||
export function trapAccentColor(type: SceneTrapType, status: SceneTrapStatus = 'inactive'): string {
|
||||
if (status === 'disarmed') return '#6b7280';
|
||||
if (status === 'active') return TYPE_COLOR[type];
|
||||
return TYPE_COLOR[type];
|
||||
}
|
||||
|
||||
export function TrapGlyph({
|
||||
type,
|
||||
status = 'inactive',
|
||||
size = 28,
|
||||
}: {
|
||||
type: SceneTrapType;
|
||||
status?: SceneTrapStatus;
|
||||
size?: number;
|
||||
}) {
|
||||
const stroke = trapAccentColor(type, status);
|
||||
const opacity = status === 'disarmed' ? 0.55 : 1;
|
||||
const common = {
|
||||
width: size,
|
||||
height: size,
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'none',
|
||||
stroke,
|
||||
strokeWidth: 1.8,
|
||||
strokeLinecap: 'round' as const,
|
||||
strokeLinejoin: 'round' as const,
|
||||
opacity,
|
||||
'aria-hidden': true as const,
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case 'mimic':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<rect x="4" y="8" width="16" height="10" rx="1.5" />
|
||||
<path d="M8 8 V6.5 a4 4 0 0 1 8 0 V8" />
|
||||
<path d="M9 13h6M10 16h4" />
|
||||
</svg>
|
||||
);
|
||||
case 'explosion':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<circle cx="12" cy="12" r="3.2" fill={stroke} stroke="none" opacity={opacity * 0.9} />
|
||||
<path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M18.4 5.6l-2.1 2.1M7.7 16.3l-2.1 2.1" />
|
||||
</svg>
|
||||
);
|
||||
case 'poison':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<path d="M12 3c2.5 3.5 5 6.2 5 10a5 5 0 1 1-10 0c0-3.8 2.5-6.5 5-10z" />
|
||||
<circle cx="10" cy="14" r="0.9" fill={stroke} stroke="none" />
|
||||
<circle cx="13.5" cy="15.5" r="0.7" fill={stroke} stroke="none" />
|
||||
</svg>
|
||||
);
|
||||
case 'pit':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<path d="M4 8h16M6 8l2 10h8l2-10" />
|
||||
<path d="M9 14h6" opacity={0.7} />
|
||||
</svg>
|
||||
);
|
||||
case 'arrow':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<path d="M4 12h14" />
|
||||
<path d="M14 7l5 5-5 5" />
|
||||
<path d="M4 9v6" />
|
||||
</svg>
|
||||
);
|
||||
case 'laser':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<circle cx="6" cy="12" r="2.2" />
|
||||
<path d="M9 12h11" strokeWidth="2.4" />
|
||||
<path d="M17 9l3 3-3 3" />
|
||||
</svg>
|
||||
);
|
||||
case 'freeform':
|
||||
return (
|
||||
<svg {...common}>
|
||||
<path d="M12 3l2.2 6.2H21l-5.2 3.8 2 6.5L12 16.2 6.2 19.5l2-6.5L3 9.2h6.8z" />
|
||||
</svg>
|
||||
);
|
||||
default: {
|
||||
const _x: never = type;
|
||||
return <svg {...common}>{String(_x)}</svg>;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user