You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

247 lines
9.1 KiB

using System;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.VFX.UIElements;
using Type = System.Type;
using EnumField = UnityEditor.VFX.UIElements.VFXEnumField;
namespace UnityEditor.VFX
{
interface IStringProvider
{
string[] GetAvailableString();
}
interface IVFXModelStringProvider
{
string[] GetAvailableString(VFXModel model);
}
[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
class StringProviderAttribute : PropertyAttribute
{
public StringProviderAttribute(Type providerType)
{
if (!typeof(IStringProvider).IsAssignableFrom(providerType) && !typeof(IVFXModelStringProvider).IsAssignableFrom(providerType))
throw new InvalidCastException("StringProviderAttribute excepts a type which implements interface IStringProvider : " + providerType);
this.providerType = providerType;
}
public Type providerType { get; private set; }
}
interface IPushButtonBehavior
{
void OnClicked(string currentValue);
}
[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
class PushButtonAttribute : PropertyAttribute
{
public PushButtonAttribute(Type pushButtonProvider, string buttonName)
{
if (!typeof(IPushButtonBehavior).IsAssignableFrom(pushButtonProvider))
throw new InvalidCastException("PushButtonAttribute excepts a type which implements interface IPushButtonBehavior : " + pushButtonProvider);
this.pushButtonProvider = pushButtonProvider;
this.buttonName = buttonName;
}
public Type pushButtonProvider { get; private set; }
public string buttonName { get; private set; }
}
}
namespace UnityEditor.VFX.UI
{
class StringPropertyRM : SimplePropertyRM<string>
{
public StringPropertyRM(IPropertyRMProvider controller, float labelWidth) : base(controller, labelWidth)
{
}
public override float GetPreferredControlWidth()
{
return 140;
}
public static Func<string[]> FindStringProvider(VFXModel model, object[] customAttributes)
{
if (customAttributes != null)
{
foreach (var attribute in customAttributes)
{
if (attribute is StringProviderAttribute)
{
var instance = Activator.CreateInstance((attribute as StringProviderAttribute).providerType);
if (instance is IStringProvider stringProvider)
{
return () => stringProvider.GetAvailableString();
}
else if (model != null && instance is IVFXModelStringProvider modelStringProvider)
{
return () => modelStringProvider.GetAvailableString(model);
}
}
}
}
return null;
}
public struct StringPushButtonInfo
{
public Action<string> action;
public string buttonName;
}
public static StringPushButtonInfo FindPushButtonBehavior(object[] customAttributes)
{
if (customAttributes != null)
{
foreach (var attribute in customAttributes)
{
if (attribute is PushButtonAttribute)
{
var instance = Activator.CreateInstance((attribute as PushButtonAttribute).pushButtonProvider);
var pushButtonBehavior = instance as IPushButtonBehavior;
return new StringPushButtonInfo() { action = (a) => pushButtonBehavior.OnClicked(a), buttonName = (attribute as PushButtonAttribute).buttonName };
}
}
}
return new StringPushButtonInfo();
}
VFXStringField m_StringField;
VFXStringFieldPushButton m_StringFieldPushButton;
VFXStringFieldProvider m_StringFieldProvider;
protected override void UpdateIndeterminate()
{
if (m_StringField != null)
{
m_StringField.indeterminate = indeterminate;
}
}
public override ValueControl<string> CreateField()
{
var stringProvider = FindStringProvider(null, m_Provider.customAttributes);
var pushButtonProvider = FindPushButtonBehavior(m_Provider.customAttributes);
var label = new Label(ObjectNames.NicifyVariableName(provider.name));
if (stringProvider != null)
{
m_StringFieldProvider = new VFXStringFieldProvider(label, stringProvider);
return m_StringFieldProvider;
}
else if (pushButtonProvider.action != null)
{
m_StringFieldPushButton = new VFXStringFieldPushButton(label, pushButtonProvider.action, pushButtonProvider.buttonName);
if (isDelayed)
{
VisualElement input = m_StringFieldPushButton.textfield.Q("unity-text-input");
input.RegisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
return m_StringFieldPushButton;
}
else
{
m_StringField = new VFXStringField(label);
if (isDelayed)
{
VisualElement input = m_StringField.textfield.Q("unity-text-input");
input.RegisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
return m_StringField;
}
}
public override bool isDelayed
{
get => base.isDelayed;
set
{
if (base.isDelayed != value)
{
base.isDelayed = value;
if (m_StringField != null)
{
VisualElement input = m_StringField.textfield.Q("unity-text-input");
if (isDelayed)
{
input.RegisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
else
{
input.UnregisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.UnregisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
}
if (m_StringFieldPushButton != null)
{
VisualElement input = m_StringFieldPushButton.textfield.Q("unity-text-input");
if (isDelayed)
{
input.RegisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
else
{
input.UnregisterCallback<BlurEvent>(OnFocusLost, TrickleDown.TrickleDown);
input.UnregisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
}
}
}
}
}
void OnKeyDown(KeyDownEvent e)
{
if (e.character == '\n')
{
if (isDelayed && hasChangeDelayed)
{
NotifyValueChanged();
}
UpdateGUI(true);
}
}
void OnFocusLost(BlurEvent e)
{
if (isDelayed && hasChangeDelayed)
{
NotifyValueChanged();
}
UpdateGUI(true);
}
public override bool IsCompatible(IPropertyRMProvider provider)
{
if (!base.IsCompatible(provider)) return false;
var stringProvider = FindStringProvider(null, m_Provider.customAttributes);
var pushButtonInfo = FindPushButtonBehavior(m_Provider.customAttributes);
if (stringProvider != null)
{
return m_Field is VFXStringFieldProvider vfxStringFieldProvider && vfxStringFieldProvider.stringProvider == stringProvider;
}
else if (pushButtonInfo.action != null)
{
return m_Field is VFXStringFieldPushButton vfxStringFieldPushButton && vfxStringFieldPushButton.pushButtonProvider == pushButtonInfo.action;
}
return !(m_Field is VFXStringFieldProvider) && !(m_Field is VFXStringFieldPushButton);
}
}
}