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

420 lines
16 KiB
C#

4 years ago
using UnityEngine;
using System.Collections;
using MalbersAnimations.Scriptables;
#if UNITY_EDITOR
using UnityEditorInternal;
using UnityEditor;
#endif
namespace MalbersAnimations.Utilities
{
[AddComponentMenu("Malbers/Events/Messages")]
public class Messages : MonoBehaviour
{
public MesssageItem[] messages; //Store messages to send it when Enter the animation State
public bool UseSendMessage = true;
public bool SendToChildren = true;
public bool debug = true;
public bool nextFrame = false;
public Component Pinned;
/// <summary> Send all the messages to a gameobject </summary>
public virtual void SendMessage(GameObject component) => SendMessage(component.transform);
/// <summary> Store the Receiver of the messages</summary>
public virtual void Pin_Receiver(GameObject component) => Pinned = component.transform;
/// <summary> Store the Receiver of the messages</summary>
public virtual void Pin_Receiver(Component component) => Pinned = component;
/// <summary>Send a message by its index to the stored receiver</summary>
public virtual void SendMessage(int index)
{
if (nextFrame)
this.Delay_Action(() => Deliver(messages[index], Pinned));
else
Deliver(messages[index], Pinned);
}
public virtual void SendMessageByIndex(int index) => SendMessage(index);
public virtual void SendMessage(Component go)
{
Pinned = go;
foreach (var m in messages)
{
if (nextFrame)
this.Delay_Action(() => Deliver(m, Pinned));
else
Deliver(m, Pinned);
}
}
private void Deliver(MesssageItem m, Component go)
{
if (UseSendMessage)
m.DeliverMessage(go, SendToChildren, debug);
else
{
IAnimatorListener[] listeners;
if (SendToChildren)
listeners = go.GetComponentsInChildren<IAnimatorListener>();
else
listeners = go.GetComponents<IAnimatorListener>();
if (listeners != null && listeners.Length > 0)
{
foreach (var animListeners in listeners)
m.DeliverAnimListener(animListeners,debug);
}
}
}
//#if UNITY_EDITOR
// private void OnDrawGizmosSelected()
// {
// DrawInteration(true);
// }
// private void OnDrawGizmos()
// {
// DrawInteration(false);
// }
// private void DrawInteration(bool Selected)
// {
// foreach (var msg in messages)
// {
// Transform t = null;
// if (msg.typeM == TypeMessage.Transform && !msg.transformValue.gameObject.IsPrefab()) t = msg.transformValue;
// else if (msg.typeM == TypeMessage.Component && !msg.ComponentValue.gameObject.IsPrefab()) t = msg.ComponentValue.transform;
// else if (msg.typeM == TypeMessage.GameObject && !msg.GoValue.IsPrefab()) t = msg.GoValue.transform;
// if (t) MalbersEditor.DrawInteraction(transform.position, t.position, Selected, Color.white);
// }
// }
//#endif
}
[System.Serializable]
public class MesssageItem
{
public string message;
public TypeMessage typeM;
public bool boolValue;
public int intValue;
public float floatValue;
public string stringValue;
public IntVar intVarValue;
public Transform transformValue;
public GameObject GoValue;
public Component ComponentValue;
public float time;
public bool sent;
public bool Active = true;
public MesssageItem()
{
message = string.Empty;
Active = true;
}
public bool IsActive => Active && !string.IsNullOrEmpty(message);
public void DeliverAnimListener(IAnimatorListener listener, bool debug = false)
{
if (!IsActive) return; //Mean the Message cannot be sent
string val = "";
bool succesful = false;
switch (typeM)
{
case TypeMessage.Bool:
succesful = listener.OnAnimatorBehaviourMessage(message, boolValue);
val = boolValue.ToString();
break;
case TypeMessage.Int:
succesful = listener.OnAnimatorBehaviourMessage(message, intValue);
val = intValue.ToString();
break;
case TypeMessage.Float:
succesful = listener.OnAnimatorBehaviourMessage(message, floatValue);
val = floatValue.ToString();
break;
case TypeMessage.String:
succesful = listener.OnAnimatorBehaviourMessage(message, stringValue);
val = stringValue.ToString();
break;
case TypeMessage.Void:
succesful = listener.OnAnimatorBehaviourMessage(message, null);
val = "Void";
break;
case TypeMessage.IntVar:
succesful = listener.OnAnimatorBehaviourMessage(message, (int)intVarValue);
val = intVarValue.name.ToString();
break;
case TypeMessage.Transform:
succesful = listener.OnAnimatorBehaviourMessage(message, transformValue);
val = transformValue.name.ToString();
break;
case TypeMessage.GameObject:
succesful = listener.OnAnimatorBehaviourMessage(message, GoValue);
val = GoValue.name.ToString();
break;
case TypeMessage.Component:
succesful = listener.OnAnimatorBehaviourMessage(message, ComponentValue);
val = GoValue.name.ToString();
break;
default:
break;
}
if (debug && succesful) Debug.Log($"<b>[AnimMsg: {message}->{val}] [{typeM}]</b> T:{Time.time:F3}"); //Debug
}
/// <summary> Using Message to the Monovehaviours asociated to this animator delivery with Send Message </summary>
public void DeliverMessage(Component anim, bool SendToChildren, bool debug = false)
{
if (!IsActive) return; //Mean the Message cannot be sent
switch (typeM)
{
case TypeMessage.Bool:
SendMessage(anim, message, boolValue, SendToChildren);
break;
case TypeMessage.Int:
SendMessage(anim, message, intValue, SendToChildren);
break;
case TypeMessage.Float:
SendMessage(anim, message, floatValue, SendToChildren);
break;
case TypeMessage.String:
SendMessage(anim, message, stringValue, SendToChildren);
break;
case TypeMessage.Void:
SendMessageVoid(anim, message, SendToChildren);
break;
case TypeMessage.IntVar:
SendMessage(anim, message, (int)intVarValue, SendToChildren);
break;
case TypeMessage.Transform:
SendMessage(anim, message, transformValue, SendToChildren);
break;
case TypeMessage.GameObject:
SendMessage(anim, message, GoValue, SendToChildren);
break;
case TypeMessage.Component:
SendMessage(anim, message, ComponentValue, SendToChildren);
break;
default:
break;
}
if (debug) Debug.Log($"<b>[Send Msg: {message}->] [{typeM}]</b> T:{Time.time:F3}", anim); //Debug
}
private void SendMessage(Component anim, string message, object value, bool SendToChildren)
{
if (SendToChildren)
anim.BroadcastMessage(message, value, SendMessageOptions.DontRequireReceiver);
else
anim.SendMessage(message, value, SendMessageOptions.DontRequireReceiver);
}
private void SendMessageVoid(Component anim, string message, bool SendToChildren)
{
if (SendToChildren)
anim.BroadcastMessage(message, SendMessageOptions.DontRequireReceiver);
else
anim.SendMessage(message, SendMessageOptions.DontRequireReceiver);
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(MesssageItem))]
public class MessageDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// position.y += 2;
EditorGUI.BeginProperty(position, label, property);
//GUI.Box(position, GUIContent.none, EditorStyles.helpBox);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
//var height = EditorGUIUtility.singleLineHeight;
//PROPERTIES
var Active = property.FindPropertyRelative("Active");
var message = property.FindPropertyRelative("message");
var typeM = property.FindPropertyRelative("typeM");
var rect = new Rect(position);
rect.y += 2;
Rect R_0 = new Rect(rect.x, rect.y, 15, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(R_0, Active, GUIContent.none);
Rect R_1 = new Rect(rect.x + 15, rect.y, (rect.width / 3) + 15, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(R_1, message, GUIContent.none);
Rect R_3 = new Rect(rect.x + ((rect.width) / 3) + 5 + 30, rect.y, ((rect.width) / 3) - 5 - 15, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(R_3, typeM, GUIContent.none);
Rect R_5 = new Rect(rect.x + ((rect.width) / 3) * 2 + 5 + 15, rect.y, ((rect.width) / 3) - 5 - 15, EditorGUIUtility.singleLineHeight);
var TypeM = (TypeMessage)typeM.intValue;
SerializedProperty messageValue = property.FindPropertyRelative("boolValue");
switch (TypeM)
{
case TypeMessage.Bool:
messageValue.boolValue = EditorGUI.ToggleLeft(R_5, messageValue.boolValue ? " True" : " False", messageValue.boolValue);
break;
case TypeMessage.Int:
messageValue = property.FindPropertyRelative("intValue");
break;
case TypeMessage.Float:
messageValue = property.FindPropertyRelative("floatValue");
break;
case TypeMessage.String:
messageValue = property.FindPropertyRelative("stringValue");
break;
case TypeMessage.IntVar:
messageValue = property.FindPropertyRelative("intVarValue");
break;
case TypeMessage.Transform:
messageValue = property.FindPropertyRelative("transformValue");
break;
case TypeMessage.Void:
break;
case TypeMessage.GameObject:
messageValue = property.FindPropertyRelative("GoValue");
break;
case TypeMessage.Component:
messageValue = property.FindPropertyRelative("ComponentValue");
break;
default:
break;
}
if (TypeM != TypeMessage.Void && TypeM != TypeMessage.Bool)
{
EditorGUI.PropertyField(R_5, messageValue, GUIContent.none);
}
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
//INSPECTOR
[CustomEditor(typeof(Messages))]
public class MessagesEd : Editor
{
private ReorderableList list;
// private Messages MMessage;
private SerializedProperty sp_messages, debug, nextFrame, SendToChildren, UseSendMessage;
private void OnEnable()
{
sp_messages = serializedObject.FindProperty("messages");
debug = serializedObject.FindProperty("debug");
SendToChildren = serializedObject.FindProperty("SendToChildren");
UseSendMessage = serializedObject.FindProperty("UseSendMessage");
nextFrame = serializedObject.FindProperty("nextFrame");
list = new ReorderableList(serializedObject, sp_messages, true, true, true, true)
{
drawHeaderCallback = HeaderCallbackDelegate1,
drawElementCallback = ( rect, index, isActive, isFocused) =>
{
EditorGUI.PropertyField(rect, sp_messages.GetArrayElementAtIndex(index), GUIContent.none);
}
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
MalbersEditor.DrawDescription("Send messages to scripts with the [IAnimatorListener] interface. " +
"Enable [SendMessage] to use Component.SendMessage() instead.");
EditorGUILayout.BeginVertical(MTools.StyleGray);
{
list.DoLayoutList();
EditorGUILayout.BeginHorizontal();
var currentGUIColor = GUI.color;
GUI.color = SendToChildren.boolValue ? (Color.green) : currentGUIColor;
SendToChildren.boolValue = GUILayout.Toggle(SendToChildren.boolValue,
new GUIContent("Children", "The Messages will be sent also to the gameobject children"), EditorStyles.miniButton);
GUI.color = UseSendMessage.boolValue ? (Color.green) : currentGUIColor;
UseSendMessage.boolValue = GUILayout.Toggle(UseSendMessage.boolValue,
new GUIContent("SendMessage()", "Uses the SendMessage() method, instead of checking for IAnimator Listener Interfaces"), EditorStyles.miniButton);
GUI.color = currentGUIColor;
if (nextFrame != null)
{
GUI.color = nextFrame.boolValue ? (Color.green) : currentGUIColor;
nextFrame.boolValue = GUILayout.Toggle(nextFrame.boolValue,
new GUIContent("Next Frame", "Waits for the next frame to send the messages"), EditorStyles.miniButton);
GUI.color = currentGUIColor;
}
MalbersEditor.DrawDebugIcon(debug);
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
static void HeaderCallbackDelegate1(Rect rect)
{
var width = (rect.width / 3);
var height = EditorGUIUtility.singleLineHeight;
Rect R_1 = new Rect(rect.x + 10, rect.y, width + 30, height);
EditorGUI.LabelField(R_1, "Message");
Rect R_3 = new Rect(rect.x + 10 + width + 5 + 30, rect.y, width - 20, height);
EditorGUI.LabelField(R_3, "Type");
Rect R_5 = new Rect(rect.x + 10 + width * 2 + 20, rect.y, width - 20, height);
EditorGUI.LabelField(R_5, "Value");
}
}
#endif
}