/// <summary> /// Displays a button for setting all axes of motion on an array of targets. /// </summary> /// <param name="preference">Preference storing the motion type value.</param> /// <param name="label">Label for the control.</param> /// <param name="targets">An array of configurable joints.</param> /// <param name="applyMethod">Method to invoke if preference value is to be applied to all targets.</param> private void DisplayMultiJointMotionButton( EditorPreference <ConfigurableJointMotion, JointEditor> preference, GUIContent label, System.Action <ConfigurableJoint, ConfigurableJointMotion> applyMethod ) { Rect controlPosition, buttonPosition; EditorGUIX.GetRectsForControlWithInlineButton( EditorGUILayout.GetControlRect(), out controlPosition, out buttonPosition, 40f, 80f ); preference.CurrentValue = (ConfigurableJointMotion)EditorGUIX.DisplayField <System.Enum>( controlPosition, label, preference.CurrentValue, EditorGUI.EnumPopup ); if (EditorGUIX.DisplayButton(buttonPosition, "Set All")) { Undo.RecordObjects(m_CachedTargets, string.Format("Set All {0} Motion", label.text)); foreach (ConfigurableJoint j in m_CachedTargets) { if (j == null) { continue; } applyMethod(j, preference.CurrentValue); } EditorUtilityX.SetDirty(m_CachedTargets); } }
/// <summary> /// Raises the inspector GUI event. /// </summary> public override void OnInspectorGUI() { bool needsUpdate = false; this.serializedObject.Update(); EditorGUILayout.PropertyField(m_Script); EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(m_CurrentLocale); EditorGUILayout.PropertyField(m_DefaultText); } if (EditorGUI.EndChangeCheck()) { needsUpdate = true; } if (EditorGUIX.DisplayButton("Add 10 Most Common Languages")) { Undo.RecordObjects(this.targets, "Add 10 Most Common Languages"); foreach (LocalizableText text in this.targets) { text.GetLocaleOverrides(m_LocaleOverrideEntries); foreach (string locale in LocalizableText.TenMostCommonLanguages) { if (!m_LocaleOverrideEntries.ContainsKey(locale)) { m_LocaleOverrideEntries.Add(locale, ""); } } text.SetLocaleOverrides(m_LocaleOverrideEntries); } EditorUtilityX.SetDirty(this.targets); UpdateGUIContents(); } if (EditorGUIX.DisplayButton("Alphabetize")) { Undo.RecordObjects(this.targets, "Alphabetize"); foreach (LocalizableText text in this.targets) { System.Collections.IList backingFieldValue = (System.Collections.IList)s_LocaleOverridesField.GetValue(text); List <IIdentifiable <string> > sortingList = backingFieldValue.Cast <IIdentifiable <string> >().ToList(); sortingList.Sort((x, y) => x.Identifier.ToLower().CompareTo(y.Identifier.ToLower())); for (int i = 0; i < sortingList.Count; ++i) { backingFieldValue[i] = sortingList[i]; } s_LocaleOverridesField.SetValue(text, backingFieldValue); } EditorUtilityX.SetDirty(this.targets); } EditorGUI.BeginChangeCheck(); { EditorGUIX.DisplayListWithElementEditor(m_LocaleOverrides); } if (EditorGUI.EndChangeCheck()) { needsUpdate = true; } this.serializedObject.ApplyModifiedProperties(); if (needsUpdate) { UpdateGUIContents(); } }
/// <summary> /// Invokes the supplied property setter for the supplied hashable serialized property and update its value /// cache. /// </summary> /// <param name="hashableProperty">A hashable representation of the property's serialized backing field.</param> /// <param name="getter">A getter method that takes the provider as its argument.</param> /// <param name="setter">A setter method that takes the provider and new value as its arguments.</param> /// <param name="propertyType">The type returned by the getter and specified in the setter signature.</param> private static void InvokeSetter( HashableSerializedProperty hashableProperty, System.Func <object, object> getter, System.Action <object, object> setter, System.Type propertyType ) { SerializedProperty sp = hashableProperty.SerializedProperty; // mark for undo HashSet <Object> objectsToUndo = new HashSet <Object>(); objectsToUndo.Add(hashableProperty.TargetObject); string undoName = string.Format("Change {0}", sp.GetDisplayName()); // if it's on a monobehaviour, it may affect other objects in the hierarchy if (hashableProperty.TargetObject is MonoBehaviour) { MonoBehaviour monoBehaviour = hashableProperty.TargetObject as MonoBehaviour; foreach (Transform t in monoBehaviour.transform.root.GetComponentsInChildren <Transform>(true)) { objectsToUndo.Add(t.gameObject); foreach (Component c in t.GetComponents <Component>()) { if (c != null) // skip MonoBehaviours with unassigned script reference { objectsToUndo.Add(c); } } } } Undo.RecordObjects(objectsToUndo.ToArray(), undoName); // get the providers FieldInfo fieldInfo; object provider = sp.GetProvider(out fieldInfo); // get the element index of the property being set, if any int elementIndex = hashableProperty.SerializedProperty.GetElementIndex(); // flush inspector changes and store pending values sp.serializedObject.ApplyModifiedProperties(); object pendingValue = null; // ensure IList backing field values are converted to the type expected by the setter if (elementIndex < 0 && typeof(IList).IsAssignableFrom(propertyType) && propertyType != fieldInfo.FieldType) { pendingValue = sp.GetConvertedIListValues(propertyType); } else { pendingValue = sp.GetValue(); } // reset backing field to old values if (elementIndex >= 0) { (fieldInfo.GetValue(provider) as IList)[elementIndex] = s_ValueCache[hashableProperty]; } else { fieldInfo.SetValue(provider, s_ValueCache[hashableProperty]); } // invoke the setter if (elementIndex >= 0) { // clone the result of the getter IList arrayValues = (IList)getter.Invoke(provider); if (typeof(System.Array).IsAssignableFrom(propertyType)) { arrayValues = (IList)((System.ICloneable)arrayValues).Clone(); } else { IList srcValues = arrayValues; arrayValues = (IList)System.Activator.CreateInstance(propertyType); for (int idx = 0; idx < srcValues.Count; ++idx) { arrayValues.Add(srcValues[idx]); } } // assign the pending element value arrayValues[elementIndex] = pendingValue; // invoke setter setter.Invoke(provider, arrayValues); } else { setter.Invoke(provider, pendingValue); // if the provider is a struct, copy its changes back up to the next reference type if (provider.GetType().IsValueType) { object newValue = provider; SerializedProperty parent = sp.GetParentProperty(); while (parent != null && !parent.isArray) { provider = parent.GetProvider(out fieldInfo); if (typeof(IList).IsAssignableFrom(fieldInfo.FieldType)) { elementIndex = parent.GetElementIndex(); (fieldInfo.GetValue(provider) as IList)[elementIndex] = newValue; } else { fieldInfo.SetValue(provider, newValue); } if (provider.GetType().IsValueType) { newValue = provider; parent = parent.GetParentProperty(); } else { parent = null; } } } } // set dirty EditorUtilityX.SetDirty(objectsToUndo.ToArray()); // update cache s_ValueCache[hashableProperty] = sp.GetValue(); }