120 lines
4.9 KiB
TypeScript
120 lines
4.9 KiB
TypeScript
|
|
|
|||
|
|
import React, { useState } from 'react';
|
|||
|
|
import { CharacterData, LocationData, StyleOption, ModelSettings } from '../types';
|
|||
|
|
import { User, MapPin, Info, Wand2, Plus } from 'lucide-react';
|
|||
|
|
import InteractiveAssetEditor from './InteractiveAssetEditor';
|
|||
|
|
|
|||
|
|
interface AssetManagerProps {
|
|||
|
|
characters: CharacterData[];
|
|||
|
|
locations: LocationData[];
|
|||
|
|
styleOption: StyleOption;
|
|||
|
|
onUpdateCharacter: (char: CharacterData) => void;
|
|||
|
|
onUpdateLocation: (loc: LocationData) => void;
|
|||
|
|
onAddCharacter: () => void;
|
|||
|
|
onAddLocation: () => void;
|
|||
|
|
onComplete: () => void;
|
|||
|
|
modelSettings: ModelSettings;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const AssetManager: React.FC<AssetManagerProps> = ({
|
|||
|
|
characters,
|
|||
|
|
locations,
|
|||
|
|
styleOption,
|
|||
|
|
onUpdateCharacter,
|
|||
|
|
onUpdateLocation,
|
|||
|
|
onAddCharacter,
|
|||
|
|
onAddLocation,
|
|||
|
|
onComplete,
|
|||
|
|
modelSettings
|
|||
|
|
}) => {
|
|||
|
|
const [activeTab, setActiveTab] = useState<'characters' | 'locations'>('characters');
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="animate-fade-in space-y-8 pb-32">
|
|||
|
|
<div className="glass-card rounded-3xl p-8 flex flex-col md:flex-row justify-between items-end gap-6">
|
|||
|
|
<div>
|
|||
|
|
<h2 className="text-3xl font-bold text-white mb-2 text-glow">資產合成實驗室</h2>
|
|||
|
|
<div className="flex items-center gap-3 text-sm text-zinc-400">
|
|||
|
|
<span>當前風格 DNA:</span>
|
|||
|
|
<span className="px-3 py-1 bg-indigo-500/10 text-indigo-300 rounded-full border border-indigo-500/20 font-medium shadow-[0_0_10px_rgba(99,102,241,0.2)]">{styleOption.name}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<div className="glass-panel p-1 rounded-xl flex">
|
|||
|
|
<button
|
|||
|
|
onClick={() => setActiveTab('characters')}
|
|||
|
|
className={`px-6 py-2.5 rounded-lg text-sm font-bold flex items-center gap-2 transition-all duration-300 ${
|
|||
|
|
activeTab === 'characters' ? 'bg-white/10 text-white shadow-lg' : 'text-zinc-500 hover:text-zinc-300'
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
<User className="w-4 h-4" />
|
|||
|
|
角色 (Characters)
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
onClick={() => setActiveTab('locations')}
|
|||
|
|
className={`px-6 py-2.5 rounded-lg text-sm font-bold flex items-center gap-2 transition-all duration-300 ${
|
|||
|
|
activeTab === 'locations' ? 'bg-white/10 text-white shadow-lg' : 'text-zinc-500 hover:text-zinc-300'
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
<MapPin className="w-4 h-4" />
|
|||
|
|
場景 (Locations)
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
<button
|
|||
|
|
onClick={activeTab === 'characters' ? onAddCharacter : onAddLocation}
|
|||
|
|
className="glass-btn w-10 h-10 rounded-xl flex items-center justify-center text-emerald-400 hover:bg-emerald-500/10 border-emerald-500/30"
|
|||
|
|
title={activeTab === 'characters' ? "新增角色" : "新增場景"}
|
|||
|
|
>
|
|||
|
|
<Plus className="w-5 h-5" />
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="space-y-12">
|
|||
|
|
{activeTab === 'characters' && characters.map(char => (
|
|||
|
|
<InteractiveAssetEditor
|
|||
|
|
key={char.id}
|
|||
|
|
type="character"
|
|||
|
|
data={char}
|
|||
|
|
styleOption={styleOption}
|
|||
|
|
onUpdate={(updated) => onUpdateCharacter(updated as CharacterData)}
|
|||
|
|
modelSettings={modelSettings}
|
|||
|
|
/>
|
|||
|
|
))}
|
|||
|
|
|
|||
|
|
{activeTab === 'locations' && locations.map(loc => (
|
|||
|
|
<InteractiveAssetEditor
|
|||
|
|
key={loc.id}
|
|||
|
|
type="location"
|
|||
|
|
data={loc}
|
|||
|
|
styleOption={styleOption}
|
|||
|
|
onUpdate={(updated) => onUpdateLocation(updated as LocationData)}
|
|||
|
|
modelSettings={modelSettings}
|
|||
|
|
/>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="fixed bottom-8 left-1/2 -translate-x-1/2 z-40 w-[90%] max-w-4xl">
|
|||
|
|
<div className="glass-card rounded-2xl p-4 flex justify-between items-center shadow-2xl backdrop-blur-xl">
|
|||
|
|
<div className="flex items-center gap-3 px-4">
|
|||
|
|
<div className="w-8 h-8 rounded-full bg-indigo-500/20 flex items-center justify-center text-indigo-400">
|
|||
|
|
<Info className="w-4 h-4" />
|
|||
|
|
</div>
|
|||
|
|
<span className="text-zinc-300 text-sm hidden md:block">確認後資產將鎖定並進入製作流程,請確保所有重要資產已生成完畢。</span>
|
|||
|
|
</div>
|
|||
|
|
<button
|
|||
|
|
onClick={onComplete}
|
|||
|
|
className="glass-btn bg-emerald-500/20 border-emerald-500/50 text-white px-8 py-3 rounded-xl font-bold flex items-center gap-2 hover:bg-emerald-500/30 text-shadow-sm"
|
|||
|
|
>
|
|||
|
|
<Wand2 className="w-5 h-5 text-emerald-400" />
|
|||
|
|
確認並進入分鏡製作
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default AssetManager;
|