// ---------------------------------------------------------------------------- // // PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH // // // This is a custom editor for the AnimatorView component. // // developer@exitgames.com // ---------------------------------------------------------------------------- namespace Photon.Pun { using System.Collections.Generic; using UnityEditor; using UnityEditor.Animations; using UnityEngine; [CustomEditor(typeof(PhotonAnimatorView))] public class PhotonAnimatorViewEditor : MonoBehaviourPunEditor { private Animator m_Animator; private PhotonAnimatorView m_Target; private AnimatorController m_Controller; public override void OnInspectorGUI() { base.OnInspectorGUI(); if (this.m_Animator == null) { EditorGUILayout.HelpBox("GameObject doesn't have an Animator component to synchronize", MessageType.Warning); return; } this.DrawWeightInspector(); if (this.GetLayerCount() == 0) { EditorGUILayout.HelpBox("Animator doesn't have any layers setup to synchronize", MessageType.Warning); } this.DrawParameterInspector(); if (this.GetParameterCount() == 0) { EditorGUILayout.HelpBox("Animator doesn't have any parameters setup to synchronize", MessageType.Warning); } this.serializedObject.ApplyModifiedProperties(); //GUILayout.Label( "m_SynchronizeLayers " + serializedObject.FindProperty( "m_SynchronizeLayers" ).arraySize ); //GUILayout.Label( "m_SynchronizeParameters " + serializedObject.FindProperty( "m_SynchronizeParameters" ).arraySize ); } private int GetLayerCount() { return (this.m_Controller == null) ? 0 : this.m_Controller.layers.Length; } private int GetParameterCount() { return (this.m_Controller == null) ? 0 : this.m_Controller.parameters.Length; } private AnimatorControllerParameter GetAnimatorControllerParameter(int i) { return this.m_Controller.parameters[i]; } private RuntimeAnimatorController GetEffectiveController(Animator animator) { RuntimeAnimatorController controller = animator.runtimeAnimatorController; AnimatorOverrideController overrideController = controller as AnimatorOverrideController; while (overrideController != null) { controller = overrideController.runtimeAnimatorController; overrideController = controller as AnimatorOverrideController; } return controller; } private void OnEnable() { this.m_Target = (PhotonAnimatorView)this.target; this.m_Animator = this.m_Target.GetComponent(); if (m_Animator) { this.m_Controller = this.GetEffectiveController(this.m_Animator) as AnimatorController; this.CheckIfStoredParametersExist(); } } private void DrawWeightInspector() { SerializedProperty foldoutProperty = this.serializedObject.FindProperty("ShowLayerWeightsInspector"); foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Layer Weights", foldoutProperty.boolValue); if (foldoutProperty.boolValue == false) { return; } float lineHeight = 20; Rect containerRect = PhotonGUI.ContainerBody(this.GetLayerCount() * lineHeight); for (int i = 0; i < this.GetLayerCount(); ++i) { if (this.m_Target.DoesLayerSynchronizeTypeExist(i) == false) { this.m_Target.SetLayerSynchronized(i, PhotonAnimatorView.SynchronizeType.Disabled); } PhotonAnimatorView.SynchronizeType syncType = this.m_Target.GetLayerSynchronizeType(i); Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i * lineHeight, containerRect.width, lineHeight); Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height); GUI.Label(labelRect, "Layer " + i); Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight); syncType = (PhotonAnimatorView.SynchronizeType)EditorGUI.EnumPopup(popupRect, syncType); if (i < this.GetLayerCount() - 1) { Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1); PhotonGUI.DrawSplitter(splitterRect); } if (syncType != this.m_Target.GetLayerSynchronizeType(i)) { Undo.RecordObject(this.target, "Modify Synchronize Layer Weights"); this.m_Target.SetLayerSynchronized(i, syncType); } } } private bool DoesParameterExist(string name) { for (int i = 0; i < this.GetParameterCount(); ++i) { if (this.GetAnimatorControllerParameter(i).name == name) { return true; } } return false; } private void CheckIfStoredParametersExist() { var syncedParams = this.m_Target.GetSynchronizedParameters(); List paramsToRemove = new List(); for (int i = 0; i < syncedParams.Count; ++i) { string parameterName = syncedParams[i].Name; if (this.DoesParameterExist(parameterName) == false) { Debug.LogWarning("Parameter '" + this.m_Target.GetSynchronizedParameters()[i].Name + "' doesn't exist anymore. Removing it from the list of synchronized parameters"); paramsToRemove.Add(parameterName); } } if (paramsToRemove.Count > 0) { foreach (string param in paramsToRemove) { this.m_Target.GetSynchronizedParameters().RemoveAll(item => item.Name == param); } } } private void DrawParameterInspector() { // flag to expose a note in Interface if one or more trigger(s) are synchronized bool isUsingTriggers = false; SerializedProperty foldoutProperty = this.serializedObject.FindProperty("ShowParameterInspector"); foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Parameters", foldoutProperty.boolValue); if (foldoutProperty.boolValue == false) { return; } float lineHeight = 20; Rect containerRect = PhotonGUI.ContainerBody(this.GetParameterCount() * lineHeight); for (int i = 0; i < this.GetParameterCount(); i++) { AnimatorControllerParameter parameter = null; parameter = this.GetAnimatorControllerParameter(i); string defaultValue = ""; if (parameter.type == AnimatorControllerParameterType.Bool) { if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy) { defaultValue += this.m_Animator.GetBool(parameter.name); } else { defaultValue += parameter.defaultBool.ToString(); } } else if (parameter.type == AnimatorControllerParameterType.Float) { if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy) { defaultValue += this.m_Animator.GetFloat(parameter.name).ToString("0.00"); } else { defaultValue += parameter.defaultFloat.ToString(); } } else if (parameter.type == AnimatorControllerParameterType.Int) { if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy) { defaultValue += this.m_Animator.GetInteger(parameter.name); } else { defaultValue += parameter.defaultInt.ToString(); } } else if (parameter.type == AnimatorControllerParameterType.Trigger) { if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy) { defaultValue += this.m_Animator.GetBool(parameter.name); } else { defaultValue += parameter.defaultBool.ToString(); } } if (this.m_Target.DoesParameterSynchronizeTypeExist(parameter.name) == false) { this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType)parameter.type, PhotonAnimatorView.SynchronizeType.Disabled); } PhotonAnimatorView.SynchronizeType value = this.m_Target.GetParameterSynchronizeType(parameter.name); // check if using trigger and actually synchronizing it if (value != PhotonAnimatorView.SynchronizeType.Disabled && parameter.type == AnimatorControllerParameterType.Trigger) { isUsingTriggers = true; } Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i * lineHeight, containerRect.width, lineHeight); Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height); GUI.Label(labelRect, parameter.name + " (" + defaultValue + ")"); Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight); value = (PhotonAnimatorView.SynchronizeType)EditorGUI.EnumPopup(popupRect, value); if (i < this.GetParameterCount() - 1) { Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1); PhotonGUI.DrawSplitter(splitterRect); } if (value != this.m_Target.GetParameterSynchronizeType(parameter.name)) { Undo.RecordObject(this.target, "Modify Synchronize Parameter " + parameter.name); this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType)parameter.type, value); } } // display note when synchronized triggers are detected. if (isUsingTriggers) { EditorGUILayout.HelpBox("When using triggers, make sure this component is last in the stack. " + "If you still experience issues, implement triggers as a regular RPC " + "or in custom IPunObservable component instead.", MessageType.Warning); } } } }