using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using UIButton = UnityEngine.UIElements.Button;
using UIToggle = UnityEngine.UIElements.Toggle;
using UnityEngine.UI;
using Spine.Unity;
using OfficeOpenXml;  // EPPlus用于读取Excel
using ArtResource;  // 美术资源SO

/// <summary>
/// 装饰配置统一编辑器
/// 支持读取/保存配置、场景还原、步骤编辑
/// </summary>
public class DecorateConfigEditor : EditorWindow
{
    [MenuItem("蹊径/场景建造工具")]
    public static void ShowWindow()
    {
        DecorateConfigEditor wnd = GetWindow<DecorateConfigEditor>();
        wnd.titleContent = new GUIContent("装饰配置编辑器");
        wnd.minSize = new Vector2(800, 600);
    }
    // UI控件
    private TextField configPathField;
    private IntegerField areaIdField;
    private IntegerField stepCountField;
    private ObjectField bgObjectField;
    private IntegerField currentStepField;
    private Label stepInfoLabel;
    private VisualElement stepEditContainer;
    private ScrollView stepEditScrollView;  // 步骤编辑滚动视图
    private Label emptyLabel;
    private Label statusLabel;  // 状态栏
    private VisualElement configContent;  // 配置管理可折叠内容
    private UIButton toggleConfigButton;  // 折叠按钮
    private bool isConfigExpanded = true; // 配置区域展开状态
    private VisualElement stepGridContainer;  // 步骤网格容器
    private List<UIButton> stepGridButtons = new List<UIButton>();  // 步骤网格按钮列表
    private VisualElement initEditContent;  // 初始状态编辑可折叠内容
    private UIButton toggleInitEditButton;  // 初始状态编辑折叠按钮
    private bool isInitEditExpanded = true;  // 初始状态编辑展开状态
    private VisualElement initEditContainer;  // 初始状态编辑容器
    private Label initEmptyLabel;  // 初始状态空标签
    
    // 数据
    private string configFilePath = "E:\\WorkSpace\\Docs\\config\\DecorateCost.xlsx";  // 修改为XLSX路径
    private const string SHEET_NAME = "DecorateCost";  // Sheet名称
    private Transform bgTransform;
    private Transform decoratePanelTransform;  // 装饰按钮Panel
    private int currentAreaId = 1;
    private int currentStepIndex = 0;
    private int maxSteps = 25;
    
    // 配置数据结构
    private List<DecorateConfigRow> allConfigRows = new List<DecorateConfigRow>();
    private List<DecorateConfigRow> currentAreaInitRows = new List<DecorateConfigRow>(); // sortId=0的初始化行
    private List<DecorateConfigRow> currentAreaStepRows = new List<DecorateConfigRow>(); // sortId>0的步骤行
    
    // 暂存区和原始数据（用于对比修改）
    private List<DecorateConfigRow> tempAreaInitRows = new List<DecorateConfigRow>();  // 初始状态暂存区
    private List<DecorateConfigRow> originalAreaStepRows = new List<DecorateConfigRow>();  // 原始步骤数据
    private List<DecorateConfigRow> originalAreaInitRows = new List<DecorateConfigRow>();  // 原始初始状态数据
    
    // 修改状态标记
    private bool isStepsModified = false;  // 步骤是否已修改
    private bool isInitRecorded = false;   // 初始状态是否已记录
    private bool isNewScene = false;       // 是否是新场景
    
    // 剪贴板：用于复制/粘贴配置
    private string clipboardAction = "";  // 复制的Action配置
    
    // SO资源缓存
    private ArtTableSO decorateIconSO;  // 图标资源SO
    private Dictionary<int, ArtTableSO> decorateSceneSODict = new Dictionary<int, ArtTableSO>();  // 场景资源SO字典（按AreaId缓存）

    public void CreateGUI()
    {
        VisualElement root = rootVisualElement;
        
        // 加载UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
            "Assets/Editor/CustomTools/DecorateConfigEditor/DecorateConfigEditor.uxml");
        
        if (visualTree == null)
        {
            Debug.LogError("无法加载UXML文件！请检查路径：Assets/Editor/CustomTools/DecorateConfigEditor/DecorateConfigEditor.uxml");
            return;
        }
        
        VisualElement uxml = visualTree.Instantiate();
        root.Add(uxml);
        
        // 绑定UI控件
        BindUIControls();
        // 绑定事件
        BindEvents();
        
        // 初始化折叠按钮状态
        InitializeToggleButtonStates();
        
        // 初始化默认配置路径
        if (configPathField != null)
        {
            configPathField.value = configFilePath;
        }
        
        // 显示分辨率提示
        ShowResolutionWarning();
        
        // 自动查找bg节点
        AutoFindBgNode();
        // 自动查找DecoratePanel
        AutoFindDecoratePanel();
    }
    
    /// <summary>
    /// 初始化折叠按钮的状态，确保UI和代码状态一致
    /// </summary>
    private void InitializeToggleButtonStates()
    {
        // 配置区域默认展开
        if (configContent != null && toggleConfigButton != null)
        {
            configContent.style.display = DisplayStyle.Flex;
            toggleConfigButton.text = "▲ 折叠";
            isConfigExpanded = true;
        }
        
        // 初始状态编辑区域默认展开
        if (initEditContent != null && toggleInitEditButton != null)
        {
            initEditContent.style.display = DisplayStyle.Flex;
            toggleInitEditButton.text = "▲ 折叠";
            isInitEditExpanded = true;
        }
    }
    
    /// <summary>
    /// 自动查找场景中的bg节点并设置
    /// </summary>
    private void AutoFindBgNode()
    {
        // 尝试查找 Canvas/MainDecoratePanel/ImageBg/bg
        GameObject canvas = GameObject.Find("Canvas");
        if (canvas != null)
        {
            Transform mainDecoratePanel = canvas.transform.Find("MainDecoratePanel");
            if (mainDecoratePanel != null)
            {
                Transform imageBg = mainDecoratePanel.Find("ImageBg");
                if (imageBg != null)
                {
                    Transform bg = imageBg.Find("bg");
                    if (bg != null)
                    {
                        bgObjectField.value = bg;
                        bgTransform = bg;
                        return;
                    }
                }
            }
        }
        
        Debug.Log("未找到默认bg节点路径(Canvas/MainDecoratePanel/ImageBg/bg)，请手动拖入");
    }
    
    /// <summary>
    /// 自动查找AreaDecoratePanel
    /// </summary>
    private void AutoFindDecoratePanel()
    {
        GameObject canvas = GameObject.Find("Canvas");
        if (canvas != null)
        {
            Transform areaDecoratePanel = canvas.transform.Find("AreaDecoratePanel");
            if (areaDecoratePanel != null)
            {
                decoratePanelTransform = areaDecoratePanel;
                // 默认隐藏装饰按钮
                decoratePanelTransform.gameObject.SetActive(false);
                return;
            }
        }
        
        Debug.Log("未找到AreaDecoratePanel，装饰按钮显示功能将无法使用");
    }

    private void BindUIControls()
    {
        configPathField = rootVisualElement.Q<TextField>("ConfigPathField");
        areaIdField = rootVisualElement.Q<IntegerField>("AreaIdField");
        stepCountField = rootVisualElement.Q<IntegerField>("StepCountField");
        if (stepCountField != null)
        {
            stepCountField.SetEnabled(false); // 禁用步骤数量编辑
        }
        bgObjectField = rootVisualElement.Q<ObjectField>("BgObjectField");
        currentStepField = rootVisualElement.Q<IntegerField>("CurrentStepField");
        stepInfoLabel = rootVisualElement.Q<Label>("StepInfoLabel");
        stepEditScrollView = rootVisualElement.Q<ScrollView>("StepEditScrollView");
        stepEditContainer = rootVisualElement.Q<VisualElement>("StepEditContainer");
        emptyLabel = rootVisualElement.Q<Label>("EmptyLabel");
        statusLabel = rootVisualElement.Q<Label>("StatusLabel");
        
        // 折叠控制
        configContent = rootVisualElement.Q<VisualElement>("ConfigContent");
        toggleConfigButton = rootVisualElement.Q<UIButton>("ToggleConfigButton");
        
        // 初始状态编辑
        initEditContent = rootVisualElement.Q<VisualElement>("InitEditContent");
        toggleInitEditButton = rootVisualElement.Q<UIButton>("ToggleInitEditButton");
        initEditContainer = rootVisualElement.Q<VisualElement>("InitEditContainer");
        initEmptyLabel = rootVisualElement.Q<Label>("InitEmptyLabel");
        
        // 步骤网格容器
        stepGridContainer = rootVisualElement.Q<VisualElement>("StepGridContainer");
        if (stepGridContainer != null)
        {
            CreateStepGridButtons();
        }
        else
        {
            Debug.LogError("未找到 StepGridContainer 元素！");
        }
    }

    private void BindEvents()
    {
        // 配置管理按钮
        BindButtonEvent("BrowseConfigButton", OnBrowseConfigClicked);
        BindButtonEvent("CheckBgButton", OnCheckBgClicked);
        BindButtonEvent("LoadConfigButton", OnLoadConfigClicked);
        BindButtonEvent("SaveConfigButton", OnSaveConfigClicked);
        BindButtonEvent("RecordInitButton", OnRecordInitClicked);
        
        // 批量设置按钮
        BindButtonEvent("AutoSetTitleButton", OnAutoSetTitleClicked);
        // BindButtonEvent("AutoSetIconButton", OnAutoSetIconClicked); // 暂时隐藏
        BindButtonEvent("BatchSetIconPosButton", OnBatchSetIconPosClicked);
        BindButtonEvent("AutoSetBuildButton", OnAutoSetBuildClicked);
        BindButtonEvent("AutoSetShineButton", OnAutoSetShineClicked);
        BindButtonEvent("BatchSetCostButton", OnBatchSetCostClicked);
        BindButtonEvent("BatchSetSkipButton", OnBatchSetSkipClicked);
        BindButtonEvent("ClearSceneButton", OnClearSceneClicked);
        
        // 隐藏自动设置Icon按钮
        var autoSetIconButton = rootVisualElement.Q<UIButton>("AutoSetIconButton");
        if (autoSetIconButton != null)
        {
            autoSetIconButton.style.display = DisplayStyle.None;
        }
        
        // 顶部常用工具按钮
        BindButtonEvent("SortNamesButtonTop", OnSortNamesClicked);
        BindButtonEvent("ScaleImageButtonTop", OnScaleImageClicked);
        
        // 折叠按钮
        if (toggleConfigButton != null)
        {
            toggleConfigButton.clicked += OnToggleConfigClicked;
        }
        if (toggleInitEditButton != null)
        {
            toggleInitEditButton.clicked += OnToggleInitEditClicked;
        }
        
        // 步骤控制按钮
        BindButtonEvent("PrevStepButton", OnPrevStepClicked);
        BindButtonEvent("NextStepButton", OnNextStepClicked);
        BindButtonEvent("GotoStepButton", OnGotoStepClicked);
        BindButtonEvent("ShowDecorateButton", OnShowDecorateButtonClicked);
        BindButtonEvent("HideDecorateButton", OnHideDecorateButtonClicked);
        
        // ObjectField值变化时更新bgTransform
        if (bgObjectField != null)
        {
            bgObjectField.RegisterValueChangedCallback(evt => 
            {
                bgTransform = evt.newValue as Transform;
            });
        }
    }
    
    /// <summary>
    /// 安全地绑定按钮事件
    /// </summary>
    private void BindButtonEvent(string buttonName, System.Action callback)
    {
        var button = rootVisualElement.Q<UIButton>(buttonName);
        if (button != null)
        {
            button.clicked += callback;
        }
        else
        {
            Debug.LogWarning($"未找到按钮: {buttonName}");
        }
    }
    
    /// <summary>
    /// 确保bgTransform是最新的
    /// </summary>
    private void UpdateBgTransform()
    {
        bgTransform = bgObjectField.value as Transform;
    }
    
    /// <summary>
    /// 切换配置管理区域的折叠状态
    /// </summary>
    private void OnToggleConfigClicked()
    {
        isConfigExpanded = !isConfigExpanded;
        
        if (isConfigExpanded)
        {
            // 展开
            configContent.style.display = DisplayStyle.Flex;
            toggleConfigButton.text = "▲ 折叠";
        }
        else
        {
            // 折叠
            configContent.style.display = DisplayStyle.None;
            toggleConfigButton.text = "▼ 展开";
        }
    }
    
    /// <summary>
    /// 切换初始状态编辑区域的折叠状态
    /// </summary>
    private void OnToggleInitEditClicked()
    {
        isInitEditExpanded = !isInitEditExpanded;
        
        if (isInitEditExpanded)
        {
            // 展开
            initEditContent.style.display = DisplayStyle.Flex;
            toggleInitEditButton.text = "▲ 折叠";
        }
        else
        {
            // 折叠
            initEditContent.style.display = DisplayStyle.None;
            toggleInitEditButton.text = "▼ 展开";
        }
    }

    /// <summary>
    /// 图片大小X1.5（当前选中物体）
    /// </summary>
    private void OnScaleImageClicked()
    {
        GameObject selectedObj = UnityEditor.Selection.activeGameObject;
        
        if (selectedObj == null)
        {
            EditorUtility.DisplayDialog("错误", "请先在Hierarchy中选择一个物体！", "确定");
            return;
        }
        
        RectTransform rt = selectedObj.GetComponent<RectTransform>();
        if (rt == null)
        {
            EditorUtility.DisplayDialog("错误", "选中的物体没有RectTransform组件！", "确定");
            return;
        }
        
        Vector2 oldSize = rt.sizeDelta;
        float newWidth = Mathf.Round(oldSize.x * 1.5f);
        float newHeight = Mathf.Round(oldSize.y * 1.5f);
        
        rt.sizeDelta = new Vector2(newWidth, newHeight);
        
        Debug.Log($"✅ 已调整 {selectedObj.name} 的大小：({oldSize.x}, {oldSize.y}) → ({newWidth}, {newHeight})");
        EditorUtility.DisplayDialog("完成", 
            $"已调整 {selectedObj.name} 的大小\n\n原始：{oldSize.x} x {oldSize.y}\n新大小：{newWidth} x {newHeight}", 
            "确定");
    }
    
    /// <summary>
    /// 创建步骤网格按钮（4列布局，更美观）
    /// </summary>
    private void CreateStepGridButtons()
    {
        stepGridButtons.Clear();
        stepGridContainer.Clear();
        
        for (int i = 0; i < maxSteps; i++)
        {
            int stepNumber = i + 1;  // 步骤编号1-25
            UIButton btn = new UIButton();
            btn.text = $"{stepNumber}";
            btn.style.width = 36;
            btn.style.height = 30;
            btn.style.marginRight = 2;
            btn.style.marginBottom = 2;
            btn.style.fontSize = 10;
            btn.style.unityFontStyleAndWeight = FontStyle.Bold;
            
            // 添加点击事件
            btn.clicked += () => OnStepGridButtonClicked(stepNumber);
            
            stepGridButtons.Add(btn);
            stepGridContainer.Add(btn);
        }
        
        UpdateStepGridButtonStates();
    }
    
    /// <summary>
    /// 点击步骤网格按钮
    /// </summary>
    private void OnStepGridButtonClicked(int stepIndex)
    {
        // 检查目标步骤是否有配置（步骤0是初始状态，始终允许）
        if (stepIndex > 0 && !IsStepConfigured(stepIndex))
        {
            EditorUtility.DisplayDialog("提示", $"步骤{stepIndex}还未配置（Action为空）\n\n请先为该步骤添加操作并保存配置后再预览。", "确定");
            return;
        }
        
        currentStepIndex = stepIndex;
        currentStepField.value = stepIndex;
        RestoreSceneToStep(stepIndex);
        UpdateStepGridButtonStates();
        
        // 自动滚动到对应步骤
        ScrollToStep(stepIndex);
    }
    
    /// <summary>
    /// 检查步骤是否已配置（Action不为空）
    /// </summary>
    private bool IsStepConfigured(int stepIndex)
    {
        if (stepIndex == 0) return true; // 步骤0是初始状态，始终允许
        
        var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == stepIndex);
        return stepRow != null && !string.IsNullOrEmpty(stepRow.Action);
    }
    
    /// <summary>
    /// 更新步骤网格按钮的状态（当前高亮，已配置/未配置颜色）
    /// </summary>
    private void UpdateStepGridButtonStates()
    {
        if (stepGridButtons == null || stepGridButtons.Count == 0) return;
        
        for (int i = 0; i < stepGridButtons.Count && i < maxSteps; i++)
        {
            UIButton btn = stepGridButtons[i];
            int stepNumber = i + 1;  // 步骤编号1-25
            bool isCurrent = (stepNumber == currentStepIndex);
            bool isConfigured = false;
            
            // 检查是否已配置：必须有Action才算已配置
            if (i < currentAreaStepRows.Count)
            {
                var stepRow = currentAreaStepRows[i];
                isConfigured = !string.IsNullOrEmpty(stepRow.Action);  // ✅ 只有Action不为空才算已配置
            }
            
            // 设置样式
            if (isCurrent)
            {
                // 当前步骤：蓝色高亮
                btn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.5f, 0.9f));
                btn.style.color = Color.white;
            }
            else if (isConfigured)
            {
                // 已配置：绿色
                btn.style.backgroundColor = new StyleColor(new Color(0.3f, 0.6f, 0.3f));
                btn.style.color = Color.white;
            }
            else
            {
                // 未配置：默认灰色
                btn.style.backgroundColor = new StyleColor(new Color(0.3f, 0.3f, 0.3f));
                btn.style.color = new Color(0.7f, 0.7f, 0.7f);
            }
        }
    }
    
    /// <summary>
    /// 滚动到指定步骤的编辑区域
    /// </summary>
    private void ScrollToStep(int stepIndex)
    {
        if (stepEditScrollView == null || stepEditContainer == null) return;
        if (currentAreaStepRows == null || currentAreaStepRows.Count == 0) return;
        
        // 延迟执行滚动，确保UI已经渲染
        EditorApplication.delayCall += () =>
        {
            try
            {
                // 找到对应步骤的容器
                // stepEditContainer的第一个子元素是标题Label
                // 之后是每个步骤的编辑项
                int targetIndex = -1;
                for (int i = 0; i < currentAreaStepRows.Count; i++)
                {
                    if (currentAreaStepRows[i].SortId == stepIndex)
                    {
                        targetIndex = i + 1; // +1因为第一个是标题Label
                        break;
                    }
                }
                
                if (targetIndex < 0 || targetIndex >= stepEditContainer.childCount) return;
                
                VisualElement targetElement = stepEditContainer.ElementAt(targetIndex);
                if (targetElement == null) return;
                
                // 计算目标元素的位置
                float targetY = 0;
                for (int i = 0; i < targetIndex; i++)
                {
                    var child = stepEditContainer.ElementAt(i);
                    if (child != null)
                    {
                        // 累加之前所有元素的高度和margin
                        targetY += child.resolvedStyle.height;
                        targetY += child.resolvedStyle.marginTop;
                        targetY += child.resolvedStyle.marginBottom;
                    }
                }
                
                // 设置ScrollView的滚动位置
                stepEditScrollView.scrollOffset = new Vector2(0, targetY);
                
                Debug.Log($"✅ 已滚动到步骤{stepIndex}");
            }
            catch (System.Exception e)
            {
                Debug.LogWarning($"滚动到步骤{stepIndex}时出错: {e.Message}");
            }
        };
    }
    
    /// <summary>
    /// 自动设置标题（Step1 到 Step25）
    /// </summary>
    private void OnAutoSetTitleClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取配置或记录初始状态！", "确定");
            return;
        }
        
        bool confirmed = EditorUtility.DisplayDialog("确认", 
            "将为所有25个步骤设置标题为 Step1 到 Step25\n这将覆盖现有标题，是否继续？", 
            "确定", "取消");
        
        if (!confirmed) return;
        
        for (int i = 0; i < currentAreaStepRows.Count && i < maxSteps; i++)
        {
            currentAreaStepRows[i].Title = $"Step{i + 1}";
        }
        
        isStepsModified = true;
        UpdateStatusLabel();
        
        // 刷新当前步骤的UI
        RefreshCurrentStepUI();
        
        Debug.Log("✅ 已为所有步骤设置标题：Step1 到 Step25");
        EditorUtility.DisplayDialog("完成", "已为所有步骤设置标题：Step1 到 Step25", "确定");
    }

    #region 配置文件操作
    
    private void OnBrowseConfigClicked()
    {
        string path = EditorUtility.OpenFilePanel("选择配置文件", "Assets/GameMain/DataTables", "txt");
        if (!string.IsNullOrEmpty(path))
        {
            // 转换为相对路径
            if (path.StartsWith(Application.dataPath))
            {
                path = "Assets" + path.Substring(Application.dataPath.Length);
            }
            configPathField.value = path;
            configFilePath = path;
        }
    }

    private void OnCheckBgClicked()
    {
        bgTransform = bgObjectField.value as Transform;
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点！", "确定");
            return;
        }

        // 检查bg格式
        bool isValid = true;
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("bg格式检查结果：");
        
        // 检查必需的子节点
        Transform addObj = bgTransform.Find("addObj");
        Transform clearObj = bgTransform.Find("clearObj");
        
        if (addObj == null)
        {
            sb.AppendLine("❌ 缺少 addObj 子节点");
            isValid = false;
        }
        else
        {
            sb.AppendLine($"✓ 找到 addObj，包含 {addObj.childCount} 个子物体");
        }
        
        if (clearObj == null)
        {
            sb.AppendLine("❌ 缺少 clearObj 子节点");
            isValid = false;
        }
        else
        {
            sb.AppendLine($"✓ 找到 clearObj，包含 {clearObj.childCount} 个子物体");
        }
        
        // 检查bg本身是否有Image组件
        if (bgTransform.GetComponent<UnityEngine.UI.Image>() == null)
        {
            sb.AppendLine("⚠ bg节点没有Image组件");
        }
        else
        {
            sb.AppendLine("✓ bg节点有Image组件");
        }

        if (isValid)
        {
            EditorUtility.DisplayDialog("检查完成", sb.ToString(), "确定");
        }
        else
        {
            EditorUtility.DisplayDialog("格式错误", sb.ToString(), "确定");
        }
    }

    private void OnLoadConfigClicked()
    {
        UpdateBgTransform();
        
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点！", "确定");
            return;
        }
        
        configFilePath = configPathField.value;
        currentAreaId = areaIdField.value;
        
        // 限制：不允许编辑AreaId 1-5（这些场景是20步，需要手动编辑）
        if (currentAreaId >= 1 && currentAreaId <= 5)
        {
            EditorUtility.DisplayDialog("限制", "AreaId 1-5 是旧版20步场景，不支持通过此工具编辑。\n如需修改请手动编辑配置文件。", "确定");
            return;
        }
        
        // 限制：步骤数固定为25，不允许修改
        maxSteps = 25;
        stepCountField.value = 25;

        if (!File.Exists(configFilePath))
        {
            EditorUtility.DisplayDialog("错误", $"配置文件不存在：{configFilePath}", "确定");
            return;
        }

        // 读取配置文件
        LoadConfigFromFile();
        
        // 检查是否是新场景：只要有初始状态或步骤配置就算旧场景
        if (currentAreaInitRows.Count == 0 && currentAreaStepRows.Count == 0)
        {
            // 新场景：完全没有配置
            isNewScene = true;
            CreateEmptySteps();
            
            // 重置暂存状态
            isStepsModified = false;
            isInitRecorded = false;
            tempAreaInitRows.Clear();
            originalAreaStepRows.Clear();
            originalAreaInitRows.Clear();
            
            // 刷新UI
            RefreshStepEditUI();
            UpdateStatusLabel();
            
            EditorUtility.DisplayDialog("新场景", 
                $"未找到AreaId={currentAreaId}的配置。\n\n已创建新场景，包含{maxSteps}个空步骤。\n\n请：\n1. 编辑步骤配置\n2. 点击\"记录初始状态\"扫描场景\n3. 点击\"保存配置\"写入文件", "确定");
        }
        else
        {
            // 旧场景：有初始状态或步骤配置
            isNewScene = false;
            
            // 如果步骤配置为空，自动创建25个空步骤
            if (currentAreaStepRows.Count == 0)
            {
                CreateEmptySteps();
            }
            
            // 保存原始数据用于对比
            originalAreaStepRows = DeepCopyRows(currentAreaStepRows);
            originalAreaInitRows = DeepCopyRows(currentAreaInitRows);
            
            // 将已有的初始状态加载到tempAreaInitRows用于编辑
            tempAreaInitRows = DeepCopyRows(currentAreaInitRows);
            
            // 重置暂存状态
            isStepsModified = false;
            isInitRecorded = (currentAreaInitRows.Count > 0); // 如果有初始状态，标记为已记录
            
            // 读取当前步骤，还原场景到指定步骤
            int targetStep = currentStepField.value;
            currentStepIndex = targetStep;
            RestoreSceneToStep(targetStep);
            
            // 刷新步骤编辑界面
            RefreshStepEditUI();
            // 刷新初始状态编辑界面
            RefreshInitEditUI();
            UpdateStatusLabel();
            
            string message = $"场景已还原到步骤{targetStep}\n初始化对象：{currentAreaInitRows.Count}个\n步骤数量：{currentAreaStepRows.Count}个";
            if (currentAreaInitRows.Count == 0)
            {
                message += "\n\n⚠ 注意：未找到初始化配置(sortId=0)\n建议先记录初始状态";
            }
            EditorUtility.DisplayDialog("完成", message, "确定");
        }
    }

    private void OnSaveConfigClicked()
    {
        UpdateBgTransform();
        
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点并检查格式！", "确定");
            return;
        }

        configFilePath = configPathField.value;
        currentAreaId = areaIdField.value;
        
        // 限制：不允许保存AreaId 1-5（这些场景是20步，需要手动编辑）
        if (currentAreaId >= 1 && currentAreaId <= 5)
        {
            EditorUtility.DisplayDialog("限制", "AreaId 1-5 是旧版20步场景，不支持通过此工具编辑。\n如需修改请手动编辑配置文件。", "确定");
            return;
        }

        // 检查保存条件
        if (isNewScene)
        {
            // 新场景：只需要初始状态记录就可以保存（步骤可以全空）
            if (!isInitRecorded)
            {
                EditorUtility.DisplayDialog("无法保存", 
                    "新场景必须先记录初始状态才能保存。\n\n请点击\"记录初始状态\"按钮扫描场景。\n\n步骤配置可以为空，后续可以逐步添加。", 
                    "确定");
                return;
            }
            
            // 提示用户步骤配置情况
            if (!isStepsModified)
            {
                if (!EditorUtility.DisplayDialog("确认保存", 
                    "当前步骤配置为空或未修改。\n\n保存后可以继续编辑步骤并再次保存。\n\n确定要保存吗？", 
                    "保存", "取消"))
                {
                    return;
                }
            }
        }
        else
        {
            // 旧场景：必须至少有一项修改
            if (!isStepsModified && !isInitRecorded)
            {
                EditorUtility.DisplayDialog("提示", "没有任何修改，无需保存。", "确定");
                return;
            }
            
            // 旧场景且步骤修改：显示差异对比
            if (isStepsModified)
            {
                string diffMsg = CompareStepChanges();
                if (!string.IsNullOrEmpty(diffMsg))
                {
                    if (!EditorUtility.DisplayDialog("确认保存", $"检测到以下步骤修改：\n\n{diffMsg}\n\n确定要保存吗？", "保存", "取消"))
                    {
                        return;
                    }
                }
            }
        }

        // 准备保存数据
        List<DecorateConfigRow> initRowsToSave = isInitRecorded ? tempAreaInitRows : currentAreaInitRows;
        List<DecorateConfigRow> stepRowsToSave = currentAreaStepRows;
        
        // 保存前检测：Icon名称在SO中的有效性验证
        List<string> invalidIcons = new List<string>();
        
        // 验证初始化配置的Icon
        foreach (var row in initRowsToSave)
        {
            if (!string.IsNullOrEmpty(row.Icon))
            {
                if (!ValidateIconNameInSO(row.Icon, currentAreaId, true, out string errorMsg))
                {
                    invalidIcons.Add($"[初始化 AreaId={currentAreaId}] {row.Icon}: {errorMsg}");
                }
            }
        }
        
        // 验证步骤配置的Icon
        foreach (var row in stepRowsToSave)
        {
            if (!string.IsNullOrEmpty(row.Icon))
            {
                if (!ValidateIconNameInSO(row.Icon, currentAreaId, false, out string errorMsg))
                {
                    invalidIcons.Add($"[Step {row.SortId}] {row.Icon}: {errorMsg}");
                }
            }
        }
        
        if (invalidIcons.Count > 0)
        {
            string iconList = string.Join("\n", invalidIcons.Take(10));
            if (invalidIcons.Count > 10)
            {
                iconList += $"\n... 还有{invalidIcons.Count - 10}个无效Icon";
            }
            
            if (!EditorUtility.DisplayDialog("⚠️ 检测到无效Icon名称", 
                $"配置中的以下Icon名称在SO资源中不存在：\n\n{iconList}\n\n可能原因：\n• Icon名称拼写错误\n• SO资源中缺少对应的Item\n• AreaId不匹配\n\n建议：\n1. 点击\"取消\"返回\n2. 检查Icon名称是否正确\n3. 确认SO中是否有对应资源\n\n强制保存可能导致运行时找不到资源！",
                "强制保存", "取消"))
            {
                return;
            }
        }
        
        // 保存前检测：路径有效性验证
        List<string> invalidPaths = ValidateConfigPaths(initRowsToSave, stepRowsToSave);
        if (invalidPaths.Count > 0)
        {
            string pathList = string.Join("\n", invalidPaths.Take(10));
            if (invalidPaths.Count > 10)
            {
                pathList += $"\n... 还有{invalidPaths.Count - 10}个无效路径";
            }
            
            if (!EditorUtility.DisplayDialog("⚠️ 检测到无效路径", 
                $"配置中引用的以下路径在场景中不存在：\n\n{pathList}\n\n可能原因：\n• 物体被删除或重命名\n• hierarchy层级调整后未点击\"名称排序\"\n\n建议：\n1. 点击\"取消\"返回\n2. 点击\"名称排序\"按钮修复\n3. 再次保存\n\n强制保存可能导致运行时错误！",
                "强制保存", "取消"))
            {
                return;
            }
        }
        
        // 智能补全初始化：检查步骤中所有Action引用的物体（新增物品默认为hide）
        AutoCompleteInitRows(initRowsToSave, stepRowsToSave);
        
        // ✅ 保存时完全遵循编辑器中的配置，不根据场景状态修改
        // 三种保存方式：
        // 1. 点击"记录初始状态" → 根据场景activeSelf设置show/hide
        // 2. 新增物品（AutoCompleteInitRows）→ 默认hide
        // 3. 编辑器中手动修改 → 保存编辑器中的值，不被场景覆盖
        
        // 保存配置到文件
        SaveConfigToFile(initRowsToSave, stepRowsToSave);
        
        // 保存后重新读取，刷新allConfigRows
        LoadConfigFromFile();
        
        // 保存原始数据用于下次对比
        originalAreaStepRows = DeepCopyRows(currentAreaStepRows);
        originalAreaInitRows = DeepCopyRows(currentAreaInitRows);
        
        // ✅ 关键修复：重新拷贝到tempAreaInitRows，以便用户可以继续编辑
        tempAreaInitRows = DeepCopyRows(currentAreaInitRows);
        
        // 重新刷新UI，让UI绑定到新的row对象
        RefreshStepEditUI();
        RefreshInitEditUI();  // 刷新初始状态编辑UI，绑定到新拷贝的tempAreaInitRows
        
        // 重置暂存状态
        isStepsModified = false;
        isInitRecorded = false;  // 重置为未修改状态，下次编辑时会重新标记
        isNewScene = false;
        // ❌ 不再清空tempAreaInitRows，保持与currentAreaInitRows同步
        // tempAreaInitRows.Clear();
        UpdateStatusLabel();
        
        EditorUtility.DisplayDialog("成功", "配置已保存！", "确定");
        AssetDatabase.Refresh();
    }

    private void LoadConfigFromFile()
    {
        allConfigRows.Clear();
        currentAreaInitRows.Clear();
        currentAreaStepRows.Clear();

        if (!File.Exists(configFilePath))
        {
            Debug.LogError($"配置文件不存在：{configFilePath}");
            EditorUtility.DisplayDialog("错误", $"配置文件不存在：\n{configFilePath}", "确定");
            return;
        }

        try
        {
            FileInfo fileInfo = new FileInfo(configFilePath);
            using (ExcelPackage package = new ExcelPackage(fileInfo))
            {
                // 按名称获取工作表
                ExcelWorksheet worksheet = package.Workbook.Worksheets[SHEET_NAME];
                if (worksheet == null)
                {
                    Debug.LogError($"找不到工作表：{SHEET_NAME}");
                    EditorUtility.DisplayDialog("错误", $"在Excel中找不到工作表：{SHEET_NAME}", "确定");
                    return;
                }

                if (worksheet.Dimension == null)
                {
                    Debug.LogWarning("工作表为空");
                    return;
                }

                int maxRows = worksheet.Dimension.End.Row;
                int maxCols = worksheet.Dimension.End.Column;
                
                Debug.Log($"开始读取配置文件：{configFilePath}，工作表：{SHEET_NAME}，数据范围：{maxRows}行 × {maxCols}列");
                
                int fixedCount = 0;  // 统计自动修复的行数
                
                // 从第3行开始读取数据（第1行是英文字段名，第2行是中文注释）
                for (int row = 3; row <= maxRows; row++)
                {
                    // 读取一行数据到string数组
                    List<string> fieldsList = new List<string>();
                    for (int col = 1; col <= maxCols; col++)
                    {
                        var cell = worksheet.Cells[row, col];
                        fieldsList.Add(cell.Value?.ToString() ?? "");
                    }
                    
                    string[] fields = fieldsList.ToArray();
                    
                    // 容错处理：如果列数不足，自动补全到17列（XLSX没有第一个空列）
                    if (fields.Length < 17)
                    {
                        fixedCount++;
                        while (fieldsList.Count < 17)
                        {
                            fieldsList.Add("");
                        }
                        fields = fieldsList.ToArray();
                    }

                    DecorateConfigRow configRow = new DecorateConfigRow();
                    configRow.ParseFromFields(fields);
                    allConfigRows.Add(configRow);

                    // 筛选当前场景的配置
                    if (configRow.AreaId == currentAreaId)
                    {
                        if (configRow.SortId == 0)
                        {
                            currentAreaInitRows.Add(configRow);
                        }
                        else
                        {
                            currentAreaStepRows.Add(configRow);
                        }
                    }
                }

                string fixedInfo = fixedCount > 0 ? $"，自动修复{fixedCount}行列数不足的数据" : "";
                Debug.Log($"配置文件加载完成，共{allConfigRows.Count}条数据{fixedInfo}");
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"读取配置文件失败：{ex.Message}\n{ex.StackTrace}");
            EditorUtility.DisplayDialog("错误", $"读取配置文件失败：\n{ex.Message}", "确定");
        }
    }

    private void SaveConfigToFile(List<DecorateConfigRow> initRows, List<DecorateConfigRow> stepRows)
    {
        try
        {
            // 移除当前场景的所有配置
            allConfigRows.RemoveAll(r => r.AreaId == currentAreaId);
            
            // 添加当前场景的配置
            allConfigRows.AddRange(initRows);
            allConfigRows.AddRange(stepRows);
            
            // 排序
            allConfigRows = allConfigRows.OrderBy(r => r.AreaId).ThenBy(r => r.SortId).ToList();

            // 写入XLSX文件
            FileInfo fileInfo = new FileInfo(configFilePath);
            
            using (ExcelPackage package = new ExcelPackage(fileInfo))
            {
                // 删除目标工作表（如果存在），保留其他工作表
                ExcelWorksheet existingSheet = package.Workbook.Worksheets[SHEET_NAME];
                if (existingSheet != null)
                {
                    package.Workbook.Worksheets.Delete(existingSheet);
                    Debug.Log($"已删除旧的工作表: {SHEET_NAME}");
                }
                
                // 创建新工作表
                ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(SHEET_NAME);
                
                // 写入表头（第1行：英文字段名）
                worksheet.Cells[1, 1].Value = "Id";
                worksheet.Cells[1, 2].Value = "AreaId";
                worksheet.Cells[1, 3].Value = "SortId";
                worksheet.Cells[1, 4].Value = "CostCount";
                worksheet.Cells[1, 5].Value = "Title";
                worksheet.Cells[1, 6].Value = "Icon";
                worksheet.Cells[1, 7].Value = "Pos";
                worksheet.Cells[1, 8].Value = "Action";
                worksheet.Cells[1, 9].Value = "Spine";
                worksheet.Cells[1, 10].Value = "Button";
                worksheet.Cells[1, 11].Value = "Build";
                worksheet.Cells[1, 12].Value = "Shine";
                worksheet.Cells[1, 13].Value = "Origin";
                worksheet.Cells[1, 14].Value = "DecoratePos";
                worksheet.Cells[1, 15].Value = "Skip";
                worksheet.Cells[1, 16].Value = "MapPethomeId";
                worksheet.Cells[1, 17].Value = "PetExp";
                
                // 写入第2行（中文注释）
                worksheet.Cells[2, 1].Value = "Id";
                worksheet.Cells[2, 2].Value = "区域Id";
                worksheet.Cells[2, 3].Value = "排序Id";
                worksheet.Cells[2, 4].Value = "消耗资源数量";
                worksheet.Cells[2, 5].Value = "标题";
                worksheet.Cells[2, 6].Value = "图标";
                worksheet.Cells[2, 7].Value = "位置";
                worksheet.Cells[2, 8].Value = "行为";
                worksheet.Cells[2, 9].Value = "交互动画";
                worksheet.Cells[2, 10].Value = "对应按钮";
                worksheet.Cells[2, 11].Value = "建造效果";
                worksheet.Cells[2, 12].Value = "闪光效果";
                worksheet.Cells[2, 13].Value = "原始大小/装饰特效位置";
                worksheet.Cells[2, 14].Value = "装饰图标位置";
                worksheet.Cells[2, 15].Value = "跳过逐步";
                worksheet.Cells[2, 16].Value = "PetHome映射";
                worksheet.Cells[2, 17].Value = "宠物经验";
                
                // 写入数据行（从第3行开始）
                int autoId = 1;
                int excelRow = 3;
                foreach (var row in allConfigRows)
                {
                    row.WriteToExcelRow(worksheet, excelRow, autoId);
                    autoId++;
                    excelRow++;
                }
                
                // 保存文件
                package.Save();
                
                Debug.Log($"配置文件已保存：{configFilePath}，共{allConfigRows.Count}条数据");
                EditorUtility.DisplayDialog("成功", $"配置已保存到：\n{configFilePath}\n\n共{allConfigRows.Count}条数据", "确定");
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"保存配置文件失败：{ex.Message}\n{ex.StackTrace}");
            EditorUtility.DisplayDialog("错误", $"保存配置文件失败：\n{ex.Message}", "确定");
        }
    }

    #endregion

    #region 场景操作

    private void OnRecordInitClicked()
    {
        UpdateBgTransform();
        
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点！", "确定");
            return;
        }

        currentAreaId = areaIdField.value;
        
        // 检查是否需要初始化步骤列表
        if (currentAreaStepRows.Count == 0)
        {
            CreateEmptySteps();
            isNewScene = true;
            originalAreaStepRows.Clear();
            originalAreaInitRows.Clear();
        }
        
        tempAreaInitRows.Clear();  // 记录到暂存区

        // 记录bg本身
        RecordBgInit(tempAreaInitRows);

        // 记录clearObj
        Transform clearObj = bgTransform.Find("clearObj");
        if (clearObj != null)
        {
            for (int i = 0; i < clearObj.childCount; i++)
            {
                RecordObjectInit(tempAreaInitRows, clearObj.GetChild(i), $"bg/clearObj/{i + 1}");
            }
        }

        // 记录addObj
        Transform addObj = bgTransform.Find("addObj");
        if (addObj != null)
        {
            for (int i = 0; i < addObj.childCount; i++)
            {
                RecordObjectInit(tempAreaInitRows, addObj.GetChild(i), $"bg/addObj/{i + 1}");
            }
        }

        // 标记为已记录
        isInitRecorded = true;
        UpdateStatusLabel();
        
        // 刷新初始状态编辑UI
        RefreshInitEditUI();
        
        EditorUtility.DisplayDialog("成功", $"已记录{tempAreaInitRows.Count}个初始化对象到暂存区\n\n点击\"保存配置\"将写入文件", "确定");
    }

    private void RecordBgInit(List<DecorateConfigRow> targetList)
    {
        var image = bgTransform.GetComponent<UnityEngine.UI.Image>();
        if (image != null && image.sprite != null)
        {
            string spritePath = AssetDatabase.GetAssetPath(image.sprite.texture);
            string iconPath = ExtractIconPath(spritePath);

            DecorateConfigRow row = new DecorateConfigRow
            {
                AreaId = currentAreaId,
                SortId = 0,
                CostCount = 0,
                Title = "show",
                Icon = iconPath,
                Pos = "0#0",
                Action = "init_img#bg",
                Spine = "",
                Button = "",
                Build = "",
                Shine = "",
                Origin = "1232#2048",
                DecoratePos = "",
                Skip = "",
                MapPethomeId = "",
                PetExp = ""
            };

            targetList.Add(row);
        }
    }

    private void RecordObjectInit(List<DecorateConfigRow> targetList, Transform obj, string path)
    {
        var image = obj.GetComponent<UnityEngine.UI.Image>();
        if (image == null || image.sprite == null) return;

        string spritePath = AssetDatabase.GetAssetPath(image.sprite.texture);
        string iconPath = ExtractIconPath(spritePath);

        RectTransform rt = obj.GetComponent<RectTransform>();
        string pos = $"{(int)rt.anchoredPosition.x}#{(int)rt.anchoredPosition.y}";
        string origin = $"{(int)rt.sizeDelta.x}#{(int)rt.sizeDelta.y}";
        // 根据物体当前的显示状态记录（手动记录初始状态时应该反映实际状态）
        string title = obj.gameObject.activeSelf ? "show" : "hide";

        DecorateConfigRow row = new DecorateConfigRow
        {
            AreaId = currentAreaId,
            SortId = 0,
            CostCount = 0,
            Title = title,
            Icon = iconPath,
            Pos = pos,
            Action = $"init_img#{path}",
            Spine = "",
            Button = "",
            Build = "",
            Shine = "",
            Origin = origin,
            DecoratePos = "",
            Skip = "",
            MapPethomeId = "",
            PetExp = ""
        };

        targetList.Add(row);
    }

    private string ExtractIconPath(string fullPath)
    {
        // 首先尝试从SO中查找匹配的Sprite路径，返回其Name
        // 加载DecorateIcon SO
        ArtTableSO iconSO = LoadDecorateIconSO();
        if (iconSO != null && iconSO.Items != null)
        {
            foreach (var item in iconSO.Items)
            {
                if (item.Sprite != null)
                {
                    string itemPath = AssetDatabase.GetAssetPath(item.Sprite);
                    if (itemPath == fullPath)
                    {
                        return item.Name;
                    }
                }
            }
        }
        
        // 尝试从Scene SO中查找
        ArtTableSO sceneSO = LoadDecorateSceneSO(currentAreaId);
        if (sceneSO != null && sceneSO.Items != null)
        {
            foreach (var item in sceneSO.Items)
            {
                if (item.Sprite != null)
                {
                    string itemPath = AssetDatabase.GetAssetPath(item.Sprite);
                    if (itemPath == fullPath)
                    {
                        return item.Name;
                    }
                }
            }
        }
        
        // 如果在SO中找不到，尝试从路径中提取（兼容旧格式）
        int decorateIndex = fullPath.IndexOf("Decorate/");
        if (decorateIndex >= 0)
        {
            string path = fullPath.Substring(decorateIndex + 9); // 跳过"Decorate/"
            path = path.Replace(".png", "");
            // 只保留最后一段路径（文件名）
            if (path.Contains("/"))
            {
                path = path.Substring(path.LastIndexOf('/') + 1);
            }
            Debug.LogWarning($"在SO中未找到Sprite，使用从路径提取的名称: {path}");
            return path;
        }
        
        Debug.LogWarning($"无法从路径提取Icon名称: {fullPath}");
        return "";
    }

    private void OnClearSceneClicked()
    {
        UpdateBgTransform();
        
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点！", "确定");
            return;
        }

        if (!EditorUtility.DisplayDialog("确认", "确定要清空场景中的所有物体状态吗？", "确定", "取消"))
        {
            return;
        }
        
        ClearSceneInternal();

        EditorUtility.DisplayDialog("成功", "场景已清空", "确定");
    }
    
    private void OnSortNamesClicked()
    {
        // 只有当bgObjectField有值时才更新，避免覆盖已有的有效bgTransform
        if (bgObjectField != null && bgObjectField.value != null)
        {
            UpdateBgTransform();
        }
        
        if (bgTransform == null)
        {
            EditorUtility.DisplayDialog("错误", "请先拖入bg节点！", "确定");
            return;
        }

        if (!EditorUtility.DisplayDialog("确认", "确定要按hierarchy顺序将clearObj和addObj的子物体重命名为 1, 2, 3... 吗？\n\n此操作会同时更新所有步骤配置中的路径。", "确定", "取消"))
        {
            return;
        }
        
        // 记录旧路径 -> 新路径的映射
        Dictionary<string, string> pathMapping = new Dictionary<string, string>();
        int totalRenamed = 0;
        
        // 重命名clearObj的子物体
        Transform clearObj = bgTransform.Find("clearObj");
        if (clearObj != null)
        {
            for (int i = 0; i < clearObj.childCount; i++)
            {
                Transform child = clearObj.GetChild(i);
                string oldPath = GetTransformPath(child);
                string newName = (i + 1).ToString();
                
                if (child.name != newName)
                {
                    child.name = newName;
                    string newPath = GetTransformPath(child);
                    pathMapping[oldPath] = newPath;
                    totalRenamed++;
                }
            }
        }

        // 重命名addObj的子物体
        Transform addObj = bgTransform.Find("addObj");
        if (addObj != null)
        {
            for (int i = 0; i < addObj.childCount; i++)
            {
                Transform child = addObj.GetChild(i);
                string oldPath = GetTransformPath(child);
                string newName = (i + 1).ToString();
                
                if (child.name != newName)
                {
                    child.name = newName;
                    string newPath = GetTransformPath(child);
                    pathMapping[oldPath] = newPath;
                    totalRenamed++;
                }
            }
        }

        // 更新所有步骤配置中的路径
        if (pathMapping.Count > 0)
        {
            int updatedSteps = UpdateActionPaths(pathMapping);
            
            // 强制重新扫描场景并更新初始化配置
            Debug.Log("名称排序后自动重新扫描初始化配置...");
            ScanAndUpdateInitAfterRename();
            
            // 同步更新原始数据，避免CompareStepChanges误报
            if (!isNewScene)
            {
                originalAreaStepRows = DeepCopyRows(currentAreaStepRows);
                originalAreaInitRows = DeepCopyRows(tempAreaInitRows);
            }
            
            // 注意：名称排序只更新路径，不标记为已修改（不影响步骤颜色状态）
            // 只刷新UI显示更新后的路径
            RefreshStepEditUI();
            RefreshInitEditUI();  // 刷新初始状态编辑UI，显示新扫描的物体
            UpdateStepGridButtonStates();  // 更新步骤网格颜色
            
            string message = $"✅ 已完成名称排序：\n\n";
            message += $"• 重命名物体：{totalRenamed}个\n";
            message += $"  - clearObj: {(clearObj != null ? clearObj.childCount : 0)}个\n";
            message += $"  - addObj: {(addObj != null ? addObj.childCount : 0)}个\n\n";
            message += $"• 更新步骤配置：{updatedSteps}个步骤\n";
            message += $"• 重新扫描初始化配置：{tempAreaInitRows.Count}个物体\n\n";
            message += "⚠️ 注意：初始化配置已从场景重新扫描，\n如有手动修改的特殊字段请检查。\n\n";
            message += "请保存配置和场景以保留修改。";
            
            EditorUtility.DisplayDialog("完成", message, "确定");
        }
        else
        {
            EditorUtility.DisplayDialog("提示", "所有物体名称已是标准格式，无需重命名。", "确定");
        }
    }
    
    private void OnAutoSetIconClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        if (!EditorUtility.DisplayDialog("确认", $"确定要自动设置AreaId={currentAreaId}的所有步骤Icon吗？\n\n将查找格式为 s{currentAreaId}_icon_renwu_{{步骤}} 的图标。", "确定", "取消"))
        {
            return;
        }
        
        int foundCount = 0;
        int notFoundCount = 0;
        StringBuilder notFoundSteps = new StringBuilder();
        
        foreach (var row in currentAreaStepRows)
        {
            // 构建Icon路径：s{AreaId}_icon_renwu_{SortId}
            string iconName = $"s{currentAreaId}_icon_renwu_{row.SortId}";
            
            // 验证Icon是否存在于SO中
            if (ValidateIconNameInSO(iconName, currentAreaId, false, out string errorMsg))
            {
                row.Icon = iconName;
                foundCount++;
            }
            else
            {
                notFoundCount++;
                if (notFoundSteps.Length < 200) // 限制显示长度
                {
                    notFoundSteps.Append($"步骤{row.SortId} ");
                }
            }
        }
        
        // 标记为已修改
        MarkStepsModified();
        
        // 刷新UI
        RefreshStepEditUI();
        
        // 显示结果
        StringBuilder message = new StringBuilder();
        message.AppendLine($"自动设置完成！");
        message.AppendLine($"\n找到：{foundCount}个Icon");
        message.AppendLine($"未找到：{notFoundCount}个Icon");
        
        if (notFoundCount > 0 && notFoundSteps.Length > 0)
        {
            message.AppendLine($"\n未找到的步骤：");
            message.AppendLine(notFoundSteps.ToString());
        }
        
        message.AppendLine($"\n请检查步骤配置，确认后点击\"保存配置\"。");
        
        EditorUtility.DisplayDialog("完成", message.ToString(), "确定");
    }
    
    private void ClearSceneInternal()
    {
        if (bgTransform == null) return;

        // 清空bg的sprite
        var bgImage = bgTransform.GetComponent<UnityEngine.UI.Image>();
        if (bgImage != null)
        {
            bgImage.sprite = null;
        }

        // 清空所有clearObj的sprite并隐藏
        Transform clearObj = bgTransform.Find("clearObj");
        if (clearObj != null)
        {
            for (int i = 0; i < clearObj.childCount; i++)
            {
                Transform child = clearObj.GetChild(i);
                child.gameObject.SetActive(false);
                
                var image = child.GetComponent<UnityEngine.UI.Image>();
                if (image != null)
                {
                    image.sprite = null;
                }
            }
        }

        // 清空所有addObj的sprite并隐藏
        Transform addObj = bgTransform.Find("addObj");
        if (addObj != null)
        {
            for (int i = 0; i < addObj.childCount; i++)
            {
                Transform child = addObj.GetChild(i);
                child.gameObject.SetActive(false);
                
                var image = child.GetComponent<UnityEngine.UI.Image>();
                if (image != null)
                {
                    image.sprite = null;
                }
            }
        }
    }

    #endregion

    #region 步骤预览

    private void OnPrevStepClicked()
    {
        if (currentStepIndex > 0)
        {
            int targetStep = currentStepIndex - 1;
            
            // 检查目标步骤是否有配置（步骤0是初始状态，始终允许）
            if (targetStep > 0 && !IsStepConfigured(targetStep))
            {
                EditorUtility.DisplayDialog("提示", $"步骤{targetStep}还未配置（Action为空）\n\n请先为该步骤添加操作并保存配置后再预览。", "确定");
                return;
            }
            
            currentStepIndex = targetStep;
            currentStepField.value = currentStepIndex;
            RestoreSceneToStep(currentStepIndex);
            UpdateStepGridButtonStates();
        }
    }

    private void OnNextStepClicked()
    {
        if (currentStepIndex < maxSteps)
        {
            int targetStep = currentStepIndex + 1;
            
            // 检查目标步骤是否有配置
            if (!IsStepConfigured(targetStep))
            {
                EditorUtility.DisplayDialog("提示", $"步骤{targetStep}还未配置（Action为空）\n\n请先为该步骤添加操作并保存配置后再预览。", "确定");
                return;
            }
            
            currentStepIndex = targetStep;
            currentStepField.value = currentStepIndex;
            RestoreSceneToStep(currentStepIndex);
            UpdateStepGridButtonStates();
        }
    }

    private void OnGotoStepClicked()
    {
        int targetStep = currentStepField.value;
        if (targetStep >= 0 && targetStep <= maxSteps)
        {
            // 检查目标步骤是否有配置（步骤0是初始状态，始终允许）
            if (targetStep > 0 && !IsStepConfigured(targetStep))
            {
                EditorUtility.DisplayDialog("提示", $"步骤{targetStep}还未配置（Action为空）\n\n请先为该步骤添加操作并保存配置后再预览。", "确定");
                return;
            }
            
            currentStepIndex = targetStep;
            RestoreSceneToStep(currentStepIndex);
            UpdateStepGridButtonStates();
        }
        else
        {
            EditorUtility.DisplayDialog("错误", $"步骤范围应在0-{maxSteps}之间", "确定");
        }
    }
    
    private void OnShowDecorateButtonClicked()
    {
        if (decoratePanelTransform == null)
        {
            AutoFindDecoratePanel();
            if (decoratePanelTransform == null)
            {
                EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel！\n请确保场景中存在Canvas/AreaDecoratePanel", "确定");
                return;
            }
        }
        
        if (currentStepIndex == 0)
        {
            EditorUtility.DisplayDialog("提示", "当前处于步骤0（初始状态）\n装饰按钮对应步骤1-25", "确定");
            return;
        }
        
        // 获取当前步骤的配置
        var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == currentStepIndex);
        if (stepRow == null)
        {
            EditorUtility.DisplayDialog("错误", $"未找到步骤{currentStepIndex}的配置！", "确定");
            return;
        }
        
        // 显示AreaDecoratePanel
        decoratePanelTransform.gameObject.SetActive(true);
        
        // 查找ImageBg/grid/Item_1
        Transform imageBg = decoratePanelTransform.Find("ImageBg");
        if (imageBg == null)
        {
            Debug.LogWarning("未找到AreaDecoratePanel/ImageBg");
            return;
        }
        
        Transform grid = imageBg.Find("grid");
        if (grid == null)
        {
            Debug.LogWarning("未找到AreaDecoratePanel/ImageBg/grid");
            return;
        }
        
        Transform item1 = grid.Find("Item_1");
        if (item1 == null)
        {
            Debug.LogWarning("未找到AreaDecoratePanel/ImageBg/grid/Item_1");
            return;
        }
        
        // 从Icon路径加载Sprite，获取其位置设置给Item_1
        if (!string.IsNullOrEmpty(stepRow.Icon))
        {
            // 查找Item_1/objS，获取objS上的Image组件
            Transform objS = item1.Find("objS");
            if (objS != null)
            {
                UnityEngine.UI.Image imageComponent = objS.GetComponent<UnityEngine.UI.Image>();
                if (imageComponent != null)
                {
                    // 从SO中加载Icon（步骤配置从DecorateIcon加载）
                    Sprite sprite = FindSpriteInSO(stepRow.Icon, currentAreaId, false);
                    
                    if (sprite != null)
                    {
                        imageComponent.sprite = sprite;
                        Debug.Log($"成功从SO中设置Item_1/objS的Image组件 sprite: {stepRow.Icon}");
                    }
                    else
                    {
                        Debug.LogWarning($"未在SO中找到Icon: {stepRow.Icon} (AreaId={currentAreaId})");
                    }
                }
                else
                {
                    Debug.LogWarning("Item_1/objS 没有Image组件");
                }
            }
            else
            {
                Debug.LogWarning("未找到Item_1/objS");
            }
        }
        
        // 从DecoratePos设置Item_1的位置
        if (!string.IsNullOrEmpty(stepRow.DecoratePos))
        {
            string[] posParts = stepRow.DecoratePos.Split('#');
            if (posParts.Length == 2)
            {
                float x, y;
                if (float.TryParse(posParts[0], out x) && float.TryParse(posParts[1], out y))
                {
                    RectTransform rt = item1.GetComponent<RectTransform>();
                    if (rt != null)
                    {
                        rt.anchoredPosition = new Vector2(x, y);
                        Debug.Log($"装饰按钮已显示，位置设置为({x}, {y})");
                    }
                }
            }
        }
        else
        {
            Debug.LogWarning($"步骤{currentStepIndex}没有DecoratePos配置，使用默认位置");
        }
    }
    
    private void OnHideDecorateButtonClicked()
    {
        if (decoratePanelTransform == null)
        {
            AutoFindDecoratePanel();
        }
        
        if (decoratePanelTransform != null)
        {
            decoratePanelTransform.gameObject.SetActive(false);
            Debug.Log("装饰按钮已隐藏");
        }
        else
        {
            EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel！", "确定");
        }
    }

    /// <summary>
    /// 检测步骤中使用的路径，如果发现场景中存在但初始化列表中没有的物体，自动添加到暂存区
    /// </summary>
    private void CheckAndAddNewObjectsFromSteps(int stepIndex)
    {
        if (bgTransform == null) return;
        
        // 收集所有步骤中使用的路径
        HashSet<string> usedPaths = new HashSet<string>();
        for (int i = 1; i <= stepIndex; i++)
        {
            var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == i);
            if (stepRow == null || string.IsNullOrEmpty(stepRow.Action)) continue;
            
            string[] actions = stepRow.Action.Split('@');
            foreach (string action in actions)
            {
                string[] parts = action.Split('#');
                if (parts.Length < 2) continue;
                
                string actionType = parts[0];
                string paths = parts[1];
                
                // 收集add、replace等操作中的路径
                if (actionType == "add" || actionType == "clear")
                {
                    string[] pathArray = paths.Split(',');
                    foreach (string path in pathArray)
                    {
                        usedPaths.Add(path);
                    }
                }
                else if (actionType == "replace")
                {
                    string[] pathArray = paths.Split(',');
                    // replace操作有两个路径：旧路径和新路径
                    foreach (string path in pathArray)
                    {
                        usedPaths.Add(path);
                    }
                }
            }
        }
        
        // 检查这些路径是否在初始化列表中
        foreach (string path in usedPaths)
        {
            string actualPath = path.StartsWith("bg/") ? path.Substring(3) : path;
            
            // 检查是否已在初始化列表中
            bool existsInInit = tempAreaInitRows.Any(r => r.Action.Contains(actualPath)) || 
                                currentAreaInitRows.Any(r => r.Action.Contains(actualPath));
            
            if (!existsInInit)
            {
                // 检查场景中是否存在该物体
                Transform target = (actualPath == "bg") ? bgTransform : bgTransform.Find(actualPath);
                if (target != null)
                {
                    // 自动添加到暂存区
                    var image = target.GetComponent<UnityEngine.UI.Image>();
                    
                    // 即使没有sprite也要添加，避免物体显示不出来
                    string iconPath = "";
                    if (image != null && image.sprite != null)
                    {
                        string spritePath = AssetDatabase.GetAssetPath(image.sprite.texture);
                        iconPath = ExtractIconPath(spritePath);
                    }
                    else
                    {
                        Debug.LogWarning($"⚠ 物体 {path} 没有设置sprite，Icon将为空。请手动在初始状态编辑中设置Icon路径。");
                    }
                    
                    RectTransform rt = target.GetComponent<RectTransform>();
                    string pos = rt != null ? $"{(int)rt.anchoredPosition.x}#{(int)rt.anchoredPosition.y}" : "0#0";
                    string origin = rt != null ? $"{(int)rt.sizeDelta.x}#{(int)rt.sizeDelta.y}" : "0#0";
                    
                    DecorateConfigRow newRow = new DecorateConfigRow
                    {
                        AreaId = currentAreaId,
                        SortId = 0,
                        CostCount = 0,
                        Title = "hide",  // 新物体默认hide
                        Icon = iconPath,
                        Pos = pos,
                        Action = $"init_img#{path}",
                        Spine = "",
                        Button = "",
                        Build = "",
                        Shine = "",
                        Origin = origin,
                        DecoratePos = "",
                        Skip = "",
                        MapPethomeId = "",
                        PetExp = ""
                    };
                    
                    tempAreaInitRows.Add(newRow);
                    currentAreaInitRows.Add(newRow);  // 也添加到当前列表，以便立即生效
                    isInitRecorded = true;
                    
                    Debug.Log($"✅ 自动添加新物体到初始化列表: {path} (Icon={iconPath})");
                }
            }
        }
        
        // 刷新初始状态编辑UI
        if (isInitRecorded)
        {
            RefreshInitEditUI();
        }
    }

    private void RestoreSceneToStep(int stepIndex)
    {
        UpdateBgTransform();
        
        if (bgTransform == null)
        {
            Debug.LogWarning("⚠ bg未设置，无法还原场景");
            return;
        }

        Debug.Log($"=== 开始还原场景到步骤 {stepIndex} ===");
        
        // 在还原场景前，检测步骤中是否有新物体需要添加到初始化列表
        CheckAndAddNewObjectsFromSteps(stepIndex);
        
        // 先清空场景
        ClearSceneInternal();
        
        // 检查是否有初始化配置
        if (currentAreaInitRows.Count == 0)
        {
            Debug.LogWarning("⚠⚠⚠ 没有初始化配置（sortId=0），将跳过初始化阶段");
            Debug.LogWarning("建议：先点击\"记录初始状态\"并保存，以便正确预览场景。");
        }
        else
        {
            // 应用初始化状态
            ApplyInitRows();
        }

        // 应用步骤1到stepIndex的所有操作
        for (int i = 1; i <= stepIndex; i++)
        {
            var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == i);
            if (stepRow != null)
            {
                ApplyStepAction(stepRow);
            }
        }

        // 更新步骤信息
        if (stepIndex == 0)
        {
            stepInfoLabel.text = "初始状态";
        }
        else
        {
            var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == stepIndex);
            if (stepRow != null)
            {
                stepInfoLabel.text = $"步骤{stepIndex}: {stepRow.Title}";
            }
            else
            {
                stepInfoLabel.text = $"步骤{stepIndex}";
            }
        }
        
        // 如果装饰按钮正在显示，更新其位置
        UpdateDecorateButtonPosition(stepIndex);
        
        Debug.Log($"=== 场景还原完成 ===");
    }
    
    /// <summary>
    /// 更新装饰按钮位置（如果正在显示）
    /// </summary>
    private void UpdateDecorateButtonPosition(int stepIndex)
    {
        // 检查装饰面板是否存在且显示中
        if (decoratePanelTransform == null || !decoratePanelTransform.gameObject.activeSelf)
        {
            return;
        }
        
        // 步骤0没有装饰按钮
        if (stepIndex == 0)
        {
            return;
        }
        
        // 获取当前步骤的配置
        var stepRow = currentAreaStepRows.FirstOrDefault(r => r.SortId == stepIndex);
        if (stepRow == null)
        {
            return;
        }
        
        // 查找Item_1
        Transform imageBg = decoratePanelTransform.Find("ImageBg");
        Transform grid = imageBg?.Find("grid");
        Transform item1 = grid?.Find("Item_1");
        RectTransform rt = item1?.GetComponent<RectTransform>();
        
        if (rt == null)
        {
            return;
        }
        
        // 更新Icon图片
        if (!string.IsNullOrEmpty(stepRow.Icon))
        {
            Transform objS = item1.Find("objS");
            if (objS != null)
            {
                UnityEngine.UI.Image imageComponent = objS.GetComponent<UnityEngine.UI.Image>();
                if (imageComponent != null)
                {
                    // 从SO中加载Icon
                    Sprite sprite = LoadSpriteFromIconName(stepRow.Icon, currentAreaId, false);
                    if (sprite != null)
                    {
                        imageComponent.sprite = sprite;
                    }
                }
            }
        }
        
        // 更新位置
        if (!string.IsNullOrEmpty(stepRow.DecoratePos))
        {
            string[] posParts = stepRow.DecoratePos.Split('#');
            if (posParts.Length == 2)
            {
                float x, y;
                if (float.TryParse(posParts[0], out x) && float.TryParse(posParts[1], out y))
                {
                    rt.anchoredPosition = new Vector2(x, y);
                }
            }
        }
    }

    private void ApplyInitRows()
    {
        // ⚠️ 关键修复：优先使用暂存区数据（如果已记录），否则使用原始数据
        List<DecorateConfigRow> initRowsToApply = isInitRecorded ? tempAreaInitRows : currentAreaInitRows;
        
        if (initRowsToApply.Count == 0)
        {
            Debug.LogWarning("⚠ 没有初始化配置行（sortId=0），跳过初始化阶段");
            Debug.LogWarning("提示：如果需要正确预览，请先设置场景初始状态，然后点击\"记录初始状态\"并保存。");
            return;
        }
        
        string dataSource = isInitRecorded ? "暂存区" : "原始配置";
        Debug.Log($"开始应用{initRowsToApply.Count}个初始化配置（数据源：{dataSource}）");
        
        try
        {
            foreach (var row in initRowsToApply)
            {
                Debug.Log($"正在应用初始化：AreaId={row.AreaId}, SortId={row.SortId}, Title={row.Title}, Icon={row.Icon}, Action={row.Action}");
                try
                {
                    ApplyInitAction(row);
                }
                catch (System.Exception ex)
                {
                    Debug.LogError($"❌ 应用初始化行失败：{ex.Message}\n{ex.StackTrace}");
                }
            }
            
            Debug.Log($"初始化配置应用完成（数据源：{dataSource}）");
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"❌ ApplyInitRows异常：{ex.Message}\n{ex.StackTrace}");
        }
    }

    private void ApplyInitAction(DecorateConfigRow row)
    {
        Debug.Log($"📍 ApplyInitAction: Title={row.Title}, Icon={row.Icon}, Action={row.Action}");
        
        // 跳过init_spine类型
        if (row.Action.StartsWith("init_spine#"))
        {
            Debug.Log($"跳过init_spine: {row.Action}");
            return;
        }
        
        if (!row.Action.StartsWith("init_img#"))
        {
            Debug.LogWarning($"⚠️ Action不是init_img格式：{row.Action}");
            return;
        }

        string path = row.Action.Substring(9); // 去掉"init_img#"
        Debug.Log($"📍 解析路径：原始={path}");
        
        // bgTransform已经是bg节点，需要去掉路径中的"bg/"前缀
        if (path == "bg")
        {
            // 如果路径就是bg，target就是bgTransform本身
            path = "";
        }
        else if (path.StartsWith("bg/"))
        {
            // 去掉"bg/"前缀
            path = path.Substring(3);
        }
        
        Transform target = string.IsNullOrEmpty(path) ? bgTransform : bgTransform.Find(path);
        if (target == null)
        {
            Debug.LogWarning($"找不到路径：{path}，完整Action：{row.Action}");
            
            // 调试：列出父节点下的所有子物体
            string[] pathParts = path.Split('/');
            if (pathParts.Length > 0)
            {
                Transform parent = bgTransform;
                for (int i = 0; i < pathParts.Length - 1; i++)
                {
                    parent = parent.Find(pathParts[i]);
                    if (parent == null)
                    {
                        Debug.LogError($"无法找到中间路径：{pathParts[i]}");
                        return;
                    }
                }
                
                // 列出父节点下的所有子物体
                Debug.Log($"父节点 {parent.name} 下的所有子物体（共{parent.childCount}个）：");
                for (int i = 0; i < parent.childCount; i++)
                {
                    Debug.Log($"  [{i}] = \"{parent.GetChild(i).name}\"");
                }
                Debug.Log($"需要查找的名字：\"{pathParts[pathParts.Length - 1]}\"");
            }
            
            return;
        }

        // 加载图片 - 从SO中加载（初始化场景从DecorateScene加载，isInitScene=true）
        Sprite sprite = LoadSpriteFromIconName(row.Icon, currentAreaId, true);
        
        if (sprite != null)
        {
            var image = target.GetComponent<UnityEngine.UI.Image>();
            if (image != null)
            {
                image.sprite = sprite;
                Debug.Log($"✓ 成功从DecorateScene SO加载图片：{row.Icon} -> {path}");
            }
            else
            {
                Debug.LogWarning($"路径 {path} 的物体没有Image组件");
            }
        }
        else
        {
            Debug.LogWarning($"⚠ 在DecorateScene SO中未找到图片：{row.Icon} (AreaId={currentAreaId})");
        }

        // 设置位置和大小（跳过bg本身，保持原始状态）
        if (target != bgTransform)
        {
            // 设置位置
            if (!string.IsNullOrEmpty(row.Pos) && row.Pos != "0#0")
            {
                string[] posArr = row.Pos.Split('#');
                if (posArr.Length == 2)
                {
                    int x = int.Parse(posArr[0]);
                    int y = int.Parse(posArr[1]);
                    RectTransform rt = target.GetComponent<RectTransform>();
                    if (rt != null)
                    {
                        rt.anchoredPosition = new Vector2(x, y);
                    }
                }
            }

            // 设置大小
            if (!string.IsNullOrEmpty(row.Origin))
            {
                string[] sizeArr = row.Origin.Split('#');
                if (sizeArr.Length == 2)
                {
                    int w = int.Parse(sizeArr[0]);
                    int h = int.Parse(sizeArr[1]);
                    RectTransform rt = target.GetComponent<RectTransform>();
                    if (rt != null)
                    {
                        rt.sizeDelta = new Vector2(w, h);
                    }
                }
            }
        }

        // 设置显示/隐藏
        target.gameObject.SetActive(row.Title == "show");
        
        Debug.Log($"应用初始化：{path}, 显示状态：{row.Title}");
    }

    private void ApplyStepAction(DecorateConfigRow row)
    {
        if (string.IsNullOrEmpty(row.Action)) return;

        string[] actions = row.Action.Split('@');
        foreach (string action in actions)
        {
            string[] parts = action.Split('#');
            if (parts.Length < 2) continue;

            string actionType = parts[0];
            string paths = parts[1];

            // 跳过所有spine相关操作
            if (actionType.Contains("spine"))
            {
                Debug.Log($"跳过spine操作: {action}");
                continue;
            }

            switch (actionType)
            {
                case "clear":
                    ApplyClearAction(paths);
                    break;
                case "add":
                    ApplyAddAction(paths);
                    break;
                case "replace":
                    ApplyReplaceAction(paths);
                    break;
                case "replace_image":
                    // replace_image是替换节点的图片，不是替换节点本身
                    ApplyReplaceImageAction(paths);
                    break;
                case "reset_pos":
                    ApplyResetPosAction(paths);
                    break;
            }
        }
    }

    private void ApplyClearAction(string paths)
    {
        string[] pathArray = paths.Split(',');
        foreach (string path in pathArray)
        {
            // 去掉bg/前缀
            string actualPath = path.StartsWith("bg/") ? path.Substring(3) : path;
            Transform target = bgTransform.Find(actualPath);
            if (target != null)
            {
                target.gameObject.SetActive(false);
                Debug.Log($"clear: {actualPath} 已隐藏");
            }
            else
            {
                Debug.LogWarning($"clear: 找不到路径 {actualPath} (原始: {path})");
            }
        }
    }

    private void ApplyAddAction(string paths)
    {
        string[] pathArray = paths.Split(',');
        foreach (string path in pathArray)
        {
            // 去掉bg/前缀
            string actualPath = path.StartsWith("bg/") ? path.Substring(3) : path;
            Transform target = bgTransform.Find(actualPath);
            if (target != null)
            {
                target.gameObject.SetActive(true);
                Debug.Log($"add: {actualPath} 已显示");
            }
            else
            {
                Debug.LogWarning($"add: 找不到路径 {actualPath} (原始: {path})");
            }
        }
    }

    private void ApplyReplaceAction(string paths)
    {
        string[] pathArray = paths.Split(',');
        if (pathArray.Length == 2)
        {
            // 去掉bg/前缀
            string oldPath = pathArray[0].StartsWith("bg/") ? pathArray[0].Substring(3) : pathArray[0];
            string newPath = pathArray[1].StartsWith("bg/") ? pathArray[1].Substring(3) : pathArray[1];
            
            // 特殊处理：如果路径是"bg"，target就是bgTransform本身
            Transform oldTarget = (oldPath == "bg") ? bgTransform : bgTransform.Find(oldPath);
            Transform newTarget = (newPath == "bg") ? bgTransform : bgTransform.Find(newPath);
            
            if (oldTarget != null)
            {
                oldTarget.gameObject.SetActive(false);
                Debug.Log($"replace: {oldPath} 已隐藏");
            }
            else
            {
                Debug.LogWarning($"replace: 找不到旧路径 {oldPath} (原始: {pathArray[0]})");
            }
            
            if (newTarget != null)
            {
                newTarget.gameObject.SetActive(true);
                Debug.Log($"replace: {newPath} 已显示");
            }
            else
            {
                Debug.LogWarning($"replace: 找不到新路径 {newPath} (原始: {pathArray[1]})");
            }
        }
    }

    private void ApplyReplaceImageAction(string paths)
    {
        string[] pathArray = paths.Split(',');
        if (pathArray.Length == 2)
        {
            // 第一个是目标节点路径，第二个是图片路径
            string targetPath = pathArray[0].StartsWith("bg/") ? pathArray[0].Substring(3) : pathArray[0];
            string imagePath = pathArray[1];
            
            // 特殊处理：如果路径是"bg"，target就是bgTransform本身
            Transform target = (targetPath == "bg") ? bgTransform : bgTransform.Find(targetPath);
            
            if (target == null)
            {
                Debug.LogWarning($"replace_image: 找不到目标节点 {targetPath} (原始: {pathArray[0]})");
                return;
            }
            
            var image = target.GetComponent<UnityEngine.UI.Image>();
            if (image == null)
            {
                Debug.LogWarning($"replace_image: 节点 {targetPath} 没有Image组件");
                return;
            }
            
            // 从SO中加载图片
            Sprite sprite = LoadSpriteFromIconName(imagePath, currentAreaId, false);
            
            if (sprite != null)
            {
                image.sprite = sprite;
                Debug.Log($"replace_image: {targetPath} 图片已替换为 {imagePath}");
            }
            else
            {
                Debug.LogWarning($"replace_image: 在SO中找不到图片 {imagePath}");
            }
        }
    }
    
    private void ApplyResetPosAction(string paths)
    {
        string[] pathArray = paths.Split(',');
        if (pathArray.Length == 2)
        {
            // 第一个是目标节点路径，第二个是位置(x=y格式)
            string targetPath = pathArray[0].StartsWith("bg/") ? pathArray[0].Substring(3) : pathArray[0];
            string positionStr = pathArray[1];
            
            Transform target = (targetPath == "bg") ? bgTransform : bgTransform.Find(targetPath);
            
            if (target == null)
            {
                Debug.LogWarning($"reset_pos: 找不到目标节点 {targetPath} (原始: {pathArray[0]})");
                return;
            }
            
            // 解析位置 x=y 格式
            string[] posParts = positionStr.Split('=');
            if (posParts.Length == 2)
            {
                float x, y;
                if (float.TryParse(posParts[0], out x) && float.TryParse(posParts[1], out y))
                {
                    RectTransform rt = target.GetComponent<RectTransform>();
                    if (rt != null)
                    {
                        rt.anchoredPosition = new Vector2(x, y);
                        Debug.Log($"reset_pos: {targetPath} 位置已重置为 ({x}, {y})");
                    }
                    else
                    {
                        Debug.LogWarning($"reset_pos: 节点 {targetPath} 没有RectTransform组件");
                    }
                }
                else
                {
                    Debug.LogWarning($"reset_pos: 位置格式错误 {positionStr}，应为 x=y 格式");
                }
            }
            else
            {
                Debug.LogWarning($"reset_pos: 位置格式错误 {positionStr}，应为 x=y 格式");
            }
        }
    }

    #endregion

    #region 步骤编辑UI
    
    /// <summary>
    /// 刷新当前步骤的UI（在步骤内容变化但不需要重建整个UI时调用）
    /// </summary>
    private void RefreshCurrentStepUI()
    {
        // 重新构建整个步骤编辑UI
        RefreshStepEditUI();
        // 更新网格按钮状态
        UpdateStepGridButtonStates();
    }

    /// <summary>
    /// 刷新初始状态编辑UI
    /// </summary>
    private void RefreshInitEditUI()
    {
        // 检查UI元素是否存在
        if (initEditContainer == null)
        {
            Debug.LogWarning("InitEditContainer 未找到，跳过刷新初始状态UI");
            return;
        }
        
        // 清空现有内容
        initEditContainer.Clear();
        
        if (tempAreaInitRows.Count == 0)
        {
            initEmptyLabel = new Label("暂无初始状态数据");
            initEmptyLabel.style.marginTop = 20;
            initEmptyLabel.style.marginBottom = 20;
            initEmptyLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
            initEmptyLabel.style.color = new Color(0.5f, 0.5f, 0.5f);
            initEditContainer.Add(initEmptyLabel);
            return;
        }
        
        // 为每个初始状态创建编辑项
        foreach (var initRow in tempAreaInitRows)
        {
            VisualElement initItem = CreateInitEditItem(initRow);
            initEditContainer.Add(initItem);
        }
    }
    
    /// <summary>
    /// 创建初始状态编辑项
    /// </summary>
    private VisualElement CreateInitEditItem(DecorateConfigRow row)
    {
        VisualElement container = new VisualElement();
        container.style.marginBottom = 8;
        container.style.paddingTop = 8;
        container.style.paddingBottom = 8;
        container.style.paddingLeft = 8;
        container.style.paddingRight = 8;
        container.style.borderTopWidth = 1;
        container.style.borderBottomWidth = 1;
        container.style.borderLeftWidth = 1;
        container.style.borderRightWidth = 1;
        container.style.borderTopColor = new Color(0.4f, 0.4f, 0.4f);
        container.style.borderBottomColor = new Color(0.4f, 0.4f, 0.4f);
        container.style.borderLeftColor = new Color(0.4f, 0.4f, 0.4f);
        container.style.borderRightColor = new Color(0.4f, 0.4f, 0.4f);
        container.style.borderTopLeftRadius = 3;
        container.style.borderTopRightRadius = 3;
        container.style.borderBottomLeftRadius = 3;
        container.style.borderBottomRightRadius = 3;
        container.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f);
        
        // 标题行：Action路径
        Label actionLabel = new Label(row.Action);
        actionLabel.style.fontSize = 12;
        actionLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
        actionLabel.style.marginBottom = 5;
        actionLabel.style.color = new Color(0.8f, 0.9f, 1.0f);
        container.Add(actionLabel);
        
        // 第一行：状态Dropdown和Icon预览
        VisualElement row1 = new VisualElement();
        row1.style.flexDirection = FlexDirection.Row;
        row1.style.marginBottom = 5;
        row1.style.alignItems = Align.Center;
        
        Label titleLabel = new Label("状态:");
        titleLabel.style.width = 45;
        titleLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
        titleLabel.style.fontSize = 11;
        row1.Add(titleLabel);
        
        // 状态下拉框
        DropdownField titleDropdown = new DropdownField();
        titleDropdown.choices = new System.Collections.Generic.List<string> { "show", "hide" };
        titleDropdown.value = string.IsNullOrEmpty(row.Title) ? "show" : row.Title;
        titleDropdown.style.width = 100;
        titleDropdown.style.marginRight = 10;
        titleDropdown.RegisterValueChangedCallback(evt => { row.Title = evt.newValue; isInitRecorded = true; });
        row1.Add(titleDropdown);
        
        Label iconLabel = new Label("Icon:");
        iconLabel.style.width = 40;
        iconLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
        iconLabel.style.fontSize = 11;
        row1.Add(iconLabel);
        
        // Icon预览框
        VisualElement iconPreview = new VisualElement();
        iconPreview.style.width = 50;
        iconPreview.style.height = 50;
        iconPreview.style.marginRight = 5;
        iconPreview.style.borderTopWidth = 1;
        iconPreview.style.borderBottomWidth = 1;
        iconPreview.style.borderLeftWidth = 1;
        iconPreview.style.borderRightWidth = 1;
        iconPreview.style.borderTopColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderBottomColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderLeftColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderRightColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.backgroundColor = new Color(0.15f, 0.15f, 0.15f);
        LoadIconPreview(iconPreview, row.Icon, true);  // 初始状态从DecorateScene加载
        row1.Add(iconPreview);
        
        TextField iconField = new TextField();
        iconField.value = row.Icon;
        iconField.style.width = 300;
        iconField.RegisterValueChangedCallback(evt => 
        { 
            row.Icon = evt.newValue; 
            isInitRecorded = true;
            LoadIconPreview(iconPreview, evt.newValue, true);  // 初始状态从DecorateScene加载
        });
        row1.Add(iconField);
        
        container.Add(row1);
        
        // 第二行：位置Vector2
        VisualElement row2 = new VisualElement();
        row2.style.flexDirection = FlexDirection.Row;
        row2.style.marginBottom = 5;
        row2.style.alignItems = Align.Center;
        
        Label posLabel = new Label("位置:");
        posLabel.style.width = 45;
        posLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
        posLabel.style.fontSize = 11;
        row2.Add(posLabel);
        
        // 解析位置 "x#y"
        Vector2 posValue = Vector2.zero;
        if (!string.IsNullOrEmpty(row.Pos))
        {
            string[] posParts = row.Pos.Split('#');
            if (posParts.Length == 2)
            {
                float.TryParse(posParts[0], out posValue.x);
                float.TryParse(posParts[1], out posValue.y);
            }
        }
        
        Vector2Field posField = new Vector2Field();
        posField.value = posValue;
        posField.style.width = 180;
        posField.style.marginRight = 15;
        // 设置内部X和Y输入框的宽度
        posField.Q("unity-x-input").style.width = 40;
        posField.Q("unity-y-input").style.width = 40;
        posField.RegisterValueChangedCallback(evt => 
        { 
            row.Pos = $"{(int)evt.newValue.x}#{(int)evt.newValue.y}";
            isInitRecorded = true;
        });
        row2.Add(posField);
        
        Label originLabel = new Label("大小:");
        originLabel.style.width = 45;
        originLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
        originLabel.style.fontSize = 11;
        row2.Add(originLabel);
        
        // 解析大小 "width#height"
        Vector2 originValue = Vector2.zero;
        if (!string.IsNullOrEmpty(row.Origin))
        {
            string[] originParts = row.Origin.Split('#');
            if (originParts.Length == 2)
            {
                float.TryParse(originParts[0], out originValue.x);
                float.TryParse(originParts[1], out originValue.y);
            }
        }
        
        Vector2Field originField = new Vector2Field();
        originField.value = originValue;
        originField.style.width = 180;
        // 设置内部X和Y输入框的宽度
        originField.Q("unity-x-input").style.width = 40;
        originField.Q("unity-y-input").style.width = 40;
        originField.RegisterValueChangedCallback(evt => 
        { 
            row.Origin = $"{(int)evt.newValue.x}#{(int)evt.newValue.y}";
            isInitRecorded = true;
        });
        row2.Add(originField);
        
        // "设置当前"按钮
        UnityEngine.UIElements.Button setCurrentButton = new UnityEngine.UIElements.Button(() => 
        {
            if (Selection.activeGameObject == null)
            {
                EditorUtility.DisplayDialog("提示", "请先选中一个场景物体", "确定");
                return;
            }
            
            RectTransform rt = Selection.activeGameObject.GetComponent<RectTransform>();
            if (rt == null)
            {
                EditorUtility.DisplayDialog("提示", "选中的物体没有RectTransform组件", "确定");
                return;
            }
            
            // 设置位置
            Vector2 pos = rt.anchoredPosition;
            posField.value = pos;
            row.Pos = $"{(int)pos.x}#{(int)pos.y}";
            
            // 设置大小
            Vector2 size = rt.sizeDelta;
            originField.value = size;
            row.Origin = $"{(int)size.x}#{(int)size.y}";
            
            isInitRecorded = true;
        });
        setCurrentButton.text = "设置当前";
        setCurrentButton.style.width = 80;
        setCurrentButton.style.marginLeft = 10;
        row2.Add(setCurrentButton);
        
        container.Add(row2);
        
        return container;
    }

    private void RefreshStepEditUI()
    {
        // 清空现有内容
        stepEditContainer.Clear();
        
        // 添加标题
        Label titleLabel = new Label("步骤编辑");
        titleLabel.style.fontSize = 16;
        titleLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
        titleLabel.style.marginBottom = 10;
        stepEditContainer.Add(titleLabel);

        // 为每个步骤创建编辑项
        foreach (var stepRow in currentAreaStepRows.OrderBy(r => r.SortId))
        {
            VisualElement stepItem = CreateStepEditItem(stepRow);
            stepEditContainer.Add(stepItem);
        }
        
        // 更新网格按钮状态
        UpdateStepGridButtonStates();
    }

    private void LoadIconPreview(VisualElement iconPreview, string iconPath, bool isInitScene = false)
    {
        // 清空背景图
        iconPreview.style.backgroundImage = null;
        
        if (string.IsNullOrEmpty(iconPath)) return;
        
        // 从SO中加载Sprite
        Sprite sprite = LoadSpriteFromIconName(iconPath, currentAreaId, isInitScene);
        if (sprite != null)
        {
            // 使用sprite的texture作为背景图
            iconPreview.style.backgroundImage = new StyleBackground(sprite.texture);
        }
    }
    
    private VisualElement CreateStepEditItem(DecorateConfigRow row)
    {
        VisualElement container = new VisualElement();
        container.style.marginBottom = 15;
        container.style.paddingTop = 10;
        container.style.paddingBottom = 10;
        container.style.paddingLeft = 10;
        container.style.paddingRight = 10;
        container.style.borderTopWidth = 2;
        container.style.borderBottomWidth = 2;
        container.style.borderLeftWidth = 2;
        container.style.borderRightWidth = 2;
        container.style.borderTopColor = new Color(0.3f, 0.3f, 0.3f);
        container.style.borderBottomColor = new Color(0.3f, 0.3f, 0.3f);
        container.style.borderLeftColor = new Color(0.3f, 0.3f, 0.3f);
        container.style.borderRightColor = new Color(0.3f, 0.3f, 0.3f);
        container.style.borderTopLeftRadius = 5;
        container.style.borderTopRightRadius = 5;
        container.style.borderBottomLeftRadius = 5;
        container.style.borderBottomRightRadius = 5;
        container.style.backgroundColor = new Color(0.22f, 0.22f, 0.22f);

        // 标题行和基础信息
        VisualElement headerRow = new VisualElement();
        headerRow.style.flexDirection = FlexDirection.Row;
        headerRow.style.alignItems = Align.Center;
        headerRow.style.marginBottom = 10;
        
        Label stepLabel = new Label($"步骤 {row.SortId}");
        stepLabel.style.fontSize = 16;
        stepLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
        stepLabel.style.flexGrow = 1;
        headerRow.Add(stepLabel);
        
        // 复制、粘贴、合并粘贴按钮
        UIButton copyBtn = new UIButton(() => OnCopyStepConfig(row)) { text = "复制" };
        copyBtn.style.width = 60;
        copyBtn.style.height = 22;
        copyBtn.style.marginRight = 5;
        copyBtn.style.backgroundColor = new Color(0.3f, 0.5f, 0.7f);
        headerRow.Add(copyBtn);
        
        UIButton pasteBtn = new UIButton(() => OnPasteStepConfig(row)) { text = "粘贴" };
        pasteBtn.style.width = 60;
        pasteBtn.style.height = 22;
        pasteBtn.style.marginRight = 5;
        pasteBtn.style.backgroundColor = new Color(0.4f, 0.6f, 0.4f);
        headerRow.Add(pasteBtn);
        
        UIButton mergePasteBtn = new UIButton(() => OnMergePasteStepConfig(row)) { text = "合并粘贴" };
        mergePasteBtn.style.width = 80;
        mergePasteBtn.style.height = 22;
        mergePasteBtn.style.marginRight = 10;
        mergePasteBtn.style.backgroundColor = new Color(0.6f, 0.5f, 0.3f);
        headerRow.Add(mergePasteBtn);
        
        TextField titleField = new TextField("标题:");
        titleField.value = row.Title;
        titleField.style.width = 200;
        titleField.RegisterValueChangedCallback(evt => { row.Title = evt.newValue; MarkStepsModified(); });
        headerRow.Add(titleField);
        
        container.Add(headerRow);

        // Icon预览、拖入和路径行
        VisualElement iconRow = new VisualElement();
        iconRow.style.flexDirection = FlexDirection.Row;
        iconRow.style.marginBottom = 10;
        iconRow.style.alignItems = Align.Center;
        
        // Icon预览图
        VisualElement iconPreview = new VisualElement();
        iconPreview.name = "IconPreview";
        iconPreview.style.width = 80;
        iconPreview.style.height = 80;
        iconPreview.style.marginRight = 10;
        iconPreview.style.borderTopWidth = 1;
        iconPreview.style.borderBottomWidth = 1;
        iconPreview.style.borderLeftWidth = 1;
        iconPreview.style.borderRightWidth = 1;
        iconPreview.style.borderTopColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderBottomColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderLeftColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.borderRightColor = new Color(0.3f, 0.3f, 0.3f);
        iconPreview.style.backgroundColor = new Color(0.15f, 0.15f, 0.15f);
        LoadIconPreview(iconPreview, row.Icon);
        iconRow.Add(iconPreview);
        
        // 垂直容器放置ObjectField和TextField
        VisualElement iconFieldsContainer = new VisualElement();
        iconFieldsContainer.style.flexGrow = 1;
        
        // ObjectField拖入Sprite
        ObjectField iconObjectField = new ObjectField("Icon图片:") { objectType = typeof(Sprite) };
        iconObjectField.style.marginBottom = 5;
        // 尝试从SO加载现有的Sprite
        if (!string.IsNullOrEmpty(row.Icon))
        {
            Sprite sprite = LoadSpriteFromIconName(row.Icon, currentAreaId, false);
            if (sprite != null)
            {
                iconObjectField.value = sprite;
            }
        }
        iconObjectField.RegisterValueChangedCallback(evt => 
        {
            Sprite sprite = evt.newValue as Sprite;
            if (sprite != null)
            {
                // 从完整路径提取Icon路径
                string fullPath = AssetDatabase.GetAssetPath(sprite);
                row.Icon = ExtractIconPath(fullPath);
                // 更新TextField
                TextField iconPathField = iconFieldsContainer.Q<TextField>("IconPathField");
                if (iconPathField != null) iconPathField.value = row.Icon;
                // 更新预览
                iconPreview.style.backgroundImage = new StyleBackground(sprite.texture);
                MarkStepsModified();
            }
        });
        iconFieldsContainer.Add(iconObjectField);
        
        // Icon路径编辑
        TextField iconPathField = new TextField("Icon路径:");
        iconPathField.name = "IconPathField";
        iconPathField.value = row.Icon;
        iconPathField.style.fontSize = 11; // 缩小字体
        iconPathField.style.height = 20; // 减少高度
        iconPathField.Q(className: "unity-text-field__input").style.unityTextAlign = TextAnchor.MiddleLeft; // 左对齐
        iconPathField.RegisterValueChangedCallback(evt => 
        {
            row.Icon = evt.newValue;
            LoadIconPreview(iconPreview, evt.newValue);
            MarkStepsModified();
            // 尝试从SO更新ObjectField
            if (!string.IsNullOrEmpty(evt.newValue))
            {
                Sprite sprite = LoadSpriteFromIconName(evt.newValue, currentAreaId, false);
                if (sprite != null)
                {
                    iconObjectField.value = sprite;
                }
            }
        });
        iconFieldsContainer.Add(iconPathField);
        
        iconRow.Add(iconFieldsContainer);
        container.Add(iconRow);
        
        // CostCount行
        VisualElement costRow = new VisualElement();
        costRow.style.flexDirection = FlexDirection.Row;
        costRow.style.marginBottom = 10;
        
        IntegerField costField = new IntegerField("消耗资源:");
        costField.value = row.CostCount;
        costField.style.width = 200;
        costField.RegisterValueChangedCallback(evt => { row.CostCount = evt.newValue; MarkStepsModified(); });
        costRow.Add(costField);
        
        // 批次选择
        DropdownField batchDropdown = new DropdownField("批次:");
        batchDropdown.choices = new List<string> { "", "first", "second", "third", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven" };
        // 确保显示配置文件中读取的批次值
        string currentBatch = string.IsNullOrEmpty(row.Skip) ? "" : row.Skip;
        if (!batchDropdown.choices.Contains(currentBatch) && !string.IsNullOrEmpty(currentBatch))
        {
            // 如果配置中的值不在选项列表中，添加到列表
            batchDropdown.choices.Add(currentBatch);
        }
        batchDropdown.value = currentBatch;
        batchDropdown.style.width = 200;
        batchDropdown.style.marginLeft = 20;
        batchDropdown.RegisterValueChangedCallback(evt => { row.Skip = evt.newValue; MarkStepsModified(); });
        costRow.Add(batchDropdown);
        
        container.Add(costRow);
        
        // DecoratePos（Icon位置）
        VisualElement decoratePosRow = new VisualElement();
        decoratePosRow.style.flexDirection = FlexDirection.Row;
        decoratePosRow.style.marginBottom = 10;
        decoratePosRow.style.alignItems = Align.Center;
        
        Vector2Field decoratePosField = new Vector2Field("Icon位置:");
        decoratePosField.style.flexGrow = 1;
        decoratePosField.style.marginRight = 10;
        decoratePosField.style.maxWidth = 250; // 限制最大宽度
        // 设置输入框样式更紧凑
        decoratePosField.Q("unity-x-input").style.width = 60;
        decoratePosField.Q("unity-y-input").style.width = 60;
        // 解析DecoratePos "x#y"格式
        if (!string.IsNullOrEmpty(row.DecoratePos))
        {
            string[] posParts = row.DecoratePos.Split('#');
            if (posParts.Length == 2)
            {
                float x, y;
                if (float.TryParse(posParts[0], out x) && float.TryParse(posParts[1], out y))
                {
                    decoratePosField.value = new Vector2(x, y);
                }
            }
        }
        decoratePosField.RegisterValueChangedCallback(evt => 
        {
            row.DecoratePos = $"{(int)evt.newValue.x}#{(int)evt.newValue.y}";
            MarkStepsModified();
        });
        decoratePosRow.Add(decoratePosField);
        
        // 自动设置Icon位置按钮
        UIButton autoSetPosBtn = new UIButton(() => AutoSetIconPosition(row, decoratePosField)) { text = "自动获取位置" };
        autoSetPosBtn.style.width = 100;
        autoSetPosBtn.style.marginRight = 5;
        decoratePosRow.Add(autoSetPosBtn);
        
        // 设置当前位置按钮（从Item_1获取）
        UIButton setCurrentPosBtn = new UIButton(() => SetIconPositionFromItem1(row, decoratePosField)) { text = "设置当前位置" };
        setCurrentPosBtn.style.width = 100;
        decoratePosRow.Add(setCurrentPosBtn);
        
        container.Add(decoratePosRow);

        // Build和Shine行
        VisualElement effectRow = new VisualElement();
        effectRow.style.flexDirection = FlexDirection.Row;
        effectRow.style.marginBottom = 10;
        
        DropdownField buildDropdown = new DropdownField("建造效果:");
        buildDropdown.choices = new List<string> { "", "build", "clear", "change_bg" };
        buildDropdown.value = string.IsNullOrEmpty(row.Build) ? "" : row.Build;
        buildDropdown.style.width = 200;
        buildDropdown.style.marginRight = 10;
        buildDropdown.RegisterValueChangedCallback(evt => { row.Build = evt.newValue; MarkStepsModified(); });
        effectRow.Add(buildDropdown);
        
        UIToggle shineToggle = new UIToggle("闪光效果");
        shineToggle.value = row.Shine == "shine";
        shineToggle.RegisterValueChangedCallback(evt => { row.Shine = evt.newValue ? "shine" : ""; MarkStepsModified(); });
        effectRow.Add(shineToggle);
        
        container.Add(effectRow);

        // 显示原始Action配置（只读）
        TextField actionDisplay = new TextField("当前配置:");
        actionDisplay.name = "ActionDisplay";
        actionDisplay.value = row.Action;
        actionDisplay.multiline = true;
        actionDisplay.style.height = 40;
        actionDisplay.style.marginTop = 10;
        actionDisplay.style.marginBottom = 10;
        actionDisplay.SetEnabled(false); // 只读
        actionDisplay.style.opacity = 0.7f;
        container.Add(actionDisplay);

        // 操作组容器
        VisualElement actionsContainer = new VisualElement();
        actionsContainer.name = "ActionsContainer";
        actionsContainer.style.marginTop = 10;
        container.Add(actionsContainer);
        
        // 解析现有的Action字符串
        ParseAndCreateActionGroups(actionsContainer, row);
        
        // 添加新操作组按钮
        VisualElement addGroupRow = new VisualElement();
        addGroupRow.style.flexDirection = FlexDirection.Row;
        addGroupRow.style.marginTop = 10;
        
        UIButton addClearBtn = new UIButton(() => AddActionGroup(actionsContainer, row, "clear")) { text = "+ Clear" };
        addClearBtn.style.marginRight = 5;
        addGroupRow.Add(addClearBtn);
        
        UIButton addAddBtn = new UIButton(() => AddActionGroup(actionsContainer, row, "add")) { text = "+ Add" };
        addAddBtn.style.marginRight = 5;
        addGroupRow.Add(addAddBtn);
        
        UIButton addReplaceBtn = new UIButton(() => AddActionGroup(actionsContainer, row, "replace")) { text = "+ Replace" };
        addReplaceBtn.style.marginRight = 5;
        addGroupRow.Add(addReplaceBtn);
        
        UIButton addReplaceImageBtn = new UIButton(() => AddActionGroup(actionsContainer, row, "replace_image")) { text = "+ ReplaceImage" };
        addReplaceImageBtn.style.marginRight = 5;
        addGroupRow.Add(addReplaceImageBtn);
        
        UIButton addResetPosBtn = new UIButton(() => AddActionGroup(actionsContainer, row, "reset_pos")) { text = "+ ResetPos" };
        addGroupRow.Add(addResetPosBtn);
        
        container.Add(addGroupRow);

        return container;
    }

    private void ParseAndCreateActionGroups(VisualElement container, DecorateConfigRow row)
    {
        if (string.IsNullOrEmpty(row.Action)) return;
        
        string[] actions = row.Action.Split('@');
        foreach (string action in actions)
        {
            if (string.IsNullOrEmpty(action)) continue;
            
            string[] parts = action.Split('#');
            if (parts.Length < 2) continue;
            
            string actionType = parts[0];
            string paths = parts[1];
            
            // 跳过所有spine相关操作，用户不可见不可编辑
            if (actionType.Contains("spine")) continue;
            
            VisualElement group = CreateActionGroup(actionType, row);
            container.Add(group);
            
            // 填充现有数据
            if (actionType == "replace_image")
            {
                // replace_image: 第一个是节点路径,第二个是图片路径
                string[] pathParts = paths.Split(',');
                if (pathParts.Length >= 1)
                {
                    Transform target = FindTransformByPath(pathParts[0]);
                    ObjectField objField = group.Q<ObjectField>("ObjectField_0");
                    if (objField != null) objField.value = target;
                }
                if (pathParts.Length >= 2)
                {
                    TextField imgField = group.Q<TextField>("ImagePath");
                    if (imgField != null) imgField.value = pathParts[1];
                }
            }
            else if (actionType == "reset_pos")
            {
                // reset_pos: 第一个是节点路径,第二个是位置(x=y格式)
                string[] pathParts = paths.Split(',');
                if (pathParts.Length >= 1)
                {
                    Transform target = FindTransformByPath(pathParts[0]);
                    ObjectField objField = group.Q<ObjectField>("ObjectField_0");
                    if (objField != null) objField.value = target;
                }
                if (pathParts.Length >= 2)
                {
                    Vector2Field posField = group.Q<Vector2Field>("PositionField");
                    if (posField != null)
                    {
                        // 解析x=y格式
                        string[] posParts = pathParts[1].Split('=');
                        if (posParts.Length == 2)
                        {
                            float x, y;
                            if (float.TryParse(posParts[0], out x) && float.TryParse(posParts[1], out y))
                            {
                                posField.value = new Vector2(x, y);
                            }
                        }
                    }
                }
            }
            else
            {
                // clear/add/replace
                string[] pathArray = paths.Split(',');
                VisualElement fieldsContainer = group.Q<VisualElement>("FieldsContainer");
                
                for (int i = 0; i < pathArray.Length; i++)
                {
                    Transform target = FindTransformByPath(pathArray[i]);
                    
                    if (i < fieldsContainer.childCount)
                    {
                        ObjectField existingField = fieldsContainer.ElementAt(i) as ObjectField;
                        if (existingField != null) existingField.value = target;
                    }
                    else if (actionType != "replace") // replace固定2个
                    {
                        AddObjectFieldToGroup(group, target);
                    }
                }
            }
        }
    }
    
    private Transform FindTransformByPath(string path)
    {
        if (bgTransform == null) return null;
        
        // 去掉bg/前缀
        string actualPath = path.StartsWith("bg/") ? path.Substring(3) : path;
        if (actualPath == "bg") return bgTransform;
        
        return bgTransform.Find(actualPath);
    }

    private VisualElement CreateActionGroup(string actionType, DecorateConfigRow row)
    {
        VisualElement group = new VisualElement();
        group.name = $"ActionGroup_{actionType}";
        group.style.marginTop = 5;
        group.style.paddingLeft = 10;
        group.style.paddingRight = 10;
        group.style.paddingTop = 5;
        group.style.paddingBottom = 5;
        group.style.backgroundColor = new Color(0.18f, 0.18f, 0.18f);
        group.style.borderTopLeftRadius = 3;
        group.style.borderTopRightRadius = 3;
        group.style.borderBottomLeftRadius = 3;
        group.style.borderBottomRightRadius = 3;
        
        // 标题行
        VisualElement headerRow = new VisualElement();
        headerRow.style.flexDirection = FlexDirection.Row;
        headerRow.style.alignItems = Align.Center;
        headerRow.style.marginBottom = 5;
        
        Label typeLabel = new Label(actionType.ToUpper());
        typeLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
        typeLabel.style.color = new Color(0.4f, 0.8f, 1f);
        typeLabel.style.flexGrow = 1;
        headerRow.Add(typeLabel);
        
        UIButton removeBtn = new UIButton(() => RemoveActionGroup(group, row)) { text = "X" };
        removeBtn.style.width = 25;
        removeBtn.style.height = 20;
        removeBtn.style.backgroundColor = new Color(0.8f, 0.3f, 0.3f);
        headerRow.Add(removeBtn);
        
        group.Add(headerRow);
        
        if (actionType == "replace_image")
        {
            // replace_image特殊处理: 1个ObjectField + 1个TextField
            ObjectField objField = new ObjectField("目标节点:") { objectType = typeof(Transform) };
            objField.name = "ObjectField_0";
            objField.RegisterValueChangedCallback(evt => UpdateRowActionString(row));
            group.Add(objField);
            
            TextField imgPath = new TextField("图片路径:");
            imgPath.name = "ImagePath";
            imgPath.RegisterValueChangedCallback(evt => UpdateRowActionString(row));
            group.Add(imgPath);
        }
        else if (actionType == "reset_pos")
        {
            // reset_pos特殊处理: 1个ObjectField + 1个Vector2Field(位置) + 1个按钮
            ObjectField objField = new ObjectField("目标节点:") { objectType = typeof(Transform) };
            objField.name = "ObjectField_0";
            objField.RegisterValueChangedCallback(evt => UpdateRowActionString(row));
            group.Add(objField);
            
            // 位置输入和按钮放在一行
            VisualElement posRow = new VisualElement();
            posRow.style.flexDirection = FlexDirection.Row;
            posRow.style.alignItems = Align.Center;
            
            Vector2Field posField = new Vector2Field("位置:");
            posField.name = "PositionField";
            posField.style.flexGrow = 1;
            posField.style.maxWidth = 250; // 限制最大宽度
            // 设置输入框宽度
            posField.Q("unity-x-input").style.width = 60;
            posField.Q("unity-y-input").style.width = 60;
            posField.RegisterValueChangedCallback(evt => UpdateRowActionString(row));
            posRow.Add(posField);
            
            UIButton getFromSelectionBtn = new UIButton(() => SetPositionFromSelection(posField)) { text = "从选中物体获取" };
            getFromSelectionBtn.style.width = 120;
            getFromSelectionBtn.style.marginLeft = 5;
            posRow.Add(getFromSelectionBtn);
            
            group.Add(posRow);
        }
        else if (actionType == "replace")
        {
            // replace固定2个ObjectField
            VisualElement fieldsContainer = new VisualElement();
            fieldsContainer.name = "FieldsContainer";
            
            for (int i = 0; i < 2; i++)
            {
                ObjectField objField = new ObjectField(i == 0 ? "旧对象:" : "新对象:") { objectType = typeof(Transform) };
                objField.RegisterValueChangedCallback(evt => UpdateRowActionString(row));
                fieldsContainer.Add(objField);
            }
            
            group.Add(fieldsContainer);
        }
        else // clear 或 add
        {
            VisualElement fieldsContainer = new VisualElement();
            fieldsContainer.name = "FieldsContainer";
            group.Add(fieldsContainer);
            
            // 默认添加1个ObjectField
            AddObjectFieldToGroup(group, null);
            
            // +/- 按钮
            VisualElement btnRow = new VisualElement();
            btnRow.style.flexDirection = FlexDirection.Row;
            btnRow.style.marginTop = 5;
            
            UIButton addBtn = new UIButton(() => AddObjectFieldToGroup(group, null)) { text = "+" };
            addBtn.style.width = 30;
            addBtn.style.marginRight = 5;
            btnRow.Add(addBtn);
            
            UIButton removeBtn2 = new UIButton(() => RemoveObjectFieldFromGroup(group, row)) { text = "-" };
            removeBtn2.style.width = 30;
            btnRow.Add(removeBtn2);
            
            group.Add(btnRow);
        }
        
        return group;
    }
    
    private void AddActionGroup(VisualElement container, DecorateConfigRow row, string actionType)
    {
        VisualElement group = CreateActionGroup(actionType, row);
        container.Add(group);
        UpdateRowActionString(row);
    }
    
    private void RemoveActionGroup(VisualElement group, DecorateConfigRow row)
    {
        group.parent.Remove(group);
        UpdateRowActionString(row);
    }
    
    private void AddObjectFieldToGroup(VisualElement group, Transform initialValue)
    {
        VisualElement fieldsContainer = group.Q<VisualElement>("FieldsContainer");
        if (fieldsContainer == null) return;
        
        ObjectField objField = new ObjectField { objectType = typeof(Transform), value = initialValue };
        objField.RegisterValueChangedCallback(evt => 
        {
            DecorateConfigRow row = FindRowFromGroup(group);
            if (row != null) UpdateRowActionString(row);
        });
        fieldsContainer.Add(objField);
    }
    
    private void RemoveObjectFieldFromGroup(VisualElement group, DecorateConfigRow row)
    {
        VisualElement fieldsContainer = group.Q<VisualElement>("FieldsContainer");
        if (fieldsContainer == null || fieldsContainer.childCount <= 1) return;
        
        fieldsContainer.RemoveAt(fieldsContainer.childCount - 1);
        UpdateRowActionString(row);
    }
    
    private DecorateConfigRow FindRowFromGroup(VisualElement group)
    {
        // 从group向上查找到步骤容器,获取步骤编号
        VisualElement current = group;
        while (current != null && current.parent != stepEditContainer)
        {
            current = current.parent;
        }
        
        if (current == null) return null;
        
        int index = stepEditContainer.IndexOf(current) - 1; // -1因为第一个是标题Label
        if (index >= 0 && index < currentAreaStepRows.Count)
        {
            return currentAreaStepRows[index];
        }
        
        return null;
    }
    
    private void UpdateRowActionString(DecorateConfigRow row)
    {
        // 从UI重新构建Action字符串
        VisualElement stepContainer = null;
        foreach (var child in stepEditContainer.Children())
        {
            if (child.childCount > 0)
            {
                var titleLabel = child.Q<Label>();
                if (titleLabel != null && titleLabel.text == $"步骤 {row.SortId}")
                {
                    stepContainer = child;
                    break;
                }
            }
        }
        
        if (stepContainer == null) return;
        
        VisualElement actionsContainer = stepContainer.Q<VisualElement>("ActionsContainer");
        if (actionsContainer == null) return;
        
        // 保存原有的spine操作（放在最前面）
        List<string> spineActions = new List<string>();
        if (!string.IsNullOrEmpty(row.Action))
        {
            string[] oldActions = row.Action.Split('@');
            foreach (string oldAction in oldActions)
            {
                if (oldAction.Contains("spine"))
                {
                    spineActions.Add(oldAction);
                }
            }
        }
        
        List<string> actionStrings = new List<string>();
        
        // 先添加spine操作
        actionStrings.AddRange(spineActions);
        
        foreach (var groupChild in actionsContainer.Children())
        {
            if (!groupChild.name.StartsWith("ActionGroup_")) continue;
            
            string actionType = groupChild.name.Replace("ActionGroup_", "");
            
            if (actionType == "replace_image")
            {
                ObjectField objField = groupChild.Q<ObjectField>("ObjectField_0");
                TextField imgField = groupChild.Q<TextField>("ImagePath");
                
                Transform target = objField?.value as Transform;
                string imgPath = imgField?.value;
                
                if (target != null && !string.IsNullOrEmpty(imgPath))
                {
                    string targetPath = GetTransformPath(target);
                    actionStrings.Add($"replace_image#{targetPath},{imgPath}");
                }
            }
            else if (actionType == "reset_pos")
            {
                ObjectField objField = groupChild.Q<ObjectField>("ObjectField_0");
                Vector2Field posField = groupChild.Q<Vector2Field>("PositionField");
                
                Transform target = objField?.value as Transform;
                
                if (target != null && posField != null)
                {
                    string targetPath = GetTransformPath(target);
                    Vector2 pos = posField.value;
                    // 转换为x=y格式
                    string positionStr = $"{(int)pos.x}={(int)pos.y}";
                    actionStrings.Add($"reset_pos#{targetPath},{positionStr}");
                }
            }
            else
            {
                VisualElement fieldsContainer = groupChild.Q<VisualElement>("FieldsContainer");
                if (fieldsContainer == null) continue;
                
                List<string> paths = new List<string>();
                foreach (var fieldChild in fieldsContainer.Children())
                {
                    ObjectField objField = fieldChild as ObjectField;
                    if (objField == null) continue;
                    
                    Transform target = objField.value as Transform;
                    if (target != null)
                    {
                        paths.Add(GetTransformPath(target));
                    }
                }
                
                if (paths.Count > 0)
                {
                    actionStrings.Add($"{actionType}#{string.Join(",", paths)}");
                }
            }
        }
        
        row.Action = string.Join("@", actionStrings);
        
        // 更新只读显示
        TextField actionDisplay = stepContainer.Q<TextField>("ActionDisplay");
        if (actionDisplay != null)
        {
            actionDisplay.value = row.Action;
        }
        
        // 标记步骤已修改
        MarkStepsModified();
    }
    
    private string GetTransformPath(Transform target)
    {
        if (target == bgTransform) return "bg";
        
        // 构建相对于bgTransform的路径
        List<string> pathParts = new List<string>();
        Transform current = target;
        
        while (current != null && current != bgTransform)
        {
            pathParts.Insert(0, current.name);
            current = current.parent;
        }
        
        if (current == bgTransform)
        {
            return "bg/" + string.Join("/", pathParts);
        }
        
        return target.name;
    }
    
    /// <summary>
    /// 自动从Action的第一个操作物体获取位置，设置到DecoratePos
    /// </summary>
    private void AutoSetIconPosition(DecorateConfigRow row, Vector2Field decoratePosField)
    {
        if (string.IsNullOrEmpty(row.Action))
        {
            EditorUtility.DisplayDialog("错误", "当前步骤没有Action配置！", "确定");
            return;
        }
        
        // 解析Action字符串，获取第一个操作
        string[] actions = row.Action.Split('@');
        if (actions.Length == 0)
        {
            EditorUtility.DisplayDialog("错误", "Action格式错误！", "确定");
            return;
        }
        
        string firstAction = actions[0];
        string[] parts = firstAction.Split('#');
        if (parts.Length < 2)
        {
            EditorUtility.DisplayDialog("错误", "Action格式错误！", "确定");
            return;
        }
        
        string actionType = parts[0];
        string paths = parts[1];
        
        // 获取第一个路径
        string[] pathParts = paths.Split(',');
        if (pathParts.Length == 0)
        {
            EditorUtility.DisplayDialog("错误", "Action中没有找到路径！", "确定");
            return;
        }
        
        string firstPath = pathParts[0];
        Transform target = FindTransformByPath(firstPath);
        
        if (target == null)
        {
            EditorUtility.DisplayDialog("错误", $"未找到路径对应的物体：{firstPath}\n请确保场景中存在该物体", "确定");
            return;
        }
        
        RectTransform rt = target.GetComponent<RectTransform>();
        if (rt == null)
        {
            EditorUtility.DisplayDialog("错误", $"物体 {firstPath} 不是RectTransform！", "确定");
            return;
        }
        
        // 获取位置并设置
        Vector2 pos = rt.anchoredPosition;
        decoratePosField.value = pos;
        row.DecoratePos = $"{(int)pos.x}#{(int)pos.y}";
        
        Debug.Log($"自动设置Icon位置为：({(int)pos.x}, {(int)pos.y})，来自物体：{firstPath}");
        EditorUtility.DisplayDialog("成功", $"已自动设置Icon位置为：({(int)pos.x}, {(int)pos.y})\n来自物体：{target.name}", "确定");
    }
    
    /// <summary>
    /// 更新所有步骤配置中的Action路径
    /// </summary>
    private int UpdateActionPaths(Dictionary<string, string> pathMapping)
    {
        int updatedSteps = 0;
        
        foreach (var row in currentAreaStepRows)
        {
            if (string.IsNullOrEmpty(row.Action)) continue;
            
            string originalAction = row.Action;
            string updatedAction = row.Action;
            
            // 使用临时占位符避免交叉替换问题
            Dictionary<string, string> tempPlaceholders = new Dictionary<string, string>();
            int placeholderIndex = 0;
            
            // 第一步：用临时占位符替换所有旧路径
            foreach (var kvp in pathMapping)
            {
                string oldPath = kvp.Key;
                string placeholder = $"__TEMP_PATH_{placeholderIndex}__";
                tempPlaceholders[placeholder] = kvp.Value;
                placeholderIndex++;
                
                updatedAction = System.Text.RegularExpressions.Regex.Replace(
                    updatedAction,
                    $@"\b{System.Text.RegularExpressions.Regex.Escape(oldPath)}\b",
                    placeholder
                );
            }
            
            // 第二步：用新路径替换所有临时占位符
            foreach (var kvp in tempPlaceholders)
            {
                updatedAction = updatedAction.Replace(kvp.Key, kvp.Value);
            }
            
            if (updatedAction != originalAction)
            {
                row.Action = updatedAction;
                updatedSteps++;
                Debug.Log($"步骤{row.SortId}路径已更新：\n旧：{originalAction}\n新：{updatedAction}");
            }
        }
        
        return updatedSteps;
    }
    
    /// <summary>
    /// 名称排序后智能更新初始化配置
    /// 关键原则：只更新路径，保留原有的所有配置（Title/Icon/Pos/Origin等）
    /// </summary>
    private void ScanAndUpdateInitAfterRename()
    {
        if (bgTransform == null) return;
        
        // 保存旧的初始化配置
        List<DecorateConfigRow> oldInitRows = isInitRecorded ? tempAreaInitRows : currentAreaInitRows;
        
        // 创建sprite路径到旧配置的映射（用于匹配同一个物体）
        Dictionary<string, DecorateConfigRow> spriteToOldConfig = new Dictionary<string, DecorateConfigRow>();
        
        foreach (var oldRow in oldInitRows)
        {
            if (!string.IsNullOrEmpty(oldRow.Icon))
            {
                spriteToOldConfig[oldRow.Icon] = oldRow;
            }
        }
        
        // 清空并重新扫描（获取新路径）
        tempAreaInitRows.Clear();
        ScanChildren(bgTransform, tempAreaInitRows);
        
        // 智能合并：根据sprite匹配，只更新路径，保留所有其他配置
        foreach (var newRow in tempAreaInitRows)
        {
            // ⚠️ 特殊处理：init_img#bg 必须始终为 show
            if (newRow.Action == "init_img#bg")
            {
                newRow.Title = "show";
                // 如果有旧配置，保留其他字段
                if (!string.IsNullOrEmpty(newRow.Icon) && spriteToOldConfig.TryGetValue(newRow.Icon, out DecorateConfigRow oldBgRow))
                {
                    newRow.CostCount = oldBgRow.CostCount;
                    newRow.Pos = oldBgRow.Pos;
                    newRow.Origin = oldBgRow.Origin;
                    newRow.Spine = oldBgRow.Spine;
                    newRow.Button = oldBgRow.Button;
                    newRow.Build = oldBgRow.Build;
                    newRow.Shine = oldBgRow.Shine;
                    newRow.DecoratePos = oldBgRow.DecoratePos;
                    newRow.Skip = oldBgRow.Skip;
                    newRow.MapPethomeId = oldBgRow.MapPethomeId;
                    newRow.PetExp = oldBgRow.PetExp;
                }
                continue;
            }
            
            if (string.IsNullOrEmpty(newRow.Icon)) continue;
            
            // 根据sprite图片路径查找旧配置
            if (spriteToOldConfig.TryGetValue(newRow.Icon, out DecorateConfigRow oldRow))
            {
                // 找到匹配：保留所有旧配置，只更新Action路径
                newRow.Title = oldRow.Title;              // 保留show/hide
                newRow.CostCount = oldRow.CostCount;      // 保留CostCount
                newRow.Pos = oldRow.Pos;                  // ⚠️ 保留初始位置（关键修复）
                newRow.Origin = oldRow.Origin;            // ⚠️ 保留初始大小（关键修复）
                newRow.Spine = oldRow.Spine;              // 保留Spine配置
                newRow.Button = oldRow.Button;            // 保留Button配置
                newRow.Build = oldRow.Build;              // 保留Build配置
                newRow.Shine = oldRow.Shine;              // 保留Shine配置
                newRow.DecoratePos = oldRow.DecoratePos;  // 保留DecoratePos
                newRow.Skip = oldRow.Skip;                // 保留Skip
                newRow.MapPethomeId = oldRow.MapPethomeId;// 保留MapPethomeId
                newRow.PetExp = oldRow.PetExp;            // 保留PetExp
                // Icon已经是相同的，不需要修改
                // Action路径是新的（已经在ScanChildren中更新）
            }
            // 如果找不到匹配，说明是新物体，保持扫描的默认值（已经是hide + 0#0）
        }
        
        // 标记已记录初始化
        isInitRecorded = true;
        UpdateStatusLabel();
        
        Debug.Log($"✅ 名称排序后智能更新初始化配置：扫描到{tempAreaInitRows.Count}个物体，匹配了{spriteToOldConfig.Count}个旧配置（保持位置不变）");
    }
    
    /// <summary>
    /// 保留旧配置中的特殊字段（已废弃，逻辑已整合到ScanAndUpdateInitAfterRename）
    /// </summary>
    private void PreserveSpecialFields(DecorateConfigRow newRow, DecorateConfigRow oldRow)
    {
        // 此方法已废弃，逻辑已整合到ScanAndUpdateInitAfterRename中
    }
    
    /// <summary>
    /// 从选中的物体获取RectTransform的位置并设置到Vector2Field
    /// </summary>
    private void SetPositionFromSelection(Vector2Field targetField)
    {
        GameObject selectedObj = UnityEditor.Selection.activeGameObject;
        
        if (selectedObj == null)
        {
            EditorUtility.DisplayDialog("错误", "请先在Hierarchy中选择一个物体！", "确定");
            return;
        }
        
        RectTransform rt = selectedObj.GetComponent<RectTransform>();
        if (rt == null)
        {
            EditorUtility.DisplayDialog("错误", "选中的物体没有RectTransform组件！", "确定");
            return;
        }
        
        Vector2 pos = rt.anchoredPosition;
        targetField.value = pos;
        
        Debug.Log($"✅ 已从选中物体 {selectedObj.name} 获取位置: ({pos.x}, {pos.y})");
    }
    
    /// <summary>
    /// 从Item_1获取位置并设置到Icon位置
    /// </summary>
    private void SetIconPositionFromItem1(DecorateConfigRow row, Vector2Field decoratePosField)
    {
        if (decoratePanelTransform == null)
        {
            AutoFindDecoratePanel();
            if (decoratePanelTransform == null)
            {
                EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel！", "确定");
                return;
            }
        }
        
        // 查找ImageBg/grid/Item_1
        Transform imageBg = decoratePanelTransform.Find("ImageBg");
        if (imageBg == null)
        {
            EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel/ImageBg！", "确定");
            return;
        }
        
        Transform grid = imageBg.Find("grid");
        if (grid == null)
        {
            EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel/ImageBg/grid！", "确定");
            return;
        }
        
        Transform item1 = grid.Find("Item_1");
        if (item1 == null)
        {
            EditorUtility.DisplayDialog("错误", "未找到AreaDecoratePanel/ImageBg/grid/Item_1！", "确定");
            return;
        }
        
        RectTransform rt = item1.GetComponent<RectTransform>();
        if (rt == null)
        {
            EditorUtility.DisplayDialog("错误", "Item_1没有RectTransform组件！", "确定");
            return;
        }
        
        Vector2 pos = rt.anchoredPosition;
        decoratePosField.value = pos;
        row.DecoratePos = $"{(int)pos.x}#{(int)pos.y}";
        MarkStepsModified();
        
        Debug.Log($"✅ 已从Item_1获取位置并设置到步骤{row.SortId}: ({pos.x}, {pos.y})");
    }
    
    /// <summary>
    /// 复制当前步骤的配置
    /// </summary>
    private void OnCopyStepConfig(DecorateConfigRow row)
    {
        if (row == null) return;
        
        // 复制Action字符串到剪贴板
        clipboardAction = row.Action ?? "";
        
        Debug.Log($"✅ 已复制步骤{row.SortId}的配置: {clipboardAction}");
        EditorUtility.DisplayDialog("完成", $"已复制步骤{row.SortId}的配置\n\n配置内容：\n{(string.IsNullOrEmpty(clipboardAction) ? "(空)" : clipboardAction)}", "确定");
    }
    
    /// <summary>
    /// 粘贴配置到当前步骤（覆盖）
    /// </summary>
    private void OnPasteStepConfig(DecorateConfigRow row)
    {
        if (row == null) return;
        
        if (string.IsNullOrEmpty(clipboardAction))
        {
            EditorUtility.DisplayDialog("提示", "剪贴板为空，请先复制一个步骤的配置！", "确定");
            return;
        }
        
        if (!EditorUtility.DisplayDialog("确认", 
            $"确定要覆盖步骤{row.SortId}的配置吗？\n\n将要粘贴的内容：\n{clipboardAction}\n\n当前配置将被替换！", 
            "确定", "取消"))
        {
            return;
        }
        
        // 直接覆盖
        row.Action = clipboardAction;
        
        MarkStepsModified();
        RefreshStepEditUI();
        
        Debug.Log($"✅ 已粘贴配置到步骤{row.SortId}: {clipboardAction}");
        EditorUtility.DisplayDialog("完成", $"已成功粘贴配置到步骤{row.SortId}", "确定");
    }
    
    /// <summary>
    /// 合并粘贴配置到当前步骤（用@拼接）
    /// </summary>
    private void OnMergePasteStepConfig(DecorateConfigRow row)
    {
        if (row == null) return;
        
        if (string.IsNullOrEmpty(clipboardAction))
        {
            EditorUtility.DisplayDialog("提示", "剪贴板为空，请先复制一个步骤的配置！", "确定");
            return;
        }
        
        string originalAction = row.Action ?? "";
        string mergedAction;
        
        if (string.IsNullOrEmpty(originalAction))
        {
            // 如果原配置为空，直接使用复制的配置
            mergedAction = clipboardAction;
        }
        else
        {
            // 用@拼接
            mergedAction = originalAction + "@" + clipboardAction;
        }
        
        if (!EditorUtility.DisplayDialog("确认", 
            $"确定要合并粘贴到步骤{row.SortId}吗？\n\n当前配置：\n{(string.IsNullOrEmpty(originalAction) ? "(空)" : originalAction)}\n\n要合并的配置：\n{clipboardAction}\n\n合并后的配置：\n{mergedAction}", 
            "确定", "取消"))
        {
            return;
        }
        
        // 合并配置
        row.Action = mergedAction;
        
        MarkStepsModified();
        RefreshStepEditUI();
        
        Debug.Log($"✅ 已合并粘贴配置到步骤{row.SortId}: {mergedAction}");
        EditorUtility.DisplayDialog("完成", $"已成功合并粘贴配置到步骤{row.SortId}", "确定");
    }
    
    /// <summary>
    /// 批量设置所有步骤的Icon位置
    /// </summary>
    private void OnBatchSetIconPosClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        if (!EditorUtility.DisplayDialog("确认", 
            $"确定要批量设置AreaId={currentAreaId}的所有步骤Icon位置吗？\n\n规则：\n• 有Action的步骤：从Action第一个操作的物体获取位置\n• 无Action的步骤：设置为0,0", 
            "确定", "取消"))
        {
            return;
        }
        
        int successCount = 0;
        int zeroCount = 0;
        int failedCount = 0;
        
        foreach (var row in currentAreaStepRows)
        {
            if (string.IsNullOrEmpty(row.Action))
            {
                // 无Action：设置为0,0
                row.DecoratePos = "0#0";
                zeroCount++;
            }
            else
            {
                // 有Action：从Action第一个操作的物体获取位置
                bool success = AutoSetIconPositionForRow(row);
                if (success)
                {
                    successCount++;
                }
                else
                {
                    // 获取失败，设置为0,0
                    row.DecoratePos = "0#0";
                    failedCount++;
                }
            }
        }
        
        MarkStepsModified();
        RefreshStepEditUI();
        
        string message = $"批量设置完成！\n\n从Action物体获取位置：{successCount}个\n设置为0,0：{zeroCount}个";
        if (failedCount > 0)
        {
            message += $"\n获取失败（已设为0,0）：{failedCount}个";
        }
        message += "\n\n请检查步骤配置，确认后点击\"保存配置\"。";
        
        EditorUtility.DisplayDialog("完成", message, "确定");
    }
    
    /// <summary>
    /// 为指定行自动设置Icon位置（内部方法，不弹提示框）
    /// </summary>
    private bool AutoSetIconPositionForRow(DecorateConfigRow row)
    {
        if (string.IsNullOrEmpty(row.Action))
        {
            return false;
        }
        
        // 解析Action字符串，获取第一个操作
        string[] actions = row.Action.Split('@');
        if (actions.Length == 0)
        {
            return false;
        }
        
        string firstAction = actions[0];
        string[] parts = firstAction.Split('#');
        if (parts.Length < 2)
        {
            return false;
        }
        
        string actionType = parts[0];
        string paths = parts[1];
        
        // 获取第一个路径
        string[] pathParts = paths.Split(',');
        if (pathParts.Length == 0)
        {
            return false;
        }
        
        string firstPath = pathParts[0];
        Transform target = FindTransformByPath(firstPath);
        
        if (target == null)
        {
            Debug.LogWarning($"批量设置Icon位置：未找到路径对应的物体：{firstPath}");
            return false;
        }
        
        RectTransform rt = target.GetComponent<RectTransform>();
        if (rt == null)
        {
            Debug.LogWarning($"批量设置Icon位置：物体 {firstPath} 不是RectTransform");
            return false;
        }
        
        // 获取位置并设置
        Vector2 pos = rt.anchoredPosition;
        row.DecoratePos = $"{(int)pos.x}#{(int)pos.y}";
        
        return true;
    }
    
    /// <summary>
    /// 自动设置建造效果（默认build，只有纯clear才是clear）
    /// </summary>
    private void OnAutoSetBuildClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        if (!EditorUtility.DisplayDialog("确认", "确定要自动设置所有步骤的建造效果吗？\n\n规则：\n• 只有纯clear的步骤设为clear\n• 其他步骤设为build", "确定", "取消"))
        {
            return;
        }
        
        int changedCount = 0;
        int clearCount = 0;
        int buildCount = 0;
        
        foreach (var row in currentAreaStepRows)
        {
            if (string.IsNullOrEmpty(row.Action))
            {
                row.Build = "";
                continue;
            }
            
            // 解析Action判断类型
            bool hasAdd = row.Action.Contains("add#");
            bool hasReplace = row.Action.Contains("replace#") || row.Action.Contains("replace_image#");
            bool hasClear = row.Action.Contains("clear#");
            
            string oldBuild = row.Build;
            
            // 只有纯clear才是clear，其他都是build
            if (hasClear && !hasAdd && !hasReplace)
            {
                row.Build = "clear";
                clearCount++;
            }
            else if (hasAdd || hasReplace || hasClear)
            {
                row.Build = "build";
                buildCount++;
            }
            else
            {
                row.Build = "";
            }
            
            if (row.Build != oldBuild)
            {
                changedCount++;
            }
        }
        
        MarkStepsModified();
        RefreshStepEditUI();
        
        EditorUtility.DisplayDialog("完成", 
            $"已自动设置{changedCount}个步骤的建造效果！\n\nbuild: {buildCount}个\nclear: {clearCount}个\n\n请检查步骤配置，确认后点击\"保存配置\"。", 
            "确定");
    }
    
    /// <summary>
    /// 全部启用闪光效果
    /// </summary>
    private void OnAutoSetShineClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        if (!EditorUtility.DisplayDialog("确认", "确定要为所有步骤启用闪光效果吗？", "确定", "取消"))
        {
            return;
        }
        
        int changedCount = 0;
        
        foreach (var row in currentAreaStepRows)
        {
            if (row.Shine != "shine")
            {
                row.Shine = "shine";
                changedCount++;
            }
        }
        
        MarkStepsModified();
        RefreshStepEditUI();
        
        EditorUtility.DisplayDialog("完成", 
            $"已为{changedCount}个步骤启用闪光效果！\n\n请检查步骤配置，确认后点击\"保存配置\"。", 
            "确定");
    }
    
    /// <summary>
    /// 批量设置资源消耗（5组）
    /// </summary>
    private void OnBatchSetCostClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        DecorateConfigBatchCostWindow.ShowWindow((costs) =>
        {
            for (int i = 0; i < currentAreaStepRows.Count && i < 25; i++)
            {
                int groupIndex = i / 5; // 0-4组
                if (groupIndex < costs.Length)
                {
                    currentAreaStepRows[i].CostCount = costs[groupIndex];
                }
            }
            
            MarkStepsModified();
            RefreshStepEditUI();
            
            EditorUtility.DisplayDialog("完成", 
                $"已设置资源消耗！\n\n第1-5步: {costs[0]}\n第6-10步: {costs[1]}\n第11-15步: {costs[2]}\n第16-20步: {costs[3]}\n第21-25步: {costs[4]}\n\n请检查步骤配置，确认后点击\"保存配置\"。", 
                "确定");
        });
    }
    
    /// <summary>
    /// 批量设置批次
    /// </summary>
    private void OnBatchSetSkipClicked()
    {
        if (currentAreaStepRows.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "请先读取或创建配置！", "确定");
            return;
        }
        
        DecorateConfigBatchSkipWindow.ShowWindow((skips) =>
        {
            for (int i = 0; i < currentAreaStepRows.Count && i < skips.Length; i++)
            {
                currentAreaStepRows[i].Skip = NumberToSkipString(skips[i]);
            }
            
            MarkStepsModified();
            RefreshStepEditUI();
            
            EditorUtility.DisplayDialog("完成", 
                $"已设置{skips.Length}个步骤的批次！\n\n请检查步骤配置，确认后点击\"保存配置\"。", 
                "确定");
        });
    }
    
    /// <summary>
    /// 数字转批次字符串
    /// </summary>
    private string NumberToSkipString(int number)
    {
        string[] skipNames = { "", "first", "second", "third", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven" };
        if (number >= 0 && number < skipNames.Length)
            return skipNames[number];
        return "";
    }
    
    /// <summary>
    /// 递归扫描子物体（用于记录初始化）
    /// 注意：只扫描bg本身、clearObj和addObj的直接子物体（数字命名）
    /// </summary>
    private void ScanChildren(Transform parent, List<DecorateConfigRow> initRows)
    {
        // 只处理bg、clearObj、addObj
        if (parent == bgTransform)
        {
            // 记录bg本身
            UnityEngine.UI.Image bgImg = parent.GetComponent<UnityEngine.UI.Image>();
            if (bgImg != null && bgImg.sprite != null)
            {
                string fullSpritePath = AssetDatabase.GetAssetPath(bgImg.sprite.texture);
                string iconPath = ExtractIconPath(fullSpritePath);
                
                DecorateConfigRow bgRow = new DecorateConfigRow
                {
                    AreaId = currentAreaId,
                    SortId = 0,
                    CostCount = 0,
                    Title = "show",
                    Icon = iconPath,
                    Pos = "0#0",
                    Action = "init_img#bg",
                    Spine = "",
                    Button = "",
                    Build = "",
                    Shine = "",
                    Origin = "1232#2048",
                    DecoratePos = "",
                    Skip = "",
                    MapPethomeId = "",
                    PetExp = ""
                };
                initRows.Add(bgRow);
            }
            
            // 扫描clearObj和addObj的直接子物体
            Transform clearObj = parent.Find("clearObj");
            if (clearObj != null)
            {
                for (int i = 0; i < clearObj.childCount; i++)
                {
                    Transform child = clearObj.GetChild(i);
                    ScanDirectChild(child, $"bg/clearObj/{child.name}", initRows);
                }
            }
            
            Transform addObj = parent.Find("addObj");
            if (addObj != null)
            {
                for (int i = 0; i < addObj.childCount; i++)
                {
                    Transform child = addObj.GetChild(i);
                    ScanDirectChild(child, $"bg/addObj/{child.name}", initRows);
                }
            }
        }
    }
    
    /// <summary>
    /// 扫描单个子物体（不递归）- 用于名称排序时自动扫描
    /// </summary>
    private void ScanDirectChild(Transform child, string pathInBg, List<DecorateConfigRow> initRows)
    {
        UnityEngine.UI.Image img = child.GetComponent<UnityEngine.UI.Image>();
        if (img == null || img.sprite == null) return;
        
        // 图片物体：使用sprite.texture路径并提取相对路径
        string fullSpritePath = AssetDatabase.GetAssetPath(img.sprite.texture);
        string iconPath = ExtractIconPath(fullSpritePath);
        
        RectTransform rt = child.GetComponent<RectTransform>();
        Vector2 pos = rt != null ? rt.anchoredPosition : Vector2.zero;
        Vector2 size = rt != null ? rt.sizeDelta : Vector2.zero;
        
        DecorateConfigRow row = new DecorateConfigRow
        {
            AreaId = currentAreaId,
            SortId = 0,
            CostCount = 0,
            Title = "hide",  // 名称排序时扫描的新物体默认hide
            Icon = iconPath,
            Pos = $"{(int)pos.x}#{(int)pos.y}",
            Action = $"init_img#{pathInBg}",
            Spine = "",
            Button = "",
            Build = "",
            Shine = "",
            Origin = $"{(int)size.x}#{(int)size.y}",
            DecoratePos = "",
            Skip = "",
            MapPethomeId = "",
            PetExp = ""
        };
        initRows.Add(row);
    }
    
    #endregion
    
    #region 辅助方法
    
    /// <summary>
    /// 显示分辨率警告提示
    /// </summary>
    private void ShowResolutionWarning()
    {
        const string PREF_KEY = "DecorateConfigEditor.DontShowResolutionWarning";
        
        // 检查用户是否选择了"不再提示"
        if (EditorPrefs.GetBool(PREF_KEY, false))
        {
            return;
        }
        
        // 显示警告对话框
        bool dontShowAgain = EditorUtility.DisplayDialog(
            "⚠️ 重要提示",
            "Game窗口的分辨率必须设置为 1080×2340\n\n否则可能导致场景编辑器预览混乱！\n\n请在Unity顶部菜单栏：\nGame窗口 > 分辨率下拉框 > 设置为1080×2340\n\n勾选\"不再提示\"后，此提示将不会再显示。",
            "确定",
            "不再提示"
        );
        
        // 如果用户点击了"不再提示"按钮
        if (!dontShowAgain)
        {
            EditorPrefs.SetBool(PREF_KEY, true);
            Debug.Log("已设置不再显示分辨率警告提示");
        }
    }
    
    /// <summary>
    /// 加载装饰图标资源SO
    /// </summary>
    private ArtTableSO LoadDecorateIconSO()
    {
        if (decorateIconSO == null)
        {
            string soPath = "Assets/Art_SubModule/Art_SO/DecorateIcon/DecorateIconResource.asset";
            decorateIconSO = AssetDatabase.LoadAssetAtPath<ArtTableSO>(soPath);
            
            if (decorateIconSO == null)
            {
                Debug.LogWarning($"未找到装饰图标资源SO: {soPath}");
            }
        }
        return decorateIconSO;
    }
    
    /// <summary>
    /// 加载指定区域的场景资源SO
    /// </summary>
    private ArtTableSO LoadDecorateSceneSO(int areaId)
    {
        if (decorateSceneSODict.ContainsKey(areaId))
        {
            return decorateSceneSODict[areaId];
        }
        
        string soPath = $"Assets/Art_SubModule/Art_SO/DecorateScene/Scene{areaId}Resource.asset";
        ArtTableSO sceneSO = AssetDatabase.LoadAssetAtPath<ArtTableSO>(soPath);
        
        if (sceneSO != null)
        {
            decorateSceneSODict[areaId] = sceneSO;
        }
        else
        {
            Debug.LogWarning($"未找到场景资源SO: {soPath}");
        }
        
        return sceneSO;
    }
    
    /// <summary>
    /// 从SO中根据Name查找Sprite
    /// </summary>
    private Sprite FindSpriteInSO(string iconName, int areaId, bool isInitScene)
    {
        if (string.IsNullOrEmpty(iconName))
        {
            return null;
        }
        
        ArtTableSO targetSO = null;
        
        if (isInitScene)
        {
            // SortId=0 的初始化场景，从DecorateScene中找
            targetSO = LoadDecorateSceneSO(areaId);
        }
        else
        {
            // SortId>0 的步骤，从DecorateIcon中找
            targetSO = LoadDecorateIconSO();
        }
        
        if (targetSO == null || targetSO.Items == null)
        {
            return null;
        }
        
        // 在Items中查找匹配Name的项
        foreach (var item in targetSO.Items)
        {
            if (item.Name == iconName)
            {
                return item.Sprite;
            }
        }
        
        Debug.LogWarning($"在SO中未找到名称为 '{iconName}' 的资源 (AreaId={areaId}, IsInitScene={isInitScene})");
        return null;
    }
    
    /// <summary>
    /// 验证Icon名称是否存在于对应的SO中
    /// </summary>
    private bool ValidateIconNameInSO(string iconName, int areaId, bool isInitScene, out string errorMsg)
    {
        errorMsg = "";
        
        if (string.IsNullOrEmpty(iconName))
        {
            errorMsg = "Icon名称为空";
            return false;
        }
        
        ArtTableSO targetSO = null;
        string soType = "";
        
        if (isInitScene)
        {
            targetSO = LoadDecorateSceneSO(areaId);
            soType = $"DecorateScene/Scene{areaId}Resource";
        }
        else
        {
            targetSO = LoadDecorateIconSO();
            soType = "DecorateIcon/DecorateIconResource";
        }
        
        if (targetSO == null)
        {
            errorMsg = $"未找到SO资源: {soType}";
            return false;
        }
        
        if (targetSO.Items == null || targetSO.Items.Count == 0)
        {
            errorMsg = $"SO资源为空: {soType}";
            return false;
        }
        
        // 检查是否存在匹配的Name
        foreach (var item in targetSO.Items)
        {
            if (item.Name == iconName)
            {
                return true;
            }
        }
        
        errorMsg = $"在 {soType} 中未找到名称为 '{iconName}' 的资源";
        return false;
    }
    
    /// <summary>
    /// 从Icon名称加载Sprite（兼容旧路径格式，自动转换为Name）
    /// </summary>
    private Sprite LoadSpriteFromIconName(string iconNameOrPath, int areaId, bool isInitScene)
    {
        if (string.IsNullOrEmpty(iconNameOrPath))
        {
            return null;
        }
        
        // 如果包含'/'，说明可能是旧格式路径，提取最后一段作为Name
        string iconName = iconNameOrPath;
        if (iconName.Contains("/"))
        {
            iconName = iconName.Substring(iconName.LastIndexOf('/') + 1);
        }
        
        // 从SO中加载
        return FindSpriteInSO(iconName, areaId, isInitScene);
    }
    
    /// <summary>
    /// 更新状态栏显示
    /// </summary>
    private void UpdateStatusLabel()
    {
        if (statusLabel == null) return;
        
        if (!isStepsModified && !isInitRecorded)
        {
            statusLabel.text = "⚪ 待保存状态：无修改";
            statusLabel.style.color = new Color(0.7f, 0.7f, 0.7f);
        }
        else
        {
            StringBuilder status = new StringBuilder("🔵 待保存状态：");
            if (isStepsModified)
            {
                status.Append("步骤 [已修改] ");
            }
            if (isInitRecorded)
            {
                status.Append("初始状态 [已记录]");
            }
            statusLabel.text = status.ToString();
            statusLabel.style.color = new Color(0.4f, 0.6f, 1f);
        }
    }
    
    /// <summary>
    /// 深拷贝配置行列表
    /// </summary>
    private List<DecorateConfigRow> DeepCopyRows(List<DecorateConfigRow> source)
    {
        List<DecorateConfigRow> result = new List<DecorateConfigRow>();
        foreach (var row in source)
        {
            result.Add(DecorateConfigRow.DeepCopy(row));
        }
        return result;
    }
    
    /// <summary>
    /// 验证配置中的路径是否在场景中存在
    /// </summary>
    private List<string> ValidateConfigPaths(List<DecorateConfigRow> initRows, List<DecorateConfigRow> stepRows)
    {
        if (bgTransform == null) return new List<string>();
        
        List<string> invalidPaths = new List<string>();
        HashSet<string> checkedPaths = new HashSet<string>();
        
        // 检查初始化配置中的路径
        foreach (var row in initRows)
        {
            if (string.IsNullOrEmpty(row.Action)) continue;
            
            string[] actions = row.Action.Split('@');
            foreach (string action in actions)
            {
                string[] parts = action.Split('#');
                if (parts.Length < 2) continue;
                
                string[] paths = parts[1].Split(',');
                foreach (string path in paths)
                {
                    string trimmedPath = path.Trim();
                    if (string.IsNullOrEmpty(trimmedPath) || checkedPaths.Contains(trimmedPath)) continue;
                    
                    checkedPaths.Add(trimmedPath);
                    Transform obj = FindTransformByPath(trimmedPath);
                    if (obj == null)
                    {
                        invalidPaths.Add($"{trimmedPath} (初始化)");
                    }
                }
            }
        }
        
        // 检查步骤配置中的路径
        foreach (var row in stepRows)
        {
            if (string.IsNullOrEmpty(row.Action)) continue;
            
            string[] actions = row.Action.Split('@');
            foreach (string action in actions)
            {
                if (action.Contains("spine")) continue;
                
                string[] parts = action.Split('#');
                if (parts.Length < 2) continue;
                
                string actionType = parts[0];
                string pathsStr = parts[1];
                string[] paths = pathsStr.Split(',');
                
                foreach (string path in paths)
                {
                    string trimmedPath = path.Trim();
                    if (string.IsNullOrEmpty(trimmedPath) || checkedPaths.Contains(trimmedPath)) continue;
                    
                    // replace_image和reset_pos的最后一个参数不是路径
                    if ((actionType == "replace_image" || actionType == "reset_pos") && path == paths[paths.Length - 1])
                    {
                        continue;
                    }
                    
                    checkedPaths.Add(trimmedPath);
                    Transform obj = FindTransformByPath(trimmedPath);
                    if (obj == null)
                    {
                        invalidPaths.Add($"{trimmedPath} (步骤{row.SortId})");
                    }
                }
            }
        }
        
        return invalidPaths;
    }
    
    /// <summary>
    /// 智能补全初始化：检查步骤中所有Action引用的物体是否在初始化中，如果没有则自动补全为hide
    /// 关键修复：新增物体自动补全为hide，保持原有物体的位置不变
    /// </summary>
    private void AutoCompleteInitRows(List<DecorateConfigRow> initRows, List<DecorateConfigRow> stepRows)
    {
        // 收集初始化中已存在的物体路径
        HashSet<string> existingPaths = new HashSet<string>();
        foreach (var initRow in initRows)
        {
            if (string.IsNullOrEmpty(initRow.Action)) continue;
            
            // 解析Action: init_img#路径 或 init_spine#路径
            string[] actions = initRow.Action.Split('@');
            foreach (string action in actions)
            {
                string[] parts = action.Split('#');
                if (parts.Length >= 2)
                {
                    string[] paths = parts[1].Split(',');
                    foreach (string path in paths)
                    {
                        if (!string.IsNullOrEmpty(path))
                        {
                            existingPaths.Add(path.Trim());
                        }
                    }
                }
            }
        }
        
        // 收集步骤中所有Action引用的物体路径（所有类型：clear, add, replace, replace_image, reset_pos）
        HashSet<string> referencedPaths = new HashSet<string>();
        foreach (var stepRow in stepRows)
        {
            if (string.IsNullOrEmpty(stepRow.Action)) continue;
            
            string[] actions = stepRow.Action.Split('@');
            foreach (string action in actions)
            {
                // 跳过spine相关操作
                if (action.Contains("spine")) continue;
                
                string[] parts = action.Split('#');
                if (parts.Length < 2) continue;
                
                string actionType = parts[0];
                string pathsStr = parts[1];
                
                // 解析路径（逗号分隔）
                string[] paths = pathsStr.Split(',');
                foreach (string path in paths)
                {
                    string trimmedPath = path.Trim();
                    if (string.IsNullOrEmpty(trimmedPath)) continue;
                    
                    // replace_image和reset_pos的第一个参数是路径，第二个参数不是
                    if ((actionType == "replace_image" || actionType == "reset_pos") && path == paths[paths.Length - 1])
                    {
                        continue;  // 跳过最后一个参数（图片路径或位置）
                    }
                    
                    if (!existingPaths.Contains(trimmedPath))
                    {
                        referencedPaths.Add(trimmedPath);
                    }
                }
            }
        }
        
        // 自动补全缺失的初始化行（新增物体默认为hide）
        if (referencedPaths.Count > 0)
        {
            Debug.Log($"✨ 智能补全：检测到{referencedPaths.Count}个新增物体未在初始化中记录，自动补全为hide：\n{string.Join("\n", referencedPaths)}");
            
            foreach (string path in referencedPaths)
            {
                // 从场景中获取物体信息（位置、大小、图片）
                Transform obj = FindTransformByPath(path);
                string icon = "";
                string pos = "0#0";     // 默认位置
                string origin = "";     // 默认大小
                
                if (obj != null)
                {
                    // 读取图片
                    var image = obj.GetComponent<UnityEngine.UI.Image>();
                    if (image != null && image.sprite != null)
                    {
                        string spritePath = AssetDatabase.GetAssetPath(image.sprite.texture);
                        icon = ExtractIconPath(spritePath);
                    }
                    
                    // 读取位置和大小
                    RectTransform rt = obj.GetComponent<RectTransform>();
                    if (rt != null)
                    {
                        // ⚠️ 关键修复：读取当前场景中的实际位置
                        pos = $"{(int)rt.anchoredPosition.x}#{(int)rt.anchoredPosition.y}";
                        // ⚠️ 关键修复：读取当前场景中的实际大小
                        origin = $"{(int)rt.sizeDelta.x}#{(int)rt.sizeDelta.y}";
                    }
                }
                
                DecorateConfigRow newInitRow = new DecorateConfigRow
                {
                    AreaId = currentAreaId,
                    SortId = 0,
                    CostCount = 0,
                    Title = "hide",  // 新增物体默认为hide
                    Icon = icon,
                    Pos = pos,       // ✅ 使用场景中的当前位置
                    Action = $"init_img#{path}",
                    Spine = "",
                    Button = "",
                    Build = "",
                    Shine = "",
                    Origin = origin, // ✅ 使用场景中的当前大小
                    DecoratePos = "",
                    Skip = "",
                    MapPethomeId = "",
                    PetExp = ""
                };
                initRows.Add(newInitRow);
                existingPaths.Add(path);
                
                Debug.Log($"  ✅ 新增物体 {path}: Pos={pos}, Origin={origin}, Icon={icon}");
            }
        }
    }
    
    /// <summary>
    /// 智能修复初始化配置的Title：根据场景中物体的实际显示状态更新
    /// </summary>
    private void AutoFixInitRowTitles(List<DecorateConfigRow> initRows)
    {
        if (bgTransform == null) return;
        
        int fixedCount = 0;
        foreach (var row in initRows)
        {
            if (string.IsNullOrEmpty(row.Action)) continue;
            
            // 解析路径
            string[] parts = row.Action.Split('#');
            if (parts.Length < 2) continue;
            
            string path = parts[1];
            
            // 在场景中查找物体
            Transform obj = FindTransformByPath(path);
            if (obj != null)
            {
                // 根据场景中的实际显示状态更新Title
                string correctTitle = obj.gameObject.activeSelf ? "show" : "hide";
                if (row.Title != correctTitle)
                {
                    Debug.Log($"🔧 修复Title: {path} - {row.Title} → {correctTitle}");
                    row.Title = correctTitle;
                    fixedCount++;
                }
            }
        }
        
        if (fixedCount > 0)
        {
            Debug.Log($"✅ 智能修复：根据场景状态更新了{fixedCount}个物体的Title");
        }
    }
    
    /// <summary>
    /// 对比步骤修改
    /// </summary>
    private string CompareStepChanges()
    {
        StringBuilder diff = new StringBuilder();
        int changedCount = 0;
        
        for (int i = 0; i < currentAreaStepRows.Count; i++)
        {
            var current = currentAreaStepRows[i];
            var original = originalAreaStepRows.FirstOrDefault(r => r.SortId == current.SortId);
            
            if (original == null) continue;
            
            List<string> changes = new List<string>();
            
            if (current.Title != original.Title) changes.Add($"标题: \"{original.Title}\" → \"{current.Title}\"");
            if (current.Icon != original.Icon) changes.Add($"Icon: {original.Icon} → {current.Icon}");
            if (current.CostCount != original.CostCount) changes.Add($"消耗: {original.CostCount} → {current.CostCount}");
            if (current.Skip != original.Skip) changes.Add($"批次: \"{original.Skip}\" → \"{current.Skip}\"");
            if (current.Action != original.Action) changes.Add($"Action已修改");
            if (current.Build != original.Build) changes.Add($"建造效果: \"{original.Build}\" → \"{current.Build}\"");
            if (current.Shine != original.Shine) changes.Add($"闪光: \"{original.Shine}\" → \"{current.Shine}\"");
            if (current.DecoratePos != original.DecoratePos) changes.Add($"Icon位置: {original.DecoratePos} → {current.DecoratePos}");
            
            if (changes.Count > 0)
            {
                changedCount++;
                diff.AppendLine($"【步骤{current.SortId}】");
                foreach (var change in changes)
                {
                    diff.AppendLine($"  • {change}");
                }
                diff.AppendLine();
                
                // 只显示前5个修改的步骤
                if (changedCount >= 5)
                {
                    int remaining = currentAreaStepRows.Count - i - 1;
                    if (remaining > 0)
                    {
                        diff.AppendLine($"... 还有更多修改未显示");
                    }
                    break;
                }
            }
        }
        
        return diff.ToString();
    }
    
    /// <summary>
    /// 创建25个空步骤
    /// </summary>
    private void CreateEmptySteps()
    {
        currentAreaStepRows.Clear();
        
        for (int i = 1; i <= maxSteps; i++)
        {
            DecorateConfigRow row = new DecorateConfigRow
            {
                AreaId = currentAreaId,
                SortId = i,
                CostCount = 0,
                Title = "",
                Icon = $"Icon/s{currentAreaId}_{i}",
                Pos = "",
                Action = "",
                Spine = "",
                Button = "",
                Build = "",
                Shine = "",
                Origin = "",
                DecoratePos = "",
                Skip = "",
                MapPethomeId = "",
                PetExp = ""
            };
            currentAreaStepRows.Add(row);
        }
    }
    
    /// <summary>
    /// 标记步骤已修改
    /// </summary>
    private void MarkStepsModified()
    {
        isStepsModified = true;
        UpdateStatusLabel();
    }

    #endregion
}

/// <summary>
/// 输入对话框窗口
/// </summary>
public class InputDialogWindow : EditorWindow
{
    public string message = "";
    public string inputValue = "";
    public bool confirmed = false;

    void OnGUI()
    {
        EditorGUILayout.LabelField(message, EditorStyles.wordWrappedLabel);
        EditorGUILayout.Space();
        
        inputValue = EditorGUILayout.TextField("AreaId:", inputValue);
        
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        
        if (GUILayout.Button("确认"))
        {
            confirmed = true;
            Close();
        }
        
        if (GUILayout.Button("取消"))
        {
            confirmed = false;
            Close();
        }
        
        EditorGUILayout.EndHorizontal();
    }
}

/// <summary>
/// 配置数据行
/// </summary>
public class DecorateConfigRow
{
    public int AreaId;
    public int SortId;
    public int CostCount;
    public string Title;
    public string Icon;
    public string Pos;
    public string Action;
    public string Spine;
    public string Button;
    public string Build;
    public string Shine;
    public string Origin;
    public string DecoratePos;
    public string Skip;
    public string MapPethomeId;
    public string PetExp;

    public void ParseFromFields(string[] fields)
    {
        // XLSX文件格式：Id + AreaId + SortId + ...（没有第一个空列）
        // fields[0] = Id（忽略，因为会自动重新生成）
        // fields[1] = AreaId
        // 所以从fields[1]开始读取（和TXT一样，但字段索引整体左移1）
        AreaId = ParseInt(fields[1]);
        SortId = ParseInt(fields[2]);
        CostCount = ParseInt(fields[3]);
        Title = fields.Length > 4 ? fields[4] : "";
        Icon = fields.Length > 5 ? fields[5] : "";
        
        // SortId != 0 时，Pos字段存储批次信息
        if (SortId != 0)
        {
            Skip = fields.Length > 6 ? fields[6] : "";  // 步骤配置：Pos字段读取到Skip（批次）
            Pos = "";                                     // 步骤配置不使用Pos作为位置
        }
        else
        {
            Pos = fields.Length > 6 ? fields[6] : "";    // 初始化配置：Pos字段是位置
            Skip = fields.Length > 14 ? fields[14] : "";  // 初始化配置从fields[14]读取Skip
        }
        
        Action = fields.Length > 7 ? fields[7] : "";
        Spine = fields.Length > 8 ? fields[8] : "";
        Button = fields.Length > 9 ? fields[9] : "";
        Build = fields.Length > 10 ? fields[10] : "";
        Shine = fields.Length > 11 ? fields[11] : "";
        Origin = fields.Length > 12 ? fields[12] : "";
        DecoratePos = fields.Length > 13 ? fields[13] : "";
        MapPethomeId = fields.Length > 15 ? fields[15] : "";
        PetExp = fields.Length > 16 ? fields[16] : "";
    }

    public string ToConfigLine(int autoId)
    {
        // 格式：[空]\t[自增Id]\t[AreaId]\t...
        // SortId != 0 时，Pos字段存储批次信息
        string posValue = (SortId != 0) ? Skip : Pos;  // 步骤配置：Pos输出批次；初始化配置：Pos输出位置
        string skipValue = (SortId != 0) ? "" : Skip;  // 步骤配置：Skip留空；初始化配置：Skip输出实际值
        return $"\t{autoId}\t{AreaId}\t{SortId}\t{CostCount}\t{Title}\t{Icon}\t{posValue}\t{Action}\t{Spine}\t{Button}\t{Build}\t{Shine}\t{Origin}\t{DecoratePos}\t{skipValue}\t{MapPethomeId}\t{PetExp}";
    }
    
    /// <summary>
    /// 将配置写入Excel行（XLSX格式，没有第一个空列）
    /// </summary>
    public void WriteToExcelRow(ExcelWorksheet worksheet, int row, int autoId)
    {
        // SortId != 0 时，Pos字段存储批次信息
        string posValue = (SortId != 0) ? Skip : Pos;  // 步骤配置：Pos输出批次；初始化配置：Pos输出位置
        string skipValue = (SortId != 0) ? "" : Skip;  // 步骤配置：Skip留空；初始化配置：Skip输出实际值
        
        worksheet.Cells[row, 1].Value = autoId;
        worksheet.Cells[row, 2].Value = AreaId;
        worksheet.Cells[row, 3].Value = SortId;
        worksheet.Cells[row, 4].Value = CostCount;
        worksheet.Cells[row, 5].Value = Title;
        worksheet.Cells[row, 6].Value = Icon;
        worksheet.Cells[row, 7].Value = posValue;
        worksheet.Cells[row, 8].Value = Action;
        worksheet.Cells[row, 9].Value = Spine;
        worksheet.Cells[row, 10].Value = Button;
        worksheet.Cells[row, 11].Value = Build;
        worksheet.Cells[row, 12].Value = Shine;
        worksheet.Cells[row, 13].Value = Origin;
        worksheet.Cells[row, 14].Value = DecoratePos;
        worksheet.Cells[row, 15].Value = skipValue;
        worksheet.Cells[row, 16].Value = MapPethomeId;
        worksheet.Cells[row, 17].Value = PetExp;
    }

    private int ParseInt(string str)
    {
        int result;
        if (int.TryParse(str, out result))
            return result;
        return 0;
    }
    
    /// <summary>
    /// 深拷贝配置行列表
    /// </summary>
    public static DecorateConfigRow DeepCopy(DecorateConfigRow source)
    {
        return new DecorateConfigRow
        {
            AreaId = source.AreaId,
            SortId = source.SortId,
            CostCount = source.CostCount,
            Title = source.Title,
            Icon = source.Icon,
            Pos = source.Pos,
            Action = source.Action,
            Spine = source.Spine,
            Button = source.Button,
            Build = source.Build,
            Shine = source.Shine,
            Origin = source.Origin,
            DecoratePos = source.DecoratePos,
            Skip = source.Skip,
            MapPethomeId = source.MapPethomeId,
            PetExp = source.PetExp
        };
    }
}

/// <summary>
/// 批量设置资源消耗弹窗
/// </summary>
public class DecorateConfigBatchCostWindow : EditorWindow
{
    private IntegerField[] costFields = new IntegerField[5];
    private System.Action<int[]> onConfirm;

    public static void ShowWindow(System.Action<int[]> confirmCallback)
    {
        var window = GetWindow<DecorateConfigBatchCostWindow>("批量设置资源消耗");
        window.minSize = new Vector2(300, 250);
        window.onConfirm = confirmCallback;
    }

    private void CreateGUI()
    {
        VisualElement root = rootVisualElement;
        root.style.paddingTop = 10;
        root.style.paddingBottom = 10;
        root.style.paddingLeft = 10;
        root.style.paddingRight = 10;

        Label title = new Label("输入5个资源消耗数值\n每5个步骤使用同一数值");
        title.style.fontSize = 14;
        title.style.marginBottom = 10;
        title.style.unityTextAlign = TextAnchor.MiddleCenter;
        root.Add(title);

        for (int i = 0; i < 5; i++)
        {
            IntegerField field = new IntegerField($"第{i * 5 + 1}-{(i + 1) * 5}步:");
            field.value = 0;
            field.style.marginBottom = 5;
            costFields[i] = field;
            root.Add(field);
        }

        VisualElement buttonRow = new VisualElement();
        buttonRow.style.flexDirection = FlexDirection.Row;
        buttonRow.style.marginTop = 15;

        UnityEngine.UIElements.Button confirmBtn = new UnityEngine.UIElements.Button(() => OnConfirmClicked()) { text = "确定" };
        confirmBtn.style.flexGrow = 1;
        confirmBtn.style.marginRight = 5;
        buttonRow.Add(confirmBtn);

        UnityEngine.UIElements.Button cancelBtn = new UnityEngine.UIElements.Button(() => Close()) { text = "取消" };
        cancelBtn.style.flexGrow = 1;
        buttonRow.Add(cancelBtn);

        root.Add(buttonRow);
    }

    private void OnConfirmClicked()
    {
        int[] costs = new int[5];
        for (int i = 0; i < 5; i++)
        {
            costs[i] = costFields[i].value;
        }
        onConfirm?.Invoke(costs);
        Close();
    }
}

/// <summary>
/// 批量设置批次弹窗
/// </summary>
public class DecorateConfigBatchSkipWindow : EditorWindow
{
    private IntegerField[] skipFields = new IntegerField[25];
    private ScrollView scrollView;
    private System.Action<int[]> onConfirm;

    public static void ShowWindow(System.Action<int[]> confirmCallback)
    {
        var window = GetWindow<DecorateConfigBatchSkipWindow>("批量设置批次");
        window.minSize = new Vector2(350, 500);
        window.onConfirm = confirmCallback;
    }

    private void CreateGUI()
    {
        VisualElement root = rootVisualElement;
        root.style.paddingTop = 10;
        root.style.paddingBottom = 10;
        root.style.paddingLeft = 10;
        root.style.paddingRight = 10;

        Label title = new Label("输入25个数字设置批次\n0=空 1=first 2=second 3=third...");
        title.style.fontSize = 14;
        title.style.marginBottom = 10;
        title.style.unityTextAlign = TextAnchor.MiddleCenter;
        root.Add(title);

        scrollView = new ScrollView();
        scrollView.style.flexGrow = 1;

        for (int i = 0; i < 25; i++)
        {
            IntegerField field = new IntegerField($"步骤{i + 1}:");
            field.value = 0;
            field.style.marginBottom = 3;
            skipFields[i] = field;
            scrollView.Add(field);
        }

        root.Add(scrollView);

        VisualElement buttonRow = new VisualElement();
        buttonRow.style.flexDirection = FlexDirection.Row;
        buttonRow.style.marginTop = 10;

        UnityEngine.UIElements.Button confirmBtn = new UnityEngine.UIElements.Button(() => OnConfirmClicked()) { text = "确定" };
        confirmBtn.style.flexGrow = 1;
        confirmBtn.style.marginRight = 5;
        buttonRow.Add(confirmBtn);

        UnityEngine.UIElements.Button cancelBtn = new UnityEngine.UIElements.Button(() => Close()) { text = "取消" };
        cancelBtn.style.flexGrow = 1;
        buttonRow.Add(cancelBtn);

        root.Add(buttonRow);
    }

    private void OnConfirmClicked()
    {
        int[] skips = new int[25];
        for (int i = 0; i < 25; i++)
        {
            skips[i] = skipFields[i].value;
        }
        onConfirm?.Invoke(skips);
        Close();
    }
}
