holopy3/Assets/Normal/Realtime/Editor/RealtimeAvatarEditor.cs
2020-12-10 15:25:12 +01:00

200 lines
9.6 KiB
C#

using System;
using UnityEngine;
using UnityEditor;
namespace Normal.Realtime {
[CustomEditor(typeof(RealtimeAvatar))]
public class RealtimeAvatarEditor : Editor {
private RealtimeAvatar realtimeAvatar { get { return (RealtimeAvatar)target; } }
private SerializedProperty headProperty { get { return serializedObject.FindProperty("_head"); } }
private SerializedProperty leftHandProperty { get { return serializedObject.FindProperty("_leftHand"); } }
private SerializedProperty rightHandProperty { get { return serializedObject.FindProperty("_rightHand"); } }
public override void OnInspectorGUI() {
GUILayout.Space(4);
// Properties
serializedObject.Update();
headProperty.objectReferenceValue = EditorGUILayout.ObjectField("Head", headProperty.objectReferenceValue, typeof(Transform), true);
leftHandProperty.objectReferenceValue = EditorGUILayout.ObjectField("Left Hand", leftHandProperty.objectReferenceValue, typeof(Transform), true);
rightHandProperty.objectReferenceValue = EditorGUILayout.ObjectField("Right Hand", rightHandProperty.objectReferenceValue, typeof(Transform), true);
GUILayout.Space(4);
// Create Avatar Prefab
GUI.enabled = !Application.isPlaying;
GUILayout.BeginHorizontal();
if (GUILayout.Button("Create Avatar Prefab"))
CreateAvatarPrefab();
GUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
GUILayout.Space(4);
}
void CreateAvatarPrefab() {
GameObject gameObject = realtimeAvatar.gameObject;
//// Root
// RealtimeView
RealtimeView rootRealtimeView = AddRealtimeViewComponentIfNeeded(gameObject);
// RealtimeAvatar
AddComponentToRealtimeViewIfNeeded(rootRealtimeView, realtimeAvatar);
// RealtimeTransform
RealtimeTransform rootRealtimeTransform = AddRealtimeTransformComponentIfNeeded(gameObject, true);
AddComponentToRealtimeViewIfNeeded(rootRealtimeView, rootRealtimeTransform);
//// Head
Transform head = CreateGameObjectForPropertyIfNeeded(headProperty, gameObject.transform, "Head", new Type[]{ typeof(Examples.VoiceScale) });
// RealtimeView
RealtimeView headRealtimeView = AddRealtimeViewComponentIfNeeded(head.gameObject);
// RealtimeTransform
RealtimeTransform headRealtimeTransform = AddRealtimeTransformComponentIfNeeded(head.gameObject, false);
AddComponentToRealtimeViewIfNeeded(headRealtimeView, headRealtimeTransform);
// RealtimeAvatarVoice
RealtimeAvatarVoice headRealtimeAvatarVoice = head.gameObject.GetComponent<RealtimeAvatarVoice>();
if (headRealtimeAvatarVoice == null) {
headRealtimeAvatarVoice = head.gameObject.AddComponent<RealtimeAvatarVoice>();
// Collapse inspector
SetComponentInspectorExpanded(headRealtimeAvatarVoice, false);
}
AddComponentToRealtimeViewIfNeeded(headRealtimeView, headRealtimeAvatarVoice);
//// Left Hand
Transform leftHand = CreateGameObjectForPropertyIfNeeded(leftHandProperty, gameObject.transform, "Left Hand");
// RealtimeView
RealtimeView leftHandRealtimeView = AddRealtimeViewComponentIfNeeded(leftHand.gameObject);
// RealtimeTransform
RealtimeTransform leftHandRealtimeTransform = AddRealtimeTransformComponentIfNeeded(leftHand.gameObject, false);
AddComponentToRealtimeViewIfNeeded(leftHandRealtimeView, leftHandRealtimeTransform);
//// Right Hand
Transform rightHand = CreateGameObjectForPropertyIfNeeded(rightHandProperty, gameObject.transform, "Right Hand");
// RealtimeView
RealtimeView rightHandRealtimeView = AddRealtimeViewComponentIfNeeded(rightHand.gameObject);
// RealtimeTransform
RealtimeTransform rightHandRealtimeTransform = AddRealtimeTransformComponentIfNeeded(rightHand.gameObject, false);
AddComponentToRealtimeViewIfNeeded(rightHandRealtimeView, rightHandRealtimeTransform);
}
static RealtimeView AddRealtimeViewComponentIfNeeded(GameObject gameObject) {
RealtimeView realtimeView = gameObject.GetComponent<RealtimeView>();
if (realtimeView == null) {
realtimeView = gameObject.AddComponent<RealtimeView>();
// Collapse inspector
SetComponentInspectorExpanded(realtimeView, false);
}
return realtimeView;
}
static RealtimeTransform AddRealtimeTransformComponentIfNeeded(GameObject gameObject, bool syncScale) {
// Check for existing RealtimeTransform
RealtimeTransform realtimeTransform = gameObject.GetComponent<RealtimeTransform>();
// Create one if needed
if (realtimeTransform == null) {
realtimeTransform = gameObject.AddComponent<RealtimeTransform>();
// Set syncScale
SerializedObject realtimeTransformSerializedObject = new SerializedObject(realtimeTransform);
realtimeTransformSerializedObject.Update();
SerializedProperty syncScaleProperty = realtimeTransformSerializedObject.FindProperty("_syncScale");
syncScaleProperty.boolValue = syncScale;
realtimeTransformSerializedObject.ApplyModifiedProperties();
// Collapse inspector
SetComponentInspectorExpanded(realtimeTransform, false);
}
// Return
return realtimeTransform;
}
static void AddComponentToRealtimeViewIfNeeded(RealtimeView realtimeView, Component component) {
SerializedObject realtimeViewSerializedObject = new SerializedObject(realtimeView);
realtimeViewSerializedObject.Update();
SerializedProperty realtimeViewComponentsProperty = realtimeViewSerializedObject.FindProperty("_components");
// Check if the component already exists on the RealtimeView
int numberOfProperties = realtimeViewComponentsProperty.arraySize;
int largestPropertyIDSeen = 0;
for (int i = 0; i < numberOfProperties; i++) {
SerializedProperty realtimeViewComponentProperty = realtimeViewComponentsProperty.GetArrayElementAtIndex(i);
SerializedProperty realtimeViewComponentComponentIDProperty = realtimeViewComponentProperty.FindPropertyRelative("componentID");
SerializedProperty realtimeViewComponentComponentProperty = realtimeViewComponentProperty.FindPropertyRelative("component");
// Record the property ID
largestPropertyIDSeen = realtimeViewComponentComponentIDProperty.intValue;
// We found the component. We're done.
if (realtimeViewComponentComponentProperty.objectReferenceValue == component)
return;
}
// Component not found, add it.
int newPropertyIndex = realtimeViewComponentsProperty.arraySize;
realtimeViewComponentsProperty.InsertArrayElementAtIndex(newPropertyIndex);
SerializedProperty realtimeViewNewComponentProperty = realtimeViewComponentsProperty.GetArrayElementAtIndex(newPropertyIndex);
SerializedProperty realtimeViewNewComponentComponentIDProperty = realtimeViewNewComponentProperty.FindPropertyRelative("componentID");
SerializedProperty realtimeViewNewComponentComponentProperty = realtimeViewNewComponentProperty.FindPropertyRelative("component");
realtimeViewNewComponentComponentIDProperty.intValue = largestPropertyIDSeen+1;
realtimeViewNewComponentComponentProperty.objectReferenceValue = component;
realtimeViewSerializedObject.ApplyModifiedProperties();
}
static Transform CreateGameObjectForPropertyIfNeeded(SerializedProperty serializedProperty, Transform parent, string gameObjectName, Type[] components = null) {
Transform transform = serializedProperty.objectReferenceValue as Transform;
if (transform == null) {
transform = CreateGameObjectWithCubeGeometry(gameObjectName, parent, components);
serializedProperty.objectReferenceValue = transform;
}
return transform;
}
static Transform CreateGameObjectWithCubeGeometry(string name, Transform parent, Type[] components = null) {
if (components == null)
components = new Type[0];
GameObject gameObject = new GameObject(name, components);
Transform transform = gameObject.transform;
transform.SetParent(parent, false);
GameObject geometry = GameObject.CreatePrimitive(PrimitiveType.Cube);
geometry.name = "Geometry";
Transform geometryTransform = geometry.transform;
geometryTransform.SetParent(transform, false);
geometryTransform.localScale = Vector3.one * 0.1f;
return transform;
}
static void SetComponentInspectorExpanded(Component component, bool expanded) {
// Set expanded
UnityEditorInternal.InternalEditorUtility.SetIsInspectorExpanded(component, expanded);
// Refresh selection
GameObject gameObject = Selection.activeGameObject;
Selection.activeGameObject = null;
Selection.activeGameObject = gameObject;
}
}
}