// Create an instance of an event configuration for a state
        private BaseInteractionEventConfiguration CreateEventConfigurationInstance(string stateName)
        {
            BaseInteractionEventConfiguration eventConfiguration;

            string subStateName = stateManager.GetState(stateName).GetSubStateName();

            // Check if the state has an associated event configuration by state name.
            // For example, the Focus state is associated with the FocusEvents class which has BaseInteractionEventConfiguration as its base class.
            // The FocusEvents class contains unity events with FocusEventData.
            // This pattern continues with states that have events with specific event data, i.e. the Touch state
            // is associated with the serialized class TouchEvents which contains unity events with TouchEventData
            var  eventConfigTypes = TypeCacheUtility.GetSubClasses <BaseInteractionEventConfiguration>();
            Type eventConfigType  = eventConfigTypes.Find((type) => type.Name.StartsWith(subStateName));

            if (eventConfigType != null)
            {
                eventConfiguration = Activator.CreateInstance(eventConfigType) as BaseInteractionEventConfiguration;
            }
            else
            {
                // If a state does not have an associated event configuration class, then create an instance of the
                // StateEvents class which contains the OnStateOn and OnStateOff unity events. These unity events do not have event data.
                eventConfiguration = Activator.CreateInstance(typeof(StateEvents)) as BaseInteractionEventConfiguration;
            }

            eventConfiguration.StateName = stateName;

            return(eventConfiguration);
        }
예제 #2
0
        /// <summary>
        /// Create the event and setup the values from the inspector
        /// </summary>
        public static ReceiverBase CreateReceiver(InteractableEvent iEvent)
        {
            // Temporary workaround
            // This is to fix a bug in GA where the AssemblyQualifiedName was never actually saved. Functionality would work in editor...but never on device player
            if (iEvent.ReceiverType == null)
            {
                var correctType = TypeCacheUtility.GetSubClasses <ReceiverBase>().Where(s => s?.Name == iEvent.ClassName).First();
                iEvent.ReceiverType = correctType;
            }

            ReceiverBase newEvent = (ReceiverBase)Activator.CreateInstance(iEvent.ReceiverType, iEvent.Event);

            InspectorGenericFields <ReceiverBase> .LoadSettings(newEvent, iEvent.Settings);

            return(newEvent);
        }
예제 #3
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            InspectorUIUtility.DrawTitle("States");
            EditorGUILayout.HelpBox("Manage state configurations to drive Interactables or Transitions", MessageType.None);

            SerializedProperty stateModelClassName   = serializedObject.FindProperty("StateModelClassName");
            SerializedProperty assemblyQualifiedName = serializedObject.FindProperty("AssemblyQualifiedName");

            var stateModelTypes      = TypeCacheUtility.GetSubClasses <BaseStateModel>();
            var stateModelClassNames = stateModelTypes.Select(t => t?.Name).ToArray();
            int id = Array.IndexOf(stateModelClassNames, stateModelClassName.stringValue);

            Rect stateModelPos = EditorGUILayout.GetControlRect();

            using (new EditorGUI.PropertyScope(stateModelPos, new GUIContent("State Model"), stateModelClassName))
            {
                int newId = EditorGUILayout.Popup("State Model", id, stateModelClassNames);
                if (id != newId)
                {
                    Type newType = stateModelTypes[newId];
                    stateModelClassName.stringValue   = newType.Name;
                    assemblyQualifiedName.stringValue = newType.AssemblyQualifiedName;
                }
            }

            for (int i = 0; i < stateList.arraySize; i++)
            {
                using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
                {
                    SerializedProperty stateItem = stateList.GetArrayElementAtIndex(i);

                    SerializedProperty name        = stateItem.FindPropertyRelative("Name");
                    SerializedProperty activeIndex = stateItem.FindPropertyRelative("ActiveIndex");
                    SerializedProperty bit         = stateItem.FindPropertyRelative("Bit");
                    SerializedProperty index       = stateItem.FindPropertyRelative("Index");

                    // assign the bitcount based on location in the list as power of 2
                    bit.intValue = 1 << i;

                    activeIndex.intValue = i;

                    Rect position = EditorGUILayout.GetControlRect();
                    using (new EditorGUILayout.HorizontalScope())
                    {
                        var label = new GUIContent(name.stringValue + " (" + bit.intValue + ")");
                        using (new EditorGUI.PropertyScope(position, new GUIContent(), name))
                        {
                            string[] stateEnums = Enum.GetNames(typeof(InteractableStates.InteractableStateEnum));
                            int      enumIndex  = Array.IndexOf(stateEnums, name.stringValue);

                            int newEnumIndex = EditorGUILayout.Popup(label, enumIndex, stateEnums);
                            if (newEnumIndex == -1)
                            {
                                newEnumIndex = 0;
                            }

                            name.stringValue = stateEnums[newEnumIndex];
                            index.intValue   = newEnumIndex;
                        }

                        if (InspectorUIUtility.SmallButton(RemoveStateLabel))
                        {
                            stateList.DeleteArrayElementAtIndex(i);
                            break;
                        }
                    }
                }
            }

            if (InspectorUIUtility.FlexButton(AddStateLabel))
            {
                stateList.InsertArrayElementAtIndex(stateList.arraySize);
            }

            serializedObject.ApplyModifiedProperties();
        }
예제 #4
0
        public void RenderThemeDefinitions()
        {
            GUIStyle box = InspectorUIUtility.HelpBox(EditorGUI.indentLevel * ThemeBoxMargin);

            // Loop through all InteractableThemePropertySettings of Theme
            for (int index = 0; index < themeDefinitions.arraySize; index++)
            {
                using (new EditorGUILayout.VerticalScope(box))
                {
                    SerializedProperty themeDefinition = themeDefinitions.GetArrayElementAtIndex(index);
                    SerializedProperty className       = themeDefinition.FindPropertyRelative("ClassName");

                    string themeDefinition_prefKey = theme.name + "_Definitions" + index;
                    bool   show = false;
                    using (new EditorGUILayout.HorizontalScope())
                    {
                        show = InspectorUIUtility.DrawSectionFoldoutWithKey(className.stringValue, themeDefinition_prefKey, MixedRealityStylesUtility.BoldFoldoutStyle);

                        if (RenderDeleteButton(index))
                        {
                            return;
                        }
                    }

                    if (show)
                    {
                        EditorGUILayout.Space();

                        using (new EditorGUI.IndentLevelScope())
                        {
                            EditorGUILayout.LabelField("General Properties", EditorStyles.boldLabel);

                            using (new EditorGUILayout.HorizontalScope())
                            {
                                var themeTypes      = TypeCacheUtility.GetSubClasses <InteractableThemeBase>();
                                var themeClassNames = themeTypes.Select(t => t?.Name).ToArray();
                                int id    = Array.IndexOf(themeClassNames, className.stringValue);
                                int newId = EditorGUILayout.Popup("Theme Runtime", id, themeClassNames);

                                // Some old Themes did not properly save a value here
                                SerializedProperty assemblyQualifiedName = themeDefinition.FindPropertyRelative("AssemblyQualifiedName");
                                if (string.IsNullOrEmpty(assemblyQualifiedName.stringValue) && newId != -1)
                                {
                                    assemblyQualifiedName.stringValue = themeTypes[newId].AssemblyQualifiedName;
                                }

                                // If user changed the theme type for current themeDefinition
                                if (id != newId && newId != -1)
                                {
                                    Type oldType = id != -1 ? themeTypes[id] : null;
                                    Type newType = themeTypes[newId];
                                    ChangeThemeDefinitionType(index, oldType, newType);
                                    return;
                                }
                            }

                            var themeType = theme.Definitions[index].ThemeType;
                            if (themeType != null)
                            {
                                SerializedProperty customProperties = themeDefinition.FindPropertyRelative("customProperties");
                                RenderCustomProperties(customProperties);

                                var themeExample = (InteractableThemeBase)Activator.CreateInstance(themeType);

                                if (themeExample.IsEasingSupported)
                                {
                                    RenderEasingProperties(themeDefinition);
                                }

                                if (themeExample.AreShadersSupported)
                                {
                                    RenderShaderProperties(themeDefinition);
                                }

                                EditorGUILayout.Space();

                                RenderThemeStates(themeDefinition);
                            }
                            else
                            {
                                InspectorUIUtility.DrawError("Theme Runtime Type is not valid");
                            }
                        }
                    }
                }
            }

            // If no theme properties assigned, add a default one
            if (themeDefinitions.arraySize < 1 || GUILayout.Button(AddThemePropertyLabel))
            {
                AddThemeDefinition();
            }
        }
        /// <summary>
        /// Render event properties for the given event item. If item has been removed, returns true. False otherwise
        /// </summary>
        /// <param name="eventItem">serialized property of the event item to render properties from</param>
        /// <returns>If item has been removed, returns true. False otherwise</returns>
        public static bool RenderEvent(SerializedProperty eventItem, bool canRemove = true)
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                SerializedProperty uEvent                = eventItem.FindPropertyRelative("Event");
                SerializedProperty eventName             = eventItem.FindPropertyRelative("Name");
                SerializedProperty className             = eventItem.FindPropertyRelative("ClassName");
                SerializedProperty assemblyQualifiedName = eventItem.FindPropertyRelative("AssemblyQualifiedName");
                Type receiverType;

                InspectorUIUtility.DrawHeader("Event Receiver Type");
                using (new EditorGUILayout.HorizontalScope())
                {
                    Rect position = EditorGUILayout.GetControlRect();
                    using (new EditorGUI.PropertyScope(position, SelectEventLabel, className))
                    {
                        var receiverTypes      = TypeCacheUtility.GetSubClasses <ReceiverBase>();
                        var recevierClassNames = receiverTypes.Select(t => t?.Name).ToArray();
                        int id    = Array.IndexOf(recevierClassNames, className.stringValue);
                        int newId = EditorGUI.Popup(position, id, recevierClassNames);
                        if (newId == -1)
                        {
                            newId = 0;
                        }

                        receiverType = receiverTypes[newId];

                        // Temporary workaround to fix bug shipped in GA where assemblyQualifiedName was never set
                        if (string.IsNullOrEmpty(assemblyQualifiedName.stringValue))
                        {
                            assemblyQualifiedName.stringValue = receiverType.AssemblyQualifiedName;
                        }

                        if (id != newId)
                        {
                            EventChanged(receiverType, eventItem);
                        }
                    }

                    if (canRemove)
                    {
                        if (InspectorUIUtility.FlexButton(new GUIContent("Remove Event")))
                        {
                            return(true);
                        }
                    }
                }

                EditorGUILayout.Space();
                InspectorUIUtility.DrawHeader("Event Properties");

                ReceiverBase receiver = (ReceiverBase)Activator.CreateInstance(receiverType, new UnityEvent());

                if (!receiver.HideUnityEvents)
                {
                    EditorGUILayout.PropertyField(uEvent, new GUIContent(receiver.Name));
                }

                SerializedProperty eventSettings = eventItem.FindPropertyRelative("Settings");

                // If fields for given receiver class type have been changed, update the related inspector field data
                var fieldList = InspectorFieldsUtility.GetInspectorFields(receiver);
                if (!InspectorFieldsUtility.AreFieldsSame(eventSettings, fieldList))
                {
                    InspectorFieldsUtility.UpdateSettingsList(eventSettings, fieldList);
                }

                for (int index = 0; index < eventSettings.arraySize; index++)
                {
                    SerializedProperty propertyField = eventSettings.GetArrayElementAtIndex(index);
                    bool isEvent = InspectorFieldsUtility.IsPropertyType(propertyField, InspectorField.FieldTypes.Event);

                    if (!receiver.HideUnityEvents || !isEvent)
                    {
                        InspectorFieldsUtility.DisplayPropertyField(eventSettings.GetArrayElementAtIndex(index));
                    }
                }
            }

            return(false);
        }