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().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().triggers.Add(entry); } void Start() { transform.Find("Name").GetComponent().text = PropertyName; valueObj = transform.Find("Value").GetComponent(); 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().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().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 = ""; 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 = "null"; } } else { v = ""; valueObj.placeholder.GetComponent().text = "null"; } } if (mustExpand || readOnly || filter != null) { valueObj.transform.Find("ValueString").GetComponent().text = v.ToString(); } else { valueObj.text = v.ToString(); } value = valueObj.text; } void OnClick(BaseEventData e) { if (mustExpand && !readOnly) { GameObject subeditor = GameObject.Instantiate(Resources.Load("Common/PropertyEditor")); object obj = prop.GetValue(Target, new object[]{ }); subeditor.GetComponent().TargetObject = obj; } else if (filter != null && !readOnly) { fdialog = GameObject.Instantiate(Resources.Load("Common/FileDialog")).GetComponent(); 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(); } } }