旧工作内容移动至示例
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23a5c2ef10b97d944a21755c6a5c520e
|
||||
guid: 7758a0679c9038144a4b0d007d44618f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
17
Samples/ConfigUIElement/Lrss3.ConfigUIElement.asmdef
Normal file
17
Samples/ConfigUIElement/Lrss3.ConfigUIElement.asmdef
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Lrss3.ConfigUIElement",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:b1727b829ae4f0641acc8ad28ed624c2"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25409440eb1d34849a42df21f5989356
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c9d6141c22cf274f80f6e2061c6f5c1
|
||||
guid: d53a566643e99d74292ec8e451eb7356
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
62
Samples/ConfigUIElement/Scripts/ConfigButton.cs
Normal file
62
Samples/ConfigUIElement/Scripts/ConfigButton.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
public class ConfigButton : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
public Button targetButton;
|
||||
|
||||
public override bool AllowInput
|
||||
{
|
||||
get => base.AllowInput;
|
||||
set
|
||||
{
|
||||
if (targetButton != null)
|
||||
targetButton.interactable = !value;
|
||||
base.AllowInput = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(newValue, forceSet);
|
||||
}
|
||||
|
||||
private bool _doOnce = false;
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
var name = component.transform.name;
|
||||
if (name is not "button") return;
|
||||
if (_doOnce)
|
||||
{
|
||||
Debug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>飺" + name);
|
||||
return;
|
||||
}
|
||||
if (component is Button button)
|
||||
{
|
||||
_doOnce = true;
|
||||
if (targetButton != null)
|
||||
targetButton = button;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigButton.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigButton.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73f7a373611d15741b1093e0669abea9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
153
Samples/ConfigUIElement/Scripts/ConfigDigitalInputField.cs
Normal file
153
Samples/ConfigUIElement/Scripts/ConfigDigitalInputField.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
/// <summary>
|
||||
/// һ<><D2BB><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ø<EFBFBD><C3B8><EFBFBD>ֵ<EFBFBD><D6B5>ΪĬ<CEAA><C4AC>
|
||||
/// </summary>
|
||||
public class ConfigDigitalInputField : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public float editorInput;
|
||||
#endif
|
||||
|
||||
public TMP_InputField targetInput;
|
||||
|
||||
public Button digitalAddButton;
|
||||
public Button digitalSubButton;
|
||||
|
||||
public double maxValue = 114514;
|
||||
public double minValue = -114515;
|
||||
public int digits = 6;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public double delta = 1;
|
||||
|
||||
public override bool AllowInput
|
||||
{
|
||||
get => base.AllowInput;
|
||||
set
|
||||
{
|
||||
if (targetInput != null)
|
||||
targetInput.readOnly = !value;
|
||||
if (digitalAddButton != null)
|
||||
digitalAddButton.interactable = value;
|
||||
if (digitalSubButton != null)
|
||||
digitalSubButton.interactable = value;
|
||||
base.AllowInput = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
#if UNITY_EDITOR
|
||||
if (targetInput != null)
|
||||
targetInput.text = editorInput.ToString();
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
if (ReferenceEquals(targetInput, null))
|
||||
{
|
||||
Debug.LogError($"{name}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>Ŀ<EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>Ԫ<EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>");
|
||||
return;
|
||||
}
|
||||
targetInput.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInput.onValueChanged.AddListener(o =>
|
||||
{
|
||||
double value = 0;
|
||||
if (double.TryParse(o, out value))
|
||||
{
|
||||
SetValue(value);
|
||||
}
|
||||
});
|
||||
targetInput.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
if (!ReferenceEquals(digitalAddButton, null))
|
||||
digitalAddButton.onClick.AddListener(delegate
|
||||
{
|
||||
SetValue(CastDigitalNumber(Value) + delta);
|
||||
RefreshFormatValue(Value);
|
||||
});
|
||||
if (!ReferenceEquals(digitalSubButton, null))
|
||||
digitalSubButton.onClick.AddListener(delegate
|
||||
{
|
||||
SetValue(CastDigitalNumber(Value) - delta);
|
||||
RefreshFormatValue(Value);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(CastDigitalNumber(newValue, minValue, maxValue, digits));
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(CastDigitalNumber(newValue, minValue, maxValue, digits), forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
|
||||
if (component is TMP_InputField inputField)
|
||||
{
|
||||
if (targetInput != null)
|
||||
targetInput = inputField;
|
||||
}
|
||||
else if(component is Button button)
|
||||
{
|
||||
var name = component.transform.name;
|
||||
switch (name)
|
||||
{
|
||||
case "subbutton":
|
||||
case "SubButton":
|
||||
if (digitalSubButton != null)
|
||||
digitalSubButton = button;
|
||||
break;
|
||||
case "addbutton":
|
||||
case "AddButton":
|
||||
if (digitalAddButton != null)
|
||||
digitalAddButton = button;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
targetInput.text = CastDigitalNumber(newValue).ToString(numberFormat);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d84fd414ac6743e46909249427b18364
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
78
Samples/ConfigUIElement/Scripts/ConfigDropdown.cs
Normal file
78
Samples/ConfigUIElement/Scripts/ConfigDropdown.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
public class ConfigDropdown : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
public TMP_Dropdown targetDropdown;
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
targetDropdown.onValueChanged.AddListener(index =>
|
||||
{
|
||||
SetValue(index);
|
||||
});
|
||||
}
|
||||
|
||||
public void InitializationDropdown(IEnumerable<string> options)
|
||||
{
|
||||
targetDropdown.options = options
|
||||
.Select(option => new TMP_Dropdown.OptionData(option)).ToList();
|
||||
targetDropdown.RefreshShownValue();
|
||||
if (IsValueInitNull)
|
||||
RefreshValueWithoutEvent(0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(CastIntNumber(newValue));
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(CastIntNumber(newValue), forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
var name = component.transform.name;
|
||||
if (name is not "dropdown") return;
|
||||
if (component is TMP_Dropdown dropdown)
|
||||
{
|
||||
if (targetDropdown != null)
|
||||
targetDropdown = dropdown;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
if (newValue == null)
|
||||
return;
|
||||
targetDropdown.value = CastIntNumber(newValue);
|
||||
targetDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigDropdown.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigDropdown.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 471d16b38f4449a46b9fcf5b312f65d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
712
Samples/ConfigUIElement/Scripts/ConfigSelectableItem.cs
Normal file
712
Samples/ConfigUIElement/Scripts/ConfigSelectableItem.cs
Normal file
@@ -0,0 +1,712 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using XericLibrary.Runtime.CustomEditor;
|
||||
using XericLibrary.Runtime.MacroLibrary;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
/// <summary>
|
||||
/// һ<><D2BB><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
|
||||
/// <code>
|
||||
/// <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD><CEAF><EFBFBD>ģ<DEB8><C4A3><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ȡ<EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״η<D7B4><CEB7><EFBFBD><EFBFBD>ı<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>м<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0>ֵ<EFBFBD><D6B5>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public abstract class ConfigSelectableItem : MonoBehaviour
|
||||
{
|
||||
#region <EFBFBD><EFBFBD>̬<EFBFBD>¼<EFBFBD>
|
||||
|
||||
private static event Action<bool, bool> ForceUpdateAllConfigEvent;
|
||||
/// <summary>
|
||||
/// ǿ<><C7BF><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>ij<EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1><EFBFBD>ⲿ<EFBFBD><E2B2BF><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
||||
/// </summary>
|
||||
/// <param name="resetDirty"></param>
|
||||
public static void ForceUpdateAll(bool resetDirty = false, bool forceSet = false)
|
||||
{
|
||||
ForceUpdateAllConfigEvent?.Invoke(resetDirty, forceSet);
|
||||
}
|
||||
|
||||
private static event Action ForceSetAllSourceValueEvent;
|
||||
/// <summary>
|
||||
/// ǿ<><C7BF><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>ij<EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>簴<EFBFBD><E7B0B4>Ӧ<EFBFBD>ð<EFBFBD>ťʱ<C5A5><CAB1>
|
||||
/// </summary>
|
||||
public static void ForceSetAllSourceValue()
|
||||
{
|
||||
ForceSetAllSourceValueEvent?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ֵ<EFBFBD><EFBFBD><EFBFBD>ʱ
|
||||
/// </summary>
|
||||
public static event Action<ConfigSelectableItem> OnAnyValueDirty;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD>յ<EFBFBD><D5B5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>ֵ
|
||||
/// </summary>
|
||||
public static event Action<ConfigSelectableItem, object> OnAnyValueChange;
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD>Ա
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD>״̬ʱ<CCAC><CAB1><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
private static readonly List<ConfigSelectableItem> ConfigItemList = new List<ConfigSelectableItem>();
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>Ч<EFBFBD><D0A7>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public static int ConfigItemListCount => ConfigItemList.Count;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static ConfigSelectableItem GetConfigItemByIndex(int index) => ConfigItemList[index];
|
||||
public static IEnumerable<ConfigSelectableItem> ConfigItemLists => ConfigItemList;
|
||||
|
||||
private static bool autoUpdateValueAll;
|
||||
/// <summary>
|
||||
/// <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
/// </summary>
|
||||
public static bool AutoUpdateValueAll
|
||||
{
|
||||
get => autoUpdateValueAll;
|
||||
set
|
||||
{
|
||||
foreach (var item in ConfigItemList)
|
||||
item.autoUpdateValue = value;
|
||||
autoUpdateValueAll = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ״̬
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ֵ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><DABA><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>ı仯
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD>ǿ<EFBFBD>ѡ<EFBFBD><D1A1>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><CCB7><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ұ<EFBFBD>OnValueChange<67><65><EFBFBD>磬<EFBFBD><E7A3AC><EFBFBD>ڸ<EFBFBD>λ֮ǰֻ<C7B0><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Ρ<EFBFBD>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Action<ConfigSelectableItem> OnValueDirty;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD>յ<EFBFBD><D5B5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>ֵ
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD>ǿ<EFBFBD>ѡ<EFBFBD><D1A1>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><CCB7><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>ˢ<EFBFBD>µĻ<C2B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еȴ<D0B5>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Action<ConfigSelectableItem, object> OnValueChange;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
|
||||
/// </summary>
|
||||
public event Action<ConfigSelectableItem, object> OnEndEdit;
|
||||
/// <summary>
|
||||
/// <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ֵ
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD>DZ<EFBFBD>Ҫ<EFBFBD><D2AA>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2><EFBFBD>¼<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD>ⲿ<EFBFBD><E2B2BF>ֵ<EFBFBD>趨<EFBFBD><E8B6A8><EFBFBD>ˡ<EFBFBD>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Func<ConfigSelectableItem, object> GetSourceValue;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD>DZ<EFBFBD>Ҫ<EFBFBD><D2AA>
|
||||
/// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ForceSetAllSourceValue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD>˴<EFBFBD><CBB4>Ľ<EFBFBD><C4BD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
/// <20><><EFBFBD>棺<EFBFBD><E6A3BA>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ForceSetAllSourceValue<75><65>SetSourceValueRequest<73>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>Լ<EFBFBD><D4BC>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Action<ConfigSelectableItem, object> SetSourceValue;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ǰ<EFBFBD><C7B0><EFBFBD>Ե<EFBFBD><D4B5>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>д<EFBFBD><D0B4><EFBFBD>Toggleʱ(<28><>ӦautoUpdateValueToggle<6C><65>Ŀ)
|
||||
/// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ⲿ<EFBFBD><E2B2BF>ֵ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ѡֵ<D1A1>趨<EFBFBD><E8B6A8><EFBFBD><EFBFBD>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Func<ConfigSelectableItem, bool> GetSourceValueAutoUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ǰ<EFBFBD><C7B0><EFBFBD>Ե<EFBFBD><D4B5>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// <code>
|
||||
/// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>д<EFBFBD><D0B4><EFBFBD>Toggleʱ(<28><>ӦautoUpdateValueToggle<6C><65>Ŀ)
|
||||
/// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>ⲿ<EFBFBD><E2B2BF><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ѡֵ<D1A1>趨<EFBFBD><E8B6A8><EFBFBD><EFBFBD>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public event Action<bool> SetSourceValueAutoUpdate;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(<28><>ֵӦ<D6B5>õ<EFBFBD><C3B5>Ĵ<EFBFBD><C4B4><EFBFBD>)
|
||||
/// </summary>
|
||||
public void SetSourceValueRequest()
|
||||
{
|
||||
SetSourceValue?.Invoke(this, Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀ<EFBFBD><C4BF>Ӧ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>tag
|
||||
/// </summary>
|
||||
[Rename("ӳ<><D3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
public string configTag;
|
||||
|
||||
/// <summary>
|
||||
/// <20>趨<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Ч<EFBFBD><D0A7>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Rename("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private bool allowInput = true;
|
||||
|
||||
/// <summary>
|
||||
/// <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Rename("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private bool autoUpdateValue = true;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>£<EFBFBD><C2A3><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>״̬ѡ<CCAC><D1A1><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Rename("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private bool allowBlockUpdate = true;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>£<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ɳ<EFBFBD><C9B3><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Rename("<22><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private bool forceBlockUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ʽ<EFBFBD><CABD><EFBFBD>ı<EFBFBD>
|
||||
/// </summary>
|
||||
public string numberFormat = "0.##";
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public TextMeshProUGUI titleLabel;
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField]
|
||||
#endif
|
||||
private string titleTextContext;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public TextMeshProUGUI helpLabel;
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField]
|
||||
#endif
|
||||
private string helpTextContext;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>λ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public TextMeshProUGUI unitLabel;
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField]
|
||||
#endif
|
||||
private string unitTextContext;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀǰ<C4BF><C7B0>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>autoUpdateValue<75><65>Ӧ
|
||||
/// </summary>
|
||||
[Rename("<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>״̬ѡ<CCAC><D1A1>")]
|
||||
public Toggle autoUpdateValueToggle;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>תѡ<D7AA><D1A1>״̬
|
||||
/// </summary>
|
||||
[Rename("<22><>ת<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>°<EFBFBD>ť״̬")]
|
||||
public bool autoUpdateValueToggleReversalState;
|
||||
|
||||
[Rename("<22><>ת<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>״̬")]
|
||||
public bool autoUpdateValueReversalState;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>λ<EFBFBD><CEBB>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>¿<EFBFBD><C2BF><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>״̬
|
||||
/// </summary>
|
||||
[Rename("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>λ")]
|
||||
public bool dirtyAutoReset = false;
|
||||
|
||||
// ==== <20><><EFBFBD><EFBFBD> ==== //
|
||||
|
||||
/// <summary>
|
||||
/// <20>趨<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
|
||||
/// </summary>
|
||||
public virtual bool AllowInput
|
||||
{
|
||||
get => allowInput;
|
||||
set => allowInput = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>ʼ<EFBFBD><CABC>
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public bool IsValueInitNull { get; private set; } = true;
|
||||
|
||||
// [Obsolete("<22><>ʹ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private bool _isDirty;
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1>ǣ<EFBFBD><C7A3>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й㲥
|
||||
/// </summary>
|
||||
private bool IsDirty
|
||||
{
|
||||
get => _isDirty;
|
||||
set
|
||||
{
|
||||
if (_isDirty)
|
||||
{
|
||||
if (!value)
|
||||
_isDirty = false;
|
||||
return;
|
||||
}
|
||||
if (!value) return;
|
||||
|
||||
_isDirty = true;
|
||||
OnAnyValueDirty?.Invoke(this);
|
||||
OnValueDirty?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>趨<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>ѡ<EFBFBD><D1A1>
|
||||
/// <code>
|
||||
/// Ϊ<><CEAA><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4>Ǻ<EFBFBD><C7BA>ⲿ<EFBFBD>ݴ<EFBFBD>ֵһ<D6B5>£<EFBFBD>
|
||||
/// <20>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>״̬<D7B4>ı<EFBFBD><EFBFBD><D7BC><EFBFBD>ʡ<EFBFBD>
|
||||
///
|
||||
/// <20><><EFBFBD>ʽ<EFBFBD><CABD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2B2BBBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
|
||||
/// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD>ô˷<C3B4><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿͨѶӦ<D1B6><D3A6>ʹ<EFBFBD><CAB9><EFBFBD>ֶΡ<D6B6>
|
||||
///
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>ж<EFBFBD>״̬תΪ<D7AA><CEAA><EFBFBD><EFBFBD>״̬<D7B4><CCAC>
|
||||
/// Ӧ<><D3A6><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>autoUpdateValueReversalStateתΪ<D7AA>ݴ<EFBFBD>ֵ<EFBFBD><D6B5>
|
||||
/// Ȼ<><C8BB><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>autoUpdateValueToggleReversalStateתΪ<D7AA><CEAA><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public bool AutoUpdateValue
|
||||
{
|
||||
get => autoUpdateValueReversalState ^ autoUpdateValue;
|
||||
set
|
||||
{
|
||||
autoUpdateValue = value;
|
||||
if (autoUpdateValueToggle != null)
|
||||
autoUpdateValueToggle.isOn = autoUpdateValueToggleReversalState ^ value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>趨<EFBFBD><E8B6A8><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public bool ForceBlockUpdate
|
||||
{
|
||||
get => forceBlockUpdate;
|
||||
set => forceBlockUpdate = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public string TitleName
|
||||
{
|
||||
get => titleLabel.text;
|
||||
set => titleLabel.text = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>ʾ<EFBFBD><CABE>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>ʾ
|
||||
/// </summary>
|
||||
public string HelpName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (helpLabel != null) return helpLabel.text;
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (helpLabel != null)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
helpLabel.text = value;
|
||||
helpLabel.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
helpLabel.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string UnitName
|
||||
{
|
||||
get => unitLabel.text;
|
||||
set => unitLabel.text = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
// [Obsolete("<22><>ʹ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
private object _value;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ŀֵ
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get => _value;
|
||||
protected set
|
||||
{
|
||||
if (IsValueInitNull && value != null)
|
||||
IsValueInitNull = false;
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// ==== <20>ݴ<EFBFBD> ==== //
|
||||
|
||||
public FieldInfo FieldInfo;
|
||||
|
||||
public Type FieldType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (titleLabel != null)
|
||||
TitleName = titleTextContext;
|
||||
if (helpLabel != null)
|
||||
HelpName = helpTextContext;
|
||||
if (unitLabel != null)
|
||||
UnitName = unitTextContext;
|
||||
}
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
foreach (var child in transform.GetChildren())
|
||||
{
|
||||
var component = child.GetComponent<UIBehaviour>();
|
||||
if (component != null)
|
||||
Initialization_ChildConstruction(component);
|
||||
}
|
||||
|
||||
Initialization_EventBinding();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
ConfigItemList.Add(this);
|
||||
ForceUpdateAllConfigEvent += ForceUpdate;
|
||||
ForceSetAllSourceValueEvent += SetSourceValueRequest;
|
||||
|
||||
if (dirtyAutoReset)
|
||||
IsDirty = false;
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
ConfigItemList.Remove(this);
|
||||
ForceUpdateAllConfigEvent -= ForceUpdate;
|
||||
ForceSetAllSourceValueEvent -= SetSourceValueRequest;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
ForceUpdate(true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (IsValueInitNull || (AutoUpdateValue && !(allowBlockUpdate && forceBlockUpdate)))
|
||||
{
|
||||
ForceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
ForceUpdateAllConfigEvent -= ForceUpdate;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>
|
||||
|
||||
protected static double CastDigitalNumber(object newValue)
|
||||
{
|
||||
if (double.TryParse(newValue.ToString(), out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>ֵǯ<D6B5><C7AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룩
|
||||
/// </summary>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="minValue"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
/// <param name="digits"></param>
|
||||
/// <returns></returns>
|
||||
protected static double CastDigitalNumber(object newValue, double minValue, double maxValue, int digits)
|
||||
{
|
||||
// var resultValue = newValue switch
|
||||
// {
|
||||
// bool boolValue => boolValue ? 1 : 0,
|
||||
// short intValue => intValue,
|
||||
// int intValue => intValue,
|
||||
// long intValue => intValue,
|
||||
// float floatValue => Math.Round(floatValue, digits),
|
||||
// double doubleValue => Math.Round(doubleValue, digits),
|
||||
// _ => 0
|
||||
// };
|
||||
#if UNITY_EDITOR
|
||||
if (newValue == null)
|
||||
{
|
||||
Debug.LogError($"<22><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:Ŀ<><C4BF><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD>ֵʱ<D6B5><CAB1>ǰ<EFBFBD>˳<EFBFBD>");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (double.TryParse(newValue.ToString(), out var value))
|
||||
{
|
||||
var resultValue = Math.Round(value, digits);
|
||||
return Math.Clamp(resultValue, minValue, maxValue);
|
||||
}
|
||||
Debug.LogError($"<22><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:{newValue}<7D><><EFBFBD>ܲ<EFBFBD><DCB2><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>ֵ");
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected static int CastIntNumber(object newValue)
|
||||
{
|
||||
var resultValue = Convert.ToInt32(newValue);
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
protected static Vector2 CastVector2(object newValue)
|
||||
{
|
||||
return newValue switch
|
||||
{
|
||||
Vector2 vec2Value => vec2Value,
|
||||
System.Numerics.Vector2 sysVec2Value => new Vector2(sysVec2Value.X, sysVec2Value.Y),
|
||||
_ => Vector2.zero
|
||||
};
|
||||
}
|
||||
|
||||
protected static Vector3 CastVector3(object newValue)
|
||||
{
|
||||
return newValue switch
|
||||
{
|
||||
Vector3 vec3Value => vec3Value,
|
||||
System.Numerics.Vector3 sysVec3Value => new Vector3(sysVec3Value.X, sysVec3Value.Y, sysVec3Value.Z),
|
||||
_ => Vector3.zero
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ѡ<EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
||||
/// </summary>
|
||||
/// <param name="autoUpdateValue"><3E>趨<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
protected void Initialization(bool autoUpdateValue = true)
|
||||
{
|
||||
AutoUpdateValue = autoUpdateValue;
|
||||
}
|
||||
|
||||
private bool _doOnce = false;
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3>ڳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ͨ<EFBFBD><CDA8>ʶ<EFBFBD><CAB6><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
protected virtual void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
// <20><><EFBFBD>ٽڵ<D9BD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
var name = component.gameObject.name;
|
||||
// <20><>ʼ<EFBFBD><CABC><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>¶Թ<C2B6>
|
||||
if (name == "toggle" && component is Toggle toggle)
|
||||
{
|
||||
if (autoUpdateValueToggle == null)
|
||||
autoUpdateValueToggle = toggle;
|
||||
return;
|
||||
}
|
||||
if (name is not ("title" or "name")) return;
|
||||
if (_doOnce)
|
||||
{
|
||||
Debug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>飺" + name);
|
||||
return;
|
||||
}
|
||||
if (component is TextMeshProUGUI textMeshProUGUI)
|
||||
{
|
||||
_doOnce = true;
|
||||
if (titleLabel != null)
|
||||
titleLabel = textMeshProUGUI;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>̬<EFBFBD>İ<F3B6A8B5><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
protected virtual void Initialization_EventBinding()
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><CEA3>¼<EFBFBD><C2BC><EFBFBD>Ҫ<EFBFBD><D2AA>ע<EFBFBD><D7A2>
|
||||
if (autoUpdateValueToggle != null)
|
||||
{
|
||||
autoUpdateValueToggle.onValueChanged.AddListener(a =>
|
||||
{
|
||||
autoUpdateValue = autoUpdateValueToggleReversalState ^ a;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ֶ<EFBFBD>
|
||||
SetSourceValueAutoUpdate?.Invoke(autoUpdateValue);
|
||||
// <20><><EFBFBD>ܲ<EFBFBD><DCB2><EFBFBD><EFBFBD><EFBFBD>
|
||||
// OnValueDirty?.Invoke(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>º<EFBFBD><C2BA><EFBFBD>
|
||||
/// <code>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>̵<EFBFBD><CCB5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>ˢ<EFBFBD><CBA2><EFBFBD><EFBFBD><EFBFBD>еĹ<D0B5><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2B2BBBB><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>Ϊ<EFBFBD><CEAA>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ӱ<EFBFBD><D3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̲<EFBFBD><CCB2><EFBFBD>ֵ<EFBFBD><D6B5>ȡ<EFBFBD>ص<EFBFBD><D8B5><EFBFBD>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public virtual void ForceUpdate(bool resetDirty = false, bool forceSet = false)
|
||||
{
|
||||
if (resetDirty)
|
||||
IsDirty = false;
|
||||
var value = GetSourceValue?.Invoke(this);
|
||||
if (value == null)
|
||||
return ;
|
||||
RefreshValueWithoutEvent(value, forceSet);
|
||||
RefreshAutoUpdateValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>ɽ<EFBFBD><C9BD>淢<EFBFBD><E6B7A2><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="newValue"></param>
|
||||
protected virtual void SetValue(object newValue)
|
||||
{
|
||||
if (Value == newValue)
|
||||
return;
|
||||
var lastValue = Value;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD>λΪ<CEBB><CEAA><EFBFBD>ڵ<EFBFBD>ֵ
|
||||
if (!allowInput)
|
||||
RefreshValueWithoutEvent(Value);
|
||||
else
|
||||
{
|
||||
Value = newValue;
|
||||
IsDirty = true;
|
||||
|
||||
OnAnyValueChange?.Invoke(this, lastValue);
|
||||
OnValueChange?.Invoke(this, lastValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ý<EFBFBD><C3BD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>¡<EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="forceSet"></param>
|
||||
public virtual void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
if (!AutoUpdateValue && !forceSet)
|
||||
return;
|
||||
if (newValue == null)
|
||||
return;
|
||||
if (Value != null && (Value.ToString() == newValue.ToString()))
|
||||
return;
|
||||
Value = newValue;
|
||||
RefreshFormatValue(newValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>״̬
|
||||
/// </summary>
|
||||
protected void RefreshAutoUpdateValue()
|
||||
{
|
||||
var isSourceValueAutoUpdate = GetSourceValueAutoUpdate?.Invoke(this);
|
||||
if (isSourceValueAutoUpdate != null)
|
||||
AutoUpdateValue = isSourceValueAutoUpdate.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ˢ<>¸<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>ˢ<EFBFBD><CBA2>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
protected virtual void RefreshFormatValue(object newValue)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void WhenStartEdit()
|
||||
{
|
||||
// Debug.Log("<22><>ʼ<EFBFBD>༭");
|
||||
ForceBlockUpdate = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><F2BDB9B5>Ƴ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>á<EFBFBD>
|
||||
/// </summary>
|
||||
protected void WhenEndEdit()
|
||||
{
|
||||
// Debug.Log("<22><><EFBFBD><EFBFBD><EFBFBD>༭");
|
||||
ForceBlockUpdate = false;
|
||||
OnEndEdit?.Invoke(this, Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>趨
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>¸<EFBFBD>ѡ<EFBFBD><EFBFBD><F2A3ACB2>趨<EFBFBD><E8B6A8>ǰ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="autoUpdateValue"></param>
|
||||
public void DestroyAutoUpdateValue(bool autoUpdateValue)
|
||||
{
|
||||
Destroy(autoUpdateValueToggle.gameObject);
|
||||
this.autoUpdateValue = autoUpdateValueReversalState ^ autoUpdateValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigSelectableItem.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigSelectableItem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e3c729eeb8e03f459a9c95dc6e239d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
100
Samples/ConfigUIElement/Scripts/ConfigTextInputField.cs
Normal file
100
Samples/ConfigUIElement/Scripts/ConfigTextInputField.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
/// <summary>
|
||||
/// һ<><D2BB><EFBFBD><EFBFBD>ͨ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public class ConfigTextInputField : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public string editorInput;
|
||||
#endif
|
||||
|
||||
public TMP_InputField targetInput;
|
||||
|
||||
|
||||
public override bool AllowInput
|
||||
{
|
||||
get => base.AllowInput;
|
||||
set
|
||||
{
|
||||
if (targetInput != null)
|
||||
targetInput.readOnly = !value;
|
||||
base.AllowInput = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
#if UNITY_EDITOR
|
||||
if (targetInput != null)
|
||||
targetInput.text = editorInput;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
targetInput.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInput.onValueChanged.AddListener(o =>
|
||||
{
|
||||
if(double.TryParse(o, out var value))
|
||||
SetValue(value);
|
||||
});
|
||||
targetInput.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(newValue);
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(newValue, forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
if (component is TMP_InputField inputField)
|
||||
{
|
||||
if (targetInput != null)
|
||||
targetInput = inputField;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
targetInput.text = newValue.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigTextInputField.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigTextInputField.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9b27b4ed9920c947b157c1d7702372c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
86
Samples/ConfigUIElement/Scripts/ConfigToggleGroup.cs
Normal file
86
Samples/ConfigUIElement/Scripts/ConfigToggleGroup.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>Ч<EFBFBD><D0A7>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊֵ<CEAA><D6B5>
|
||||
/// </summary>
|
||||
public class ConfigToggleGroup : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
public ToggleGroup targetToggle;
|
||||
|
||||
public List<Toggle> toggles;
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
for (int i = 0; i < toggles.Count; i++)
|
||||
{
|
||||
void BuildInGroupInit()
|
||||
{
|
||||
var index = i;
|
||||
var toggle = toggles[i];
|
||||
toggle.onValueChanged.AddListener(a =>
|
||||
{
|
||||
if (a)
|
||||
SetValue(index);
|
||||
});
|
||||
}
|
||||
BuildInGroupInit();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(CastIntNumber(newValue));
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(CastIntNumber(newValue), forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
if (component is Toggle toggle &&
|
||||
!toggles.Contains(toggle))
|
||||
toggles.Add(toggle);
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
var newIndex = CastIntNumber(newValue);
|
||||
// var index = 0;
|
||||
// foreach (var toggle in targetToggle.ActiveToggles())
|
||||
// {
|
||||
// if (newIndex != index++)
|
||||
// continue;
|
||||
// toggle.isOn = true;
|
||||
// Debug.Log(TitleName +":<3A><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD>Ŀ");
|
||||
// }
|
||||
toggles[newIndex].SetIsOnWithoutNotify(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigToggleGroup.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigToggleGroup.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b1b61fd3a211734eb3d51cedcbe579f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class ConfigTypeOverrideAttribute : PropertyAttribute
|
||||
{
|
||||
public readonly string TypeName;
|
||||
|
||||
public ConfigTypeOverrideAttribute(string name)
|
||||
{
|
||||
TypeName = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>е<EFBFBD>rename<6D><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="field"></param>
|
||||
/// <param name="name">ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>Ϊԭ<CEAA><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <returns><3E>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></returns>
|
||||
public static bool TryGetMemberName(FieldInfo field, out string name)
|
||||
{
|
||||
if (field.GetCustomAttribute(typeof(ConfigTypeOverrideAttribute)) is ConfigTypeOverrideAttribute rename)
|
||||
{
|
||||
name = rename.TypeName;
|
||||
return true;
|
||||
}
|
||||
|
||||
name = field.FieldType.Name;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a130623ae66ff564a9e14580549d2858
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
129
Samples/ConfigUIElement/Scripts/ConfigVec2InputField.cs
Normal file
129
Samples/ConfigUIElement/Scripts/ConfigVec2InputField.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
public class ConfigVec2InputField : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public Vector2 editorInput;
|
||||
#endif
|
||||
|
||||
public TMP_InputField targetInputX;
|
||||
public TMP_InputField targetInputY;
|
||||
|
||||
public override bool AllowInput
|
||||
{
|
||||
get => base.AllowInput;
|
||||
set
|
||||
{
|
||||
if (targetInputX != null)
|
||||
targetInputX.readOnly = !value;
|
||||
if (targetInputY != null)
|
||||
targetInputY.readOnly = value;
|
||||
base.AllowInput = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
#if UNITY_EDITOR
|
||||
if (targetInputX != null)
|
||||
targetInputX.text = editorInput.x.ToString();
|
||||
if (targetInputY != null)
|
||||
targetInputY.text = editorInput.y.ToString();
|
||||
#endif
|
||||
}
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
targetInputX.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInputY.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInputX.onValueChanged.AddListener(a =>
|
||||
{
|
||||
var value = CastVector3(Value);
|
||||
value.x = float.Parse(a);
|
||||
SetValue(value);
|
||||
});
|
||||
targetInputY.onValueChanged.AddListener(a =>
|
||||
{
|
||||
var value = CastVector3(Value);
|
||||
value.y = float.Parse(a);
|
||||
SetValue(value);
|
||||
});
|
||||
targetInputX.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
targetInputY.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(CastVector2(newValue));
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(CastVector2(newValue), forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
var name = component.transform.name;
|
||||
if (component is not TMP_InputField inputField)
|
||||
return;
|
||||
switch (name)
|
||||
{
|
||||
case "inputx":
|
||||
case "inputX":
|
||||
if (targetInputX != null)
|
||||
targetInputX = inputField;
|
||||
break;
|
||||
case "inputy":
|
||||
case "inputY":
|
||||
if (targetInputY != null)
|
||||
targetInputY = inputField;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
var value = CastVector2(newValue);
|
||||
targetInputX.text = value.x.ToString(numberFormat);
|
||||
targetInputY.text = value.y.ToString(numberFormat);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigVec2InputField.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigVec2InputField.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 118ff8f18137da54087c6d572fc5db75
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
158
Samples/ConfigUIElement/Scripts/ConfigVec3InputField.cs
Normal file
158
Samples/ConfigUIElement/Scripts/ConfigVec3InputField.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace LRC
|
||||
{
|
||||
|
||||
public class ConfigVec3InputField : ConfigSelectableItem
|
||||
{
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public Vector3 editorInput;
|
||||
#endif
|
||||
|
||||
public TMP_InputField targetInputX;
|
||||
public TMP_InputField targetInputY;
|
||||
public TMP_InputField targetInputZ;
|
||||
|
||||
public override bool AllowInput
|
||||
{
|
||||
get => base.AllowInput;
|
||||
set
|
||||
{
|
||||
if (targetInputX != null)
|
||||
targetInputX.readOnly = !value;
|
||||
if (targetInputY != null)
|
||||
targetInputY.readOnly = value;
|
||||
if (targetInputZ != null)
|
||||
targetInputZ.readOnly = value;
|
||||
base.AllowInput = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
#if UNITY_EDITOR
|
||||
if (targetInputX != null)
|
||||
targetInputX.text = editorInput.x.ToString();
|
||||
if (targetInputY != null)
|
||||
targetInputY.text = editorInput.y.ToString();
|
||||
if (targetInputZ != null)
|
||||
targetInputZ.text = editorInput.z.ToString();
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
targetInputX.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInputY.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInputZ.onSelect.AddListener(a =>
|
||||
{
|
||||
WhenStartEdit();
|
||||
});
|
||||
targetInputX.onValueChanged.AddListener(a =>
|
||||
{
|
||||
var value = CastVector3(Value);
|
||||
value.x = float.Parse(a);
|
||||
SetValue(value);
|
||||
});
|
||||
targetInputY.onValueChanged.AddListener(a =>
|
||||
{
|
||||
var value = CastVector3(Value);
|
||||
value.y = float.Parse(a);
|
||||
SetValue(value);
|
||||
});
|
||||
targetInputZ.onValueChanged.AddListener(a =>
|
||||
{
|
||||
var value = CastVector3(Value);
|
||||
value.z = float.Parse(a);
|
||||
SetValue(value);
|
||||
});
|
||||
targetInputX.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
targetInputY.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
targetInputZ.onEndEdit.AddListener(delegate
|
||||
{
|
||||
WhenEndEdit();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ʵ<EFBFBD><EFBFBD>
|
||||
|
||||
protected override void SetValue(object newValue)
|
||||
{
|
||||
base.SetValue(CastVector3(newValue));
|
||||
}
|
||||
|
||||
public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false)
|
||||
{
|
||||
base.RefreshValueWithoutEvent(CastVector3(newValue), forceSet);
|
||||
}
|
||||
|
||||
protected override void Initialization_ChildConstruction(UIBehaviour component)
|
||||
{
|
||||
base.Initialization_ChildConstruction(component);
|
||||
|
||||
var name = component.transform.name;
|
||||
if (component is not TMP_InputField inputField)
|
||||
return;
|
||||
switch (name)
|
||||
{
|
||||
case "inputx":
|
||||
case "inputX":
|
||||
if (targetInputX != null)
|
||||
targetInputX = inputField;
|
||||
break;
|
||||
case "inputy":
|
||||
case "inputY":
|
||||
if (targetInputY != null)
|
||||
targetInputY = inputField;
|
||||
break;
|
||||
case "inputz":
|
||||
case "inputZ":
|
||||
if (targetInputZ != null)
|
||||
targetInputZ = inputField;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RefreshFormatValue(object newValue)
|
||||
{
|
||||
base.RefreshFormatValue(newValue);
|
||||
var value = CastVector3(newValue);
|
||||
targetInputX.text = value.x.ToString(numberFormat);
|
||||
targetInputY.text = value.y.ToString(numberFormat);
|
||||
targetInputZ.text = value.z.ToString(numberFormat);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Samples/ConfigUIElement/Scripts/ConfigVec3InputField.cs.meta
Normal file
11
Samples/ConfigUIElement/Scripts/ConfigVec3InputField.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6e1779348dcc2b48a6f009b828e9b5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ffb2362d770a7f49b6ef2ddf8487343
|
||||
guid: bce0f9a72c71a9a4c9e79c61ee4a4bf8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 557f21129700c2640b88cafb45f16ee1
|
||||
guid: 9e2d9409c1fef764fa5d423dda5b3cfe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
12
package.json
12
package.json
@@ -5,11 +5,17 @@
|
||||
"unity": "2021.3",
|
||||
"description": "这是一个规范基础用例的扩展库,主要提供以下功能\r\n\r\n▪ 编程支持:函数平滑、多项式计算、权重拟合、过程分级、工业控制、曲线绘制、路径设置、对象控制、迭代扩展、空间变换、独特结构、文本格式、类型转换、机器编码、开发调试、动态生成、几何创建、快速池化、导航寻路、隔离控制、隔离输入、语义化委托、反射超驰、数学常数、单位换算、排序算法、程序调用、网络连接等。\r\n\r\n▪常用脚本:游戏交互、界面适配、弱扩展、绘制工厂、SQL扩展。\r\n\r\n▪编辑器界面:AI对话(Deepseek)、脚本蓝图(需要XericBlueprintGraph)、蓝图UI搭建(需要XericUIGraph)、调试工具集(需要Digital Twin Tool)\r\n\r\n需要注意:插件内如果涉及多平台切换,可能会提供多种自动或手动的切换方案,或默认使用windows平台,请注意辨别。\r\n\r\n建议添加ODin插件,便于呈现更多界面功能。\r\n\r\n更多详细内容说明请翻阅README文档,由于插件内含操作较多,手册存在缺漏,部分说明内容仍需完善,还请见谅。\r\n如果发现任何问题,包括版本兼容性,计算错误,调用错误,使用问题,都可以通过发布页Issues或其他联系方式找我获得帮助。",
|
||||
"type": "library",
|
||||
"hideInEditor": false,
|
||||
"samples": [
|
||||
{
|
||||
"displayName": "空示例",
|
||||
"description": "这个人很懒……",
|
||||
"path": "Samples~/Example"
|
||||
"displayName": "自动化配置界面UI",
|
||||
"description": "适用于自动化菜单界面生成的解决方案",
|
||||
"path": "Samples~/ConfigUIElement"
|
||||
},
|
||||
{
|
||||
"displayName": "轨迹线路预设脚本",
|
||||
"description": "适用于平面线路绘制及导航的一种解决方案",
|
||||
"path": "Samples~/HorizonLineOrbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user