Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавил больше настроек в систему настроек - Пока у большинства настроек нет функционала - Немного изменил внешний вид настроек
337 lines
14 KiB
C#
337 lines
14 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using RR.Common.Settings;
|
|
|
|
namespace RR.Common.InspectorOverrides
|
|
{
|
|
/// <summary>
|
|
/// Custom property drawer for SettingEntry - v1.2
|
|
/// </summary>
|
|
[CustomPropertyDrawer(typeof(SettingEntry))]
|
|
public class SettingEntryDrawer : PropertyDrawer
|
|
{
|
|
private const float Pad = 6f;
|
|
|
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
// Чтоб выглядело стабильнее в узких инспекторах
|
|
bool prevWide = EditorGUIUtility.wideMode;
|
|
float prevLabelWidth = EditorGUIUtility.labelWidth;
|
|
EditorGUIUtility.wideMode = true;
|
|
EditorGUIUtility.labelWidth = 110f;
|
|
|
|
EditorGUI.BeginProperty(position, label, property);
|
|
|
|
var keyProp = property.FindPropertyRelative("key");
|
|
var nameProp = property.FindPropertyRelative("displayName");
|
|
var descProp = property.FindPropertyRelative("description");
|
|
var groupProp = property.FindPropertyRelative("group");
|
|
var shownInSettingsProp = property.FindPropertyRelative("shownInSettings");
|
|
var exposedProp = property.FindPropertyRelative("exposed");
|
|
var typeProp = property.FindPropertyRelative("valueType");
|
|
|
|
var defBoolProp = property.FindPropertyRelative("defaultBool");
|
|
var defIntProp = property.FindPropertyRelative("defaultInt");
|
|
var defFloatProp = property.FindPropertyRelative("defaultFloat");
|
|
var defStringProp = property.FindPropertyRelative("defaultString");
|
|
|
|
var minIntProp = property.FindPropertyRelative("minInt");
|
|
var maxIntProp = property.FindPropertyRelative("maxInt");
|
|
var intDisplayFormatProp = property.FindPropertyRelative("intDisplayFormat");
|
|
var intStepProp = property.FindPropertyRelative("intStep");
|
|
var minFloatProp = property.FindPropertyRelative("minFloat");
|
|
var maxFloatProp = property.FindPropertyRelative("maxFloat");
|
|
var displayAsPercentageProp = property.FindPropertyRelative("displayAsPercentage");
|
|
|
|
var applyProp = property.FindPropertyRelative("applyTarget");
|
|
var audioTargetProp = property.FindPropertyRelative("audioTargetType");
|
|
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
// Card
|
|
var box = new Rect(position.x, position.y, position.width, position.height);
|
|
GUI.Box(box, GUIContent.none, EditorStyles.helpBox);
|
|
|
|
var r = new Rect(position.x + Pad, position.y + Pad, position.width - Pad * 2, line);
|
|
|
|
// Header foldout
|
|
string header = BuildHeader(nameProp.stringValue, keyProp.stringValue);
|
|
property.isExpanded = EditorGUI.Foldout(r, property.isExpanded, header, true);
|
|
r.y += line + space;
|
|
|
|
if (!property.isExpanded)
|
|
{
|
|
EditorGUI.EndProperty();
|
|
EditorGUIUtility.wideMode = prevWide;
|
|
EditorGUIUtility.labelWidth = prevLabelWidth;
|
|
return;
|
|
}
|
|
|
|
DrawSectionTitle(ref r, "Meta");
|
|
DrawProp(ref r, nameProp, "Display Name");
|
|
DrawProp(ref r, keyProp, "Key");
|
|
DrawProp(ref r, groupProp, "Group");
|
|
DrawProp(ref r, descProp, "Description", includeChildren: true);
|
|
|
|
DrawSectionTitle(ref r, "Visibility & Access");
|
|
DrawFlagsRow(ref r, shownInSettingsProp, exposedProp, "Shown in UI", "Exposed");
|
|
|
|
DrawSectionTitle(ref r, "Value");
|
|
DrawProp(ref r, typeProp, "Value Type");
|
|
|
|
var t = (SettingValueType)typeProp.enumValueIndex;
|
|
|
|
switch (t)
|
|
{
|
|
case SettingValueType.Bool:
|
|
DrawProp(ref r, defBoolProp, "Default");
|
|
break;
|
|
|
|
case SettingValueType.Int:
|
|
DrawProp(ref r, defIntProp, "Default");
|
|
DrawMinMaxRow(ref r, minIntProp, maxIntProp, "Min", "Max");
|
|
DrawProp(ref r, intDisplayFormatProp, "Display Format");
|
|
|
|
// Показываем intStep только если выбран ValueSelector
|
|
var displayFormat = (IntDisplayFormat)intDisplayFormatProp.enumValueIndex;
|
|
if (displayFormat == IntDisplayFormat.ValueSelector)
|
|
{
|
|
DrawProp(ref r, intStepProp, "Step");
|
|
}
|
|
break;
|
|
|
|
case SettingValueType.Float:
|
|
DrawProp(ref r, defFloatProp, "Default");
|
|
DrawMinMaxRow(ref r, minFloatProp, maxFloatProp, "Min", "Max");
|
|
DrawProp(ref r, displayAsPercentageProp, "Display as %");
|
|
break;
|
|
|
|
case SettingValueType.String:
|
|
DrawProp(ref r, defStringProp, "Default");
|
|
break;
|
|
|
|
case SettingValueType.Button:
|
|
DrawSectionTitle(ref r, "Button Settings");
|
|
var buttonTextProp = property.FindPropertyRelative("buttonText");
|
|
var buttonDataProp = property.FindPropertyRelative("buttonData");
|
|
var buttonColorProp = property.FindPropertyRelative("buttonColor");
|
|
var buttonSpriteProp = property.FindPropertyRelative("buttonSprite");
|
|
|
|
DrawProp(ref r, buttonTextProp, "Button Text");
|
|
DrawProp(ref r, buttonDataProp, "Button Data");
|
|
DrawProp(ref r, buttonColorProp, "Button Color");
|
|
DrawProp(ref r, buttonSpriteProp, "Button Sprite");
|
|
break;
|
|
|
|
case SettingValueType.OptionPicker:
|
|
DrawSectionTitle(ref r, "Option Picker Settings");
|
|
var optionsProp = property.FindPropertyRelative("options");
|
|
var defOptionIndexProp = property.FindPropertyRelative("defaultOptionIndex");
|
|
|
|
DrawProp(ref r, optionsProp, "Options", includeChildren: true);
|
|
DrawProp(ref r, defOptionIndexProp, "Default Index");
|
|
break;
|
|
}
|
|
|
|
DrawSectionTitle(ref r, "Apply");
|
|
DrawProp(ref r, applyProp, "Apply Target");
|
|
|
|
var apply = (ApplyTarget)applyProp.enumValueIndex;
|
|
if (apply == ApplyTarget.Audio)
|
|
{
|
|
DrawProp(ref r, audioTargetProp, "Audio Type");
|
|
}
|
|
|
|
// Warning
|
|
if (string.IsNullOrWhiteSpace(keyProp.stringValue))
|
|
{
|
|
var warnH = line * 1.4f;
|
|
var warn = new Rect(r.x, r.y, r.width, warnH);
|
|
EditorGUI.HelpBox(warn, "Key is empty - setting won't work.", MessageType.Warning);
|
|
r.y += warnH + space;
|
|
}
|
|
|
|
EditorGUI.EndProperty();
|
|
|
|
// restore
|
|
EditorGUIUtility.wideMode = prevWide;
|
|
EditorGUIUtility.labelWidth = prevLabelWidth;
|
|
}
|
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
{
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
float h = 0f;
|
|
|
|
// padding + foldout
|
|
h += Pad * 2;
|
|
h += line + space;
|
|
|
|
if (!property.isExpanded)
|
|
return h + 2f;
|
|
|
|
SerializedProperty keyProp = property.FindPropertyRelative("key");
|
|
SerializedProperty nameProp = property.FindPropertyRelative("displayName");
|
|
SerializedProperty groupProp = property.FindPropertyRelative("group");
|
|
SerializedProperty descProp = property.FindPropertyRelative("description");
|
|
SerializedProperty typeProp = property.FindPropertyRelative("valueType");
|
|
SerializedProperty applyProp = property.FindPropertyRelative("applyTarget");
|
|
|
|
// Meta section title
|
|
h += line + space;
|
|
h += HeightOf(nameProp) + space;
|
|
h += HeightOf(keyProp) + space;
|
|
h += HeightOf(groupProp) + space;
|
|
h += HeightOf(descProp, true) + space;
|
|
|
|
// Visibility & Access section title
|
|
h += line + space;
|
|
h += line + space; // flags row (shownInSettings + exposed)
|
|
|
|
// Value section title
|
|
h += line + space;
|
|
h += HeightOf(typeProp) + space;
|
|
|
|
// Default + optional range row
|
|
SettingValueType t = (SettingValueType)typeProp.enumValueIndex;
|
|
|
|
switch (t)
|
|
{
|
|
case SettingValueType.Bool:
|
|
case SettingValueType.String:
|
|
h += line + space; // Default
|
|
break;
|
|
|
|
case SettingValueType.Int:
|
|
h += line + space; // Default
|
|
h += line + space; // range row
|
|
h += line + space; // intDisplayFormat
|
|
|
|
// Добавляем высоту для intStep если выбран ValueSelector
|
|
var intDisplayFormatProp = property.FindPropertyRelative("intDisplayFormat");
|
|
if (intDisplayFormatProp != null)
|
|
{
|
|
var displayFormat = (IntDisplayFormat)intDisplayFormatProp.enumValueIndex;
|
|
if (displayFormat == IntDisplayFormat.ValueSelector)
|
|
{
|
|
h += line + space; // intStep
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SettingValueType.Float:
|
|
h += line + space; // Default
|
|
h += line + space; // range row
|
|
h += line + space; // displayAsPercentage checkbox
|
|
break;
|
|
|
|
case SettingValueType.Button:
|
|
h += line + space; // section title
|
|
h += line + space; // buttonText
|
|
h += line + space; // buttonData
|
|
h += line + space; // buttonColor
|
|
h += line + space; // buttonSprite
|
|
break;
|
|
|
|
case SettingValueType.OptionPicker:
|
|
h += line + space; // section title
|
|
var optionsProp = property.FindPropertyRelative("options");
|
|
h += HeightOf(optionsProp, true) + space; // options list
|
|
h += line + space; // defaultOptionIndex
|
|
break;
|
|
}
|
|
|
|
// Apply section title
|
|
h += line + space;
|
|
h += HeightOf(applyProp) + space;
|
|
|
|
ApplyTarget apply = (ApplyTarget)applyProp.enumValueIndex;
|
|
if (apply == ApplyTarget.Audio)
|
|
{
|
|
h += line + space; // audioTargetType
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(keyProp.stringValue))
|
|
h += line * 1.4f + space;
|
|
|
|
return h + 6f;
|
|
}
|
|
|
|
private static float HeightOf(SerializedProperty prop, bool includeChildren = false)
|
|
=> EditorGUI.GetPropertyHeight(prop, includeChildren);
|
|
|
|
private static void DrawProp(ref Rect r, SerializedProperty prop, string label, bool includeChildren = false)
|
|
{
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
GUIContent gc = new(label);
|
|
|
|
float h = EditorGUI.GetPropertyHeight(prop, gc, includeChildren);
|
|
Rect rect = new(r.x, r.y, r.width, h);
|
|
EditorGUI.PropertyField(rect, prop, gc, includeChildren);
|
|
r.y += h + space;
|
|
}
|
|
|
|
private static void DrawSectionTitle(ref Rect r, string title)
|
|
{
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
Rect rect = new(r.x, r.y, r.width, line);
|
|
EditorGUI.LabelField(rect, title, EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
}
|
|
|
|
private static void DrawMinMaxRow(ref Rect r, SerializedProperty leftProp, SerializedProperty rightProp, string leftLabel, string rightLabel)
|
|
{
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
float gap = 10f;
|
|
float half = (r.width - gap) * 0.5f;
|
|
|
|
Rect left = new(r.x, r.y, half, line);
|
|
Rect right = new(r.x + half + gap, r.y, half, line);
|
|
|
|
EditorGUI.PropertyField(left, leftProp, new GUIContent(leftLabel));
|
|
EditorGUI.PropertyField(right, rightProp, new GUIContent(rightLabel));
|
|
|
|
r.y += line + space;
|
|
}
|
|
|
|
private static void DrawFlagsRow(ref Rect r, SerializedProperty leftProp, SerializedProperty rightProp, string leftLabel, string rightLabel)
|
|
{
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
float gap = 10f;
|
|
float half = (r.width - gap) * 0.5f;
|
|
|
|
Rect left = new(r.x, r.y, half, line);
|
|
Rect right = new(r.x + half + gap, r.y, half, line);
|
|
|
|
// Shown in Settings
|
|
GUIContent leftContent = new GUIContent(leftLabel, "Показывать настройку в UI меню настроек");
|
|
EditorGUI.PropertyField(left, leftProp, leftContent);
|
|
|
|
// Exposed
|
|
GUIContent rightContent = new GUIContent(rightLabel, "Доступна для изменения извне (через API/файл)");
|
|
EditorGUI.PropertyField(right, rightProp, rightContent);
|
|
|
|
r.y += line + space;
|
|
}
|
|
|
|
private static string BuildHeader(string displayName, string key)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(displayName) && !string.IsNullOrWhiteSpace(key))
|
|
return $"{displayName} ({key})";
|
|
if (!string.IsNullOrWhiteSpace(displayName)) return displayName;
|
|
return !string.IsNullOrWhiteSpace(key) ? key : "Setting";
|
|
}
|
|
}
|
|
}
|
|
#endif
|