Files
zeling_v2/Assets/_Game/Scripts/Editor/Hub/DataHubWindow.cs
Joywayer bb3afd130f feat: Add SkillModule and WeaponModule for managing skills and weapons
- Implemented SkillModule to manage FormSkillSO assets with a detailed UI for editing and displaying skill properties.
- Implemented WeaponModule to manage WeaponSO assets with a detailed UI for editing and displaying weapon properties.
- Created AssetOperations class for centralized CRUD operations on ScriptableObject assets, including create, rename, delete, and clone functionalities.
- Added DetailHeader for displaying and renaming asset names in the UI.
- Introduced SoListPane for a reusable ScriptableObject list panel with search functionality and context menus.
- Added meta files for all new scripts to ensure proper asset management in Unity.
2026-05-21 07:09:53 +08:00

263 lines
9.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using BaseGames.Editor.Modules;
namespace BaseGames.Editor
{
/// <summary>
/// 数据管理总枢纽窗口DataHub
/// 布局导航侧边栏120px | TwoPaneSplitView → 列表区220px + 详情区flex
/// 菜单BaseGames / Data Hub (priority=50)
/// </summary>
public class DataHubWindow : EditorWindow
{
private const string UssPath = "Assets/_Game/Scripts/Editor/UIToolkit/Editor.uss";
private const string PrefKey = "DataHub.ActiveModuleId";
private const float NavWidth = 120f;
private const float ListWidth = 220f;
private const float MinWinWidth = 680f;
private const float MinWinHeight = 420f;
[MenuItem("BaseGames/Data Hub", priority = 50)]
public static void Open()
{
var wnd = GetWindow<DataHubWindow>();
wnd.titleContent = new GUIContent("Data Hub", EditorGUIUtility.IconContent("d_ScriptableObject Icon").image);
wnd.minSize = new Vector2(MinWinWidth, MinWinHeight);
}
// ── 状态 ─────────────────────────────────────────────────────────────
private readonly List<IDataModule> _modules = new();
private readonly HashSet<string> _initializedIds = new();
private IDataModule _activeModule;
private VisualElement _navSidebar;
// 缓存:列表区和详情区引用(由 TwoPaneSplitView 子节点提供)
private VisualElement _listWrapper;
private VisualElement _detailWrapper;
// 当前选中资产
private UnityEngine.Object _selected;
// ── 生命周期 ──────────────────────────────────────────────────────────
public void CreateGUI()
{
// USS
var uss = AssetDatabase.LoadAssetAtPath<StyleSheet>(UssPath);
if (uss != null) rootVisualElement.styleSheets.Add(uss);
// 注册模块
RegisterModules();
// 构建 UI
BuildLayout();
// 恢复上次激活的模块
string savedId = EditorPrefs.GetString(PrefKey, string.Empty);
var toActivate = _modules.Find(m => m.ModuleId == savedId) ?? _modules.FirstOrDefault();
if (toActivate != null) ActivateModule(toActivate);
}
// ── 模块注册 ──────────────────────────────────────────────────────────
private void RegisterModules()
{
_modules.Clear();
_modules.Add(new WeaponModule());
_modules.Add(new SkillModule());
_modules.Add(new EnemyModule());
_modules.Add(new FormModule());
_modules.Add(new BossSkillModule());
}
// ── 布局 ─────────────────────────────────────────────────────────────
private void BuildLayout()
{
var root = rootVisualElement;
root.style.flexDirection = FlexDirection.Row;
root.style.flexGrow = 1;
// 导航侧边栏
_navSidebar = BuildNavSidebar();
root.Add(_navSidebar);
// 垂直分隔线
var divider = new VisualElement();
divider.style.width = 1;
divider.style.backgroundColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.25f));
root.Add(divider);
// TwoPaneSplitView列表 + 详情)
var split = new TwoPaneSplitView(0, ListWidth, TwoPaneSplitViewOrientation.Horizontal);
split.style.flexGrow = 1;
root.Add(split);
// 列表区容器
_listWrapper = new VisualElement();
_listWrapper.style.flexGrow = 1;
split.Add(_listWrapper);
// 详情区容器
_detailWrapper = new VisualElement();
_detailWrapper.style.flexGrow = 1;
split.Add(_detailWrapper);
}
private VisualElement BuildNavSidebar()
{
var sidebar = new VisualElement();
sidebar.style.width = NavWidth;
sidebar.style.flexShrink = 0;
sidebar.style.flexDirection = FlexDirection.Column;
sidebar.style.paddingTop = 8;
// 标题
var title = new Label("DATA HUB");
title.style.fontSize = 10;
title.style.opacity = 0.5f;
title.style.paddingLeft = 10;
title.style.marginBottom = 6;
title.style.unityFontStyleAndWeight = FontStyle.Bold;
sidebar.Add(title);
foreach (var module in _modules)
{
var btn = BuildNavItem(module);
sidebar.Add(btn);
}
// 弹性填充
var spacer = new VisualElement();
spacer.style.flexGrow = 1;
sidebar.Add(spacer);
return sidebar;
}
private Button BuildNavItem(IDataModule module)
{
var btn = new Button(() => ActivateModule(module));
btn.name = "nav-" + module.ModuleId;
btn.style.flexDirection = FlexDirection.Row;
btn.style.alignItems = Align.Center;
btn.style.paddingLeft = 10;
btn.style.paddingRight = 8;
btn.style.paddingTop = 8;
btn.style.paddingBottom = 8;
btn.style.borderTopLeftRadius = 0;
btn.style.borderTopRightRadius = 0;
btn.style.borderBottomLeftRadius = 0;
btn.style.borderBottomRightRadius = 0;
btn.style.borderLeftWidth = 0;
btn.style.borderRightWidth = 0;
btn.style.borderTopWidth = 0;
btn.style.borderBottomWidth = 0;
btn.style.backgroundColor = new StyleColor(Color.clear);
btn.style.marginBottom = 2;
// 图标
if (!string.IsNullOrEmpty(module.IconName))
{
var icon = new Image { image = EditorGUIUtility.IconContent(module.IconName).image };
icon.style.width = 16;
icon.style.height = 16;
icon.style.marginRight = 6;
btn.Add(icon);
}
var label = new Label(module.DisplayName);
label.style.flexGrow = 1;
btn.Add(label);
return btn;
}
// ── 模块切换 ──────────────────────────────────────────────────────────
private void ActivateModule(IDataModule module)
{
if (_activeModule == module) return;
_activeModule = module;
_selected = null;
// 更新导航项视觉状态
foreach (var m in _modules)
{
var navBtn = _navSidebar.Q<Button>("nav-" + m.ModuleId);
if (navBtn == null) continue;
if (m == module)
{
navBtn.style.backgroundColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.18f));
navBtn.style.borderLeftWidth = 3;
navBtn.style.borderLeftColor = new StyleColor(new Color(0.4f, 0.65f, 1f, 1f));
}
else
{
navBtn.style.backgroundColor = new StyleColor(Color.clear);
navBtn.style.borderLeftWidth = 0;
}
}
// 初始化模块(首次激活时调用一次)
if (!_initializedIds.Contains(module.ModuleId))
{
_initializedIds.Add(module.ModuleId);
module.Initialize();
}
module.OnActivated();
// 重建列表区
_listWrapper.Clear();
module.BuildListPane(_listWrapper, OnModuleSelected);
// 清空详情区
RebuildDetailPane(null);
EditorPrefs.SetString(PrefKey, module.ModuleId);
}
private void OnModuleSelected(UnityEngine.Object selected)
{
_selected = selected;
RebuildDetailPane(selected);
}
private void RebuildDetailPane(UnityEngine.Object selected)
{
_detailWrapper.Clear();
if (_activeModule == null) return;
if (selected == null)
{
var placeholder = new Label("← 从左侧列表选择一项");
placeholder.style.opacity = 0.45f;
placeholder.style.marginTop = 60;
placeholder.style.unityTextAlign = TextAnchor.MiddleCenter;
_detailWrapper.Add(placeholder);
return;
}
_activeModule.BuildDetailPane(_detailWrapper, selected);
}
// ── 公共辅助(供 Module 回调使用)────────────────────────────────────
/// <summary>通知 Hub 已完成重命名,需要刷新详情区标题。</summary>
public void NotifyRenamed(UnityEngine.Object asset)
{
if (_activeModule == null || asset == null) return;
RebuildDetailPane(asset);
}
}
}