Files
zeling_v2/Assets/_Game/Scripts/Editor/Modules/WeaponModule.cs
Joywayer 6eaa83dc71 feat: Round 48 narrative systems improvements
- QuestSO: Add ValidateBranchCycles() DFS detection for branches[].nextQuest loop
- QuestSO: Mark three legacy prerequisite fields with v2.0 removal warning in Tooltip
- IQuestManager: Add QuestLockReason enum + QuestLockInfo struct (strongly-typed lock info)
- IQuestManager: Add GetQuestLockInfo() method to interface; GetQuestLockReason() now delegates to it
- IQuestEventSource: Add OnQuestStateChanged(questId, oldState, newState) unified event
- QuestManager: Implement GetQuestLockInfo(); fire OnQuestStateChanged on all state transitions
- DialogueManager: Add one-frame yield in HandleChoices before ShowChoices (skip-debounce fix)
- DialogueManager: Increment _playbackId in ForceEnd() to invalidate residual choice callbacks
- DialogueSequenceSO: Add UNITY_EDITOR debug log in TryGetActiveVariant on variant match
- WorldStateRegistry: Add OnBatchStateChanged event + BatchMark() batch-write API
- DialogueModule: List badge shows warning indicator for unconditional-shadowing variants
- DialogueModule: BuildVariantsCard shows logic mode (AND/OR) alongside flag conditions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 00:05:15 +08:00

184 lines
6.6 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 UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using BaseGames.Player;
namespace BaseGames.Editor.Modules
{
/// <summary>
/// DataHub 武器模块 —— 管理 WeaponSO 资产。
/// </summary>
public class WeaponModule : IDataModule, IDataModuleOrdered
{
private const string Folder = "Assets/_Game/Data/Weapons";
private const string Prefix = "WPN_";
public string ModuleId => "weapon";
public string DisplayName => "武器";
public string IconName => null;
public int DisplayOrder => 10;
private SoListPane<WeaponSO> _listPane;
private DetailHeader _header;
private VisualElement _detailRoot;
private WeaponSO _selected;
public void Initialize()
{
_listPane = new SoListPane<WeaponSO>(
Folder, Prefix,
w => w.weaponType.ToString());
}
public void BuildListPane(VisualElement container, Action<UnityEngine.Object> onSelected)
{
_listPane.SelectionChanged = sel =>
{
_selected = sel;
onSelected?.Invoke(sel);
};
container.Add(_listPane);
_listPane.Refresh();
}
public void BuildDetailPane(VisualElement container, UnityEngine.Object selected)
{
_selected = selected as WeaponSO;
// Header重命名
_header = new DetailHeader();
_header.SetAsset(_selected);
_header.RenameRequested += OnRenameRequested;
container.Add(_header);
if (_selected == null) return;
// Stats Card
var statsCard = BuildStatsCard(_selected);
container.Add(statsCard);
// 操作按钮行
var toolbar = BuildActionBar(_selected);
container.Add(toolbar);
// 分隔线
container.Add(MakeDivider());
// Inspector
var insp = new InspectorElement(_selected); container.Add(insp);
}
public void OnActivated()
{
_listPane?.Refresh();
}
// ── 内部 ─────────────────────────────────────────────────────────────
private void OnRenameRequested(string newName)
{
if (_selected == null) return;
var (ok, err) = AssetOperations.Rename(_selected, newName);
if (!ok)
EditorUtility.DisplayDialog("重命名失败", err, "确定");
else
{
_header.SetAsset(_selected);
_listPane.Invalidate();
}
}
private static VisualElement BuildStatsCard(WeaponSO w)
{
var card = new VisualElement();
card.style.flexDirection = FlexDirection.Row;
card.style.flexWrap = Wrap.Wrap;
card.style.paddingLeft = 12;
card.style.paddingRight = 12;
card.style.paddingTop = 8;
card.style.paddingBottom = 8;
card.style.marginBottom = 4;
card.style.backgroundColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.08f));
card.style.borderBottomWidth = 1;
card.style.borderBottomColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.2f));
AddStatChip(card, "类型", w.weaponType.ToString());
AddStatChip(card, "地面段数", (w.groundComboSteps?.Length ?? 0).ToString());
AddStatChip(card, "空中段数", (w.airComboSteps?.Length ?? 0).ToString());
AddStatChip(card, "ID", string.IsNullOrEmpty(w.weaponId) ? "-" : w.weaponId);
return card;
}
private static void AddStatChip(VisualElement parent, string label, string value)
{
var chip = new VisualElement();
chip.style.flexDirection = FlexDirection.Row;
chip.style.alignItems = Align.Center;
chip.style.marginRight = 14;
chip.style.marginBottom = 2;
var lbl = new Label(label + ":");
lbl.style.opacity = 0.6f;
lbl.style.fontSize = 11;
lbl.style.marginRight = 3;
chip.Add(lbl);
var val = new Label(value);
val.style.fontSize = 11;
val.style.unityFontStyleAndWeight = UnityEngine.FontStyle.Bold;
chip.Add(val);
parent.Add(chip);
}
private VisualElement BuildActionBar(WeaponSO w)
{
var bar = new VisualElement();
bar.style.flexDirection = FlexDirection.Row;
bar.style.paddingLeft = 12;
bar.style.paddingRight = 12;
bar.style.paddingTop = 6;
bar.style.paddingBottom = 6;
bar.style.flexWrap = Wrap.Wrap;
var btnPing = new Button(() => { EditorGUIUtility.PingObject(w); Selection.activeObject = w; })
{ text = "在 Project 中定位", tooltip = "在 Project 窗口高亮此资产" };
bar.Add(btnPing);
var btnClone = new Button(() =>
{
var clone = AssetOperations.Clone(w, Folder);
if (clone != null) _listPane.Refresh(clone);
}) { text = "克隆..." };
bar.Add(btnClone);
var btnDel = new Button(() =>
{
if (AssetOperations.Delete(w)) _listPane.Refresh(null);
}) { text = "删除" };
btnDel.style.borderLeftColor = new StyleColor(new Color(0.8f, 0.3f, 0.3f, 0.6f));
btnDel.style.borderRightColor = new StyleColor(new Color(0.8f, 0.3f, 0.3f, 0.6f));
btnDel.style.borderTopColor = new StyleColor(new Color(0.8f, 0.3f, 0.3f, 0.6f));
btnDel.style.borderBottomColor = new StyleColor(new Color(0.8f, 0.3f, 0.3f, 0.6f));
btnDel.style.borderLeftWidth = 1;
btnDel.style.borderRightWidth = 1;
btnDel.style.borderTopWidth = 1;
btnDel.style.borderBottomWidth = 1;
btnDel.style.marginLeft = 8;
bar.Add(btnDel);
return bar;
}
private static VisualElement MakeDivider()
{
var d = new VisualElement();
d.style.height = 1;
d.style.backgroundColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.2f));
return d;
}
}
}