Files
crtr/Assets/Cryville/Common/Unity/PropItem.cs
2023-03-26 23:25:20 +08:00

146 lines
4.3 KiB
C#

using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Cryville.Common.Unity {
public class PropItem : MonoBehaviour {
public object Target;
public PropertyEditor editor;
public DirectoryInfo ContextPath;
public string PropertyName = "";
InputField valueObj;
string value;
string desc = "";
PropertyInfo prop;
Type bindToType;
TypeConverter converter;
bool mustExpand = false;
bool readOnly = false;
string[] filter = null;
FileDialog fdialog;
#pragma warning disable IDE0051
void Awake() {
transform.Find("Value").GetComponent<InputField>().onEndEdit.AddListener(s => OnValueChanged(s));
var entry = new EventTrigger.Entry(){
eventID = EventTriggerType.PointerClick,
callback = new EventTrigger.TriggerEvent()
};
entry.callback.AddListener(e => OnClick(e));
transform.Find("Value").GetComponent<EventTrigger>().triggers.Add(entry);
}
void Start() {
transform.Find("Name").GetComponent<Text>().text = PropertyName;
valueObj = transform.Find("Value").GetComponent<InputField>();
prop = Target.GetType().GetProperty(PropertyName);
bindToType = prop.PropertyType;
converter = TypeDescriptor.GetConverter(bindToType);
var descattr = (DescriptionAttribute[])prop.GetCustomAttributes(typeof(DescriptionAttribute), true);
if (descattr.Length > 0) desc = descattr[0].Description;
var roattr = (ReadOnlyAttribute[])prop.GetCustomAttributes(typeof(ReadOnlyAttribute), true);
if (roattr.Length > 0) if (roattr[0].IsReadOnly == true) {
readOnly = true;
valueObj.enabled = false;
valueObj.transform.Find("ValueString").GetComponent<Text>().color = Color.gray;
}
if (converter == null || !converter.CanConvertFrom(typeof(string)) || converter.GetPropertiesSupported()){
mustExpand = true;
valueObj.enabled = false;
}
var fsattr = (FileStringAttribute[])prop.GetCustomAttributes(typeof(FileStringAttribute), true);
if (fsattr.Length > 0) {
valueObj.enabled = false;
filter = fsattr[0].Filter;
}
UpdateValue();
}
#pragma warning restore IDE0051
void OnFileDialogClosed() {
var file = fdialog.GetComponent<FileDialog>().FileName;
if (file != "") {
var f = new FileInfo(file);
if (f.Directory.FullName != ContextPath.FullName) {
string targetFile = ContextPath.FullName + "\\" + f.Name;
f.CopyTo(targetFile, true);
}
OnValueChanged(f.Name);
}
}
void UpdateValue() {
object v;
valueObj.placeholder.GetComponent<Text>().text = "";
v = prop.GetValue(Target, new object[]{ });
if (v == null) {
DefaultValueAttribute[] defvattr = (DefaultValueAttribute[])prop.GetCustomAttributes(typeof(DefaultValueAttribute), true);
if (defvattr.Length > 0) {
v = defvattr[0].Value;
if (v == null) {
v = "";
valueObj.placeholder.GetComponent<Text>().text = "null";
}
}
else {
v = "";
valueObj.placeholder.GetComponent<Text>().text = "null";
}
}
if (mustExpand || readOnly || filter != null) {
valueObj.transform.Find("ValueString").GetComponent<Text>().text = v.ToString();
}
else {
valueObj.text = v.ToString();
}
value = valueObj.text;
}
void OnClick(BaseEventData e) {
if (mustExpand && !readOnly) {
GameObject subeditor = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/PropertyEditor"));
object obj = prop.GetValue(Target, new object[]{ });
subeditor.GetComponent<PropertyEditor>().TargetObject = obj;
}
else if (filter != null && !readOnly) {
fdialog = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/FileDialog")).GetComponent<FileDialog>();
fdialog.Filter = filter;
fdialog.CurrentDirectory = ContextPath;
fdialog.OnClose += OnFileDialogClosed;
}
editor.SetDescription(PropertyName, desc);
UpdateValue();
}
void OnValueChanged(string s) {
if (s == value) return;
object v = null;
if (!(mustExpand || readOnly)) {
try {
v = converter.ConvertFrom(s);
prop.SetValue(Target, v, new object[]{ });
}
catch (TargetInvocationException ex) {
// CallHelper.ShowMessageBox(ex.InnerException.Message);
}
catch (Exception ex) {
// CallHelper.ShowMessageBox(ex.Message);
}
}
UpdateValue();
}
}
}