// Copyright (c) 2025 EFramework Innovation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
namespace EFramework.Unity.UIPlugin.Editor
{
///
/// UIWrapContent 组件的自定义编辑器,提供包装内容布局的编辑界面和创建功能。
///
///
///
/// 功能特性
/// - 为 UIWrapContent 组件提供自定义 Inspector 界面
/// - 支持垂直列表、水平列表、垂直网格和水平网格四种布局模式
/// - 提供便捷的Unity编辑器菜单创建组件
///
/// 更多信息请参考模块文档。
///
[CustomEditor(typeof(UIWrapContent), true)]
[CanEditMultipleObjects]
public class UIWrapContentEditor : ScrollRectEditor
{
///
/// 当前编辑的 UIWrapContent 实例
///
private UIWrapContent activeTarget;
///
/// 布局模式属性
///
private SerializedProperty layoutProp;
///
/// 分段属性(列表模式下为间距,网格模式下为列数或行数)
///
private SerializedProperty segmentProp;
///
/// 边距属性(列表模式下为边距,网格模式下为间距)
///
private SerializedProperty paddingProp;
///
/// 启用编辑器时初始化序列化属性。
///
protected override void OnEnable()
{
base.OnEnable();
activeTarget = (UIWrapContent)target;
layoutProp = serializedObject.FindProperty("layout");
segmentProp = serializedObject.FindProperty("segment");
paddingProp = serializedObject.FindProperty("padding");
}
///
/// 绘制自定义 Inspector 界面,根据不同的布局模式显示不同的属性。
///
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(layoutProp, new GUIContent("Layout"));
switch (activeTarget.Layout)
{
case UIWrapContent.LayoutMode.VerticalList:
EditorGUILayout.PropertyField(segmentProp, new GUIContent("Space"));
EditorGUILayout.PropertyField(paddingProp, new GUIContent("Margin"));
EditorGUILayout.HelpBox("X - Top, Y - Bottom", MessageType.Info, false);
break;
case UIWrapContent.LayoutMode.HorizontalList:
EditorGUILayout.PropertyField(segmentProp, new GUIContent("Space"));
EditorGUILayout.PropertyField(paddingProp, new GUIContent("Margin"));
EditorGUILayout.HelpBox("X - Left, Y - Right", MessageType.Info, false);
break;
case UIWrapContent.LayoutMode.VerticalGrid:
EditorGUILayout.PropertyField(paddingProp, new GUIContent("Space"));
EditorGUILayout.HelpBox("X - Horizontal, Y - Vertical", MessageType.Info, false);
if (EditorGUILayout.PropertyField(segmentProp, new GUIContent("Columns"))) segmentProp.intValue = Math.Max(1, segmentProp.intValue);
break;
case UIWrapContent.LayoutMode.HorizontalGrid:
EditorGUILayout.PropertyField(paddingProp, new GUIContent("Space"));
EditorGUILayout.HelpBox("X - Horizontal, Y - Vertical", MessageType.Info, false);
if (EditorGUILayout.PropertyField(segmentProp, new GUIContent("Rows"))) segmentProp.intValue = Math.Max(1, segmentProp.intValue);
break;
default:
throw new ArgumentOutOfRangeException();
}
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
///
/// 创建包装内容的菜单项处理方法,基于滚动视图添加 UIWrapContent 组件。
///
[MenuItem("GameObject/UI/Wrap Content")]
private static void CreateTemplate()
{
EditorApplication.ExecuteMenuItem("GameObject/UI/Scroll View");
var selected = Selection.activeGameObject;
selected.name = "Wrap Content";
var scrollRect = selected.GetComponent();
var serialObj = new SerializedObject(scrollRect);
List serialProps = new List();
SerializedProperty it = serialObj.GetIterator();
bool children = true;
while (it.NextVisible(children))
{
if (it.name == "m_Script") continue;
serialProps.Add(it.Copy());
}
DestroyImmediate(scrollRect);
var wrapContent = selected.AddComponent();
serialObj = new SerializedObject(wrapContent);
foreach (var item in serialProps)
{
serialObj.CopyFromSerializedProperty(item);
}
serialObj.ApplyModifiedProperties();
Selection.activeGameObject = selected;
Undo.RegisterCreatedObjectUndo(selected, "Create Wrap Content");
}
}
}