public override void OnInspectorGUI() { Rect rect; string currentControlName; // Check for key down before drawing any fields because they might consume the event. bool enterKeyDown = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return; // Load serialized object serializedObject.Update(); // Port field EditorGUI.BeginChangeCheck(); GUI.SetNextControlName(portControlName); int newPort = EditorGUILayout.IntField(_portLabel, _oscIn.port); if (EditorGUI.EndChangeCheck()) { _portProp.intValue = newPort; if (_oscIn.isOpen) { _oscIn.Close(); // Close UDPReceiver while editing } } currentControlName = GUI.GetNameOfFocusedControl(); bool enterKeyDownPort = enterKeyDown && currentControlName == portControlName; if (enterKeyDownPort) { UnfocusAndUpdateUI(); } bool deselect = _prevControlName == portControlName && currentControlName != portControlName; if ((deselect || enterKeyDownPort) && !_oscIn.isOpen) { if (_oscIn.Open(_portProp.intValue)) { _tempPort = _portProp.intValue; } else { _portProp.intValue = _tempPort; // undo _oscIn.Open(_portProp.intValue); } } // Mode field EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_modeProp, _modeLabel); if (EditorGUI.EndChangeCheck()) { switch ((OscReceiveMode)_modeProp.enumValueIndex) { case OscReceiveMode.UnicastBroadcast: _oscIn.Open(_oscIn.port, string.Empty); _multicastAddressProp.stringValue = string.Empty; break; case OscReceiveMode.UnicastBroadcastMulticast: _oscIn.Open(_oscIn.port, OscConst.multicastAddressDefault); _multicastAddressProp.stringValue = OscConst.multicastAddressDefault; break; } } // Multicast field if (_oscIn.mode == OscReceiveMode.UnicastBroadcastMulticast) { EditorGUI.BeginChangeCheck(); GUI.SetNextControlName(multicastAddressControlName); EditorGUILayout.PropertyField(_multicastAddressProp, _multicastIpAddressLabel); if (EditorGUI.EndChangeCheck()) { if (_oscIn.isOpen) { _oscIn.Close(); // Close socket while editing } } currentControlName = GUI.GetNameOfFocusedControl(); bool enterKeyDownMulticastIpAddress = enterKeyDown && currentControlName == multicastAddressControlName; if (enterKeyDownMulticastIpAddress) { UnfocusAndUpdateUI(); } deselect = _prevControlName == multicastAddressControlName && currentControlName != multicastAddressControlName; if ((deselect || enterKeyDownMulticastIpAddress) && !_oscIn.isOpen) { if (_oscIn.Open(_portProp.intValue, _multicastAddressProp.stringValue)) { _tempMulticastAddress = _multicastAddressProp.stringValue; } else { _multicastAddressProp.stringValue = _tempMulticastAddress; // undo _oscIn.Open(_portProp.intValue, _multicastAddressProp.stringValue); } } } // IP Address field. EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(_localIpAddressLabel); EditorGUILayout.LabelField(" "); rect = GUILayoutUtility.GetLastRect(); // UI voodoo to position the selectable label perfectly EditorGUI.SelectableLabel(rect, OscIn.localIpAddress); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); // Alternative IP Addresses field. if (OscIn.localIpAddressAlternatives.Count > 0) { int i = 0; foreach (string ip in OscIn.localIpAddressAlternatives) { EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(new GUIContent(_localIpAddressAlternativesLabel.text + "[" + i + "]", _localIpAddressAlternativesLabel.tooltip)); EditorGUILayout.LabelField(" "); rect = GUILayoutUtility.GetLastRect(); // UI voodoo to position the selectable label perfectly EditorGUI.SelectableLabel(rect, ip); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); i++; } } // Is Open field EditorGUI.BeginDisabledGroup(true); EditorGUILayout.Toggle(_isOpenLabel, _oscIn.isOpen); EditorGUI.EndDisabledGroup(); // Open On Awake field EditorGUI.BeginDisabledGroup(Application.isPlaying); EditorGUILayout.PropertyField(_openOnAwakeProp, _openOnAwakeLabel); EditorGUI.EndDisabledGroup(); // Settings ... _settingsFoldoutProp.boolValue = EditorGUILayout.Foldout(_settingsFoldoutProp.boolValue, _settingsFoldLabel, true); if (_settingsFoldoutProp.boolValue) { EditorGUI.indentLevel++; // Udp Buffer Size field. EditorGUI.BeginChangeCheck(); int newBufferSize = EditorGUILayout.IntField(_udpBufferSizeLabel, _udpBufferSizeProp.intValue); if (EditorGUI.EndChangeCheck()) { if (newBufferSize >= OscConst.udpBufferSizeMin) { _udpBufferSizeProp.intValue = newBufferSize; _oscIn.udpBufferSize = newBufferSize; // This will reopen OscIn } } // Filter Duplicates field BoolSettingsField(_filterDuplicatesProp, _filterDuplicatesLabel); // Add Time Tags To Bundled Messages field. BoolSettingsField(_addTimeTagsToBundledMessagesProp, _addTimeTagsToBundledMessagesLabel); EditorGUI.indentLevel--; } // Mappings ... string mappingsFoldLabel = "Mappings (" + _mappingsProp.arraySize + ")"; _mappingsFoldoutProp.boolValue = EditorGUILayout.Foldout(_mappingsFoldoutProp.boolValue, mappingsFoldLabel, true); if (_mappingsFoldoutProp.boolValue) { EditorGUI.indentLevel++; EditorGUI.BeginDisabledGroup(Application.isPlaying); // Mapping elements .. int removeIndexRequsted = -1; for (int m = 0; m < _mappingsProp.arraySize; m++) { SerializedProperty mappingProp = _mappingsProp.GetArrayElementAtIndex(m); // Mapping field (using custom property drawer) EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(mappingProp); if (EditorGUI.EndChangeCheck()) { SerializedProperty addressProp = mappingProp.FindPropertyRelative(mappingAddressFieldName); addressProp.stringValue = GetSanitizedAndUniqueAddress(_mappingsProp, m, addressProp.stringValue); } // Remove mapping button rect = GUILayoutUtility.GetLastRect(); rect = EditorGUI.IndentedRect(GUILayoutUtility.GetLastRect()); rect.x = rect.x + rect.width - OscMappingDrawer.removeButtonWidth - 7; rect.y += 6; rect.width = OscMappingDrawer.removeButtonWidth; rect.height = OscMappingDrawer.removeButtonHeight; if (GUI.Button(rect, _removeMappingButtonLabel)) { removeIndexRequsted = m; } } // Handle mapping removal .. if (removeIndexRequsted != -1) { _mappingsProp.DeleteArrayElementAtIndex(removeIndexRequsted); } // Add mapping button rect = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 30)); if (GUI.Button(rect, _addMappingButtonLabel)) { string newAddress = GetSanitizedAndUniqueAddress(_mappingsProp, -1, "/"); FieldInfo meppingsInfo = serializedObject.targetObject.GetType().GetField(_mappingsProp.propertyPath, BindingFlags.Instance | BindingFlags.NonPublic); List <OscMapping> mappings = (List <OscMapping>)meppingsInfo.GetValue(serializedObject.targetObject); OscMapping mapping = new OscMapping(newAddress, OscMessageType.OscMessage); mapping.AddEmptyEntry(); mappings.Add(mapping); } EditorGUILayout.Space(); EditorGUI.EndDisabledGroup(); EditorGUI.indentLevel--; } // Messages ... _sb.Clear(); _sb.Append("Messages (").Append(_oscIn.messageCountReceivedLastFrame).Append(",").Append(OscDebug.GetPrettyByteSize(_oscIn.byteCountReceivedLastFrame)).Append(")"); GUIContent messagesFoldContent = new GUIContent(_sb.ToString(), "Messages received last update"); _messagesFoldoutProp.boolValue = EditorGUILayout.Foldout(_messagesFoldoutProp.boolValue, messagesFoldContent, true); if (_messagesFoldoutProp.boolValue) { EditorGUI.indentLevel++; if (_messageMonitorText.Length > 0) { _messageMonitorText.Remove(_messageMonitorText.Length - 1, 1); // Trim last new line temporarily. } EditorGUILayout.HelpBox(_messageMonitorText.ToString(), MessageType.None); if (_messageMonitorText.Length > 0) { _messageMonitorText.Append('\n'); } EditorGUI.indentLevel--; } // Apply serializedObject.ApplyModifiedProperties(); // Request OnInspectorGUI to be called every frame as long as inspector is active EditorUtility.SetDirty(target); // Store name of focused control to detect unfocus events _prevControlName = GUI.GetNameOfFocusedControl(); }
public override void OnGUI(Rect areaRect, SerializedProperty entryProp, GUIContent label) { // Begin. EditorGUI.BeginProperty(areaRect, label, entryProp); // Find property path to OscEvent in which this entry lives. String mappingPropPath = entryProp.propertyPath.Substring(0, entryProp.propertyPath.IndexOf("_entries") - 1); // Get properties. SerializedProperty mappingProp = entryProp.serializedObject.FindProperty(mappingPropPath); SerializedProperty mappingTypeProp = mappingProp.FindPropertyRelative("_type"); SerializedProperty targetGameObjectProp = entryProp.FindPropertyRelative("targetGameObject"); SerializedProperty serializedTargetObjectProp = entryProp.FindPropertyRelative("serializedTargetObject"); SerializedProperty nonSerializedTargetObjectNameProp = entryProp.FindPropertyRelative("nonSerializedTargetObjectName"); SerializedProperty targetMethodNameProp = entryProp.FindPropertyRelative("targetMethodName"); SerializedProperty targetParamAssemblyNameProp = entryProp.FindPropertyRelative("targetParamAssemblyQualifiedName"); //Debug.Log("oscEventParamAssemblyNameProp: " + oscEventParamAssemblyNameProp.name + " " + oscEventParamAssemblyNameProp.propertyPath + " " + oscEventParamAssemblyNameProp.stringValue ); // Get the parameter type. Type mappingParamType = OscMapping.GetParamType((OscMessageType)mappingTypeProp.enumValueIndex); // Prepare positioning. Rect rect = areaRect; rect.height = EditorGUIUtility.singleLineHeight; rect.width = (areaRect.width + 16 + 26) / 3f; rect.y += verticalPadding; rect.x -= 16; // Target GameObject. bool displayGameObjectField = (Application.isPlaying && targetGameObjectProp.objectReferenceValue != null) || !Application.isPlaying; if (displayGameObjectField) { targetGameObjectProp.objectReferenceValue = EditorGUI.ObjectField(rect, targetGameObjectProp.objectReferenceValue, typeof(GameObject), true); if (targetGameObjectProp.objectReferenceValue is GameObject && !(serializedTargetObjectProp.objectReferenceValue is Component)) { serializedTargetObjectProp.objectReferenceValue = null; } } else { EditorGUI.LabelField(rect, string.Empty); } rect.x += rect.width - 13; // Target Object. rect.y += 1; // The default object selection GUI is taller than drop down. bool isAnonymous = targetMethodNameProp.stringValue.IndexOfAny(anonymousChars) > -1; if (isAnonymous) { EditorGUI.LabelField(rect, string.Empty); } else { bool displayObjectDropdown = targetGameObjectProp.objectReferenceValue != null; if (displayObjectDropdown) { if (targetGameObjectProp.objectReferenceValue != null) { GameObject go = targetGameObjectProp.objectReferenceValue as GameObject; Component[] components = go.GetComponents <Component>(); int selectedComponentIndex = Array.IndexOf(components, serializedTargetObjectProp.objectReferenceValue as Component); GUIContent[] componentOptions = new GUIContent[components.Length]; for (int i = 0; i < components.Length; i++) { componentOptions[i] = new GUIContent(components[i].GetType().Name); } int newSelectedComponentIndex = EditorGUI.Popup(rect, selectedComponentIndex, componentOptions); if (newSelectedComponentIndex != selectedComponentIndex) { serializedTargetObjectProp.objectReferenceValue = components[newSelectedComponentIndex]; targetMethodNameProp.stringValue = string.Empty; } } else if (serializedTargetObjectProp.objectReferenceValue != null) { EditorGUI.BeginDisabledGroup(true); serializedTargetObjectProp.objectReferenceValue = EditorGUI.ObjectField(rect, serializedTargetObjectProp.objectReferenceValue, typeof(Object), true); EditorGUI.EndDisabledGroup(); } } else if (!string.IsNullOrEmpty(nonSerializedTargetObjectNameProp.stringValue)) { // Non serialized object. EditorGUI.LabelField(rect, nonSerializedTargetObjectNameProp.stringValue); } else { EditorGUI.LabelField(rect, string.Empty); } } rect.x += rect.width - 13; // Method. if (isAnonymous) { EditorGUI.LabelField(rect, "Anonymous"); } else { bool displayMethodDropdown = serializedTargetObjectProp.objectReferenceValue != null; if (displayMethodDropdown) { bool isMappingParamNull = mappingParamType == null; CandidateLists candidateLists; GetMethodOptions(serializedTargetObjectProp.objectReferenceValue.GetType(), mappingParamType, out candidateLists); int selectedMethodNameIndex = Array.IndexOf(candidateLists.methodNames, targetMethodNameProp.stringValue); bool isPrivateMethod = selectedMethodNameIndex == -1 && !string.IsNullOrEmpty(targetMethodNameProp.stringValue) && Application.isPlaying; if (isPrivateMethod) { EditorGUI.LabelField(rect, targetMethodNameProp.stringValue); } else { int newSelectedMethodNameIndex = EditorGUI.Popup(rect, selectedMethodNameIndex, candidateLists.methodOptions); if (newSelectedMethodNameIndex != selectedMethodNameIndex) { selectedMethodNameIndex = newSelectedMethodNameIndex; targetMethodNameProp.stringValue = candidateLists.methodNames[selectedMethodNameIndex]; if (!isMappingParamNull) { targetParamAssemblyNameProp.stringValue = candidateLists.paramTypes[selectedMethodNameIndex].AssemblyQualifiedName; } } } } else { EditorGUI.LabelField(rect, targetMethodNameProp.stringValue); } } // End. EditorGUI.EndProperty(); }