public override void OnPreTargetMembersGUI() { var skin = InspectorEditor.Skin; var constraints = GetTargets <Constraint>().ToArray(); var refConstraint = constraints[0]; var differentTypes = false; var anyUnknownType = constraints.Any(c => c.Type == ConstraintType.Unknown); for (int i = 1; i < constraints.Length; ++i) { differentTypes = differentTypes || refConstraint.Type != constraints[i].Type; } // Render AttachmentPair GUI. ConstraintAttachmentFrameTool.OnPreTargetMembersGUI(); Undo.RecordObjects(constraints, "ConstraintTool"); UnityEngine.GUI.changed = false; // The constraint type is Unknown when, e.g., go.AddComponent<Constraint>() // or when the constraint has been reset. If any of the selected constraints // is of type Unknown, we exit the GUI here. if (!ConstraintTypeGUI(constraints, differentTypes)) { return; } EditorGUI.showMixedValue = constraints.Any(constraint => refConstraint.CollisionsState != constraint.CollisionsState); var collisionsState = ConstraintCollisionsStateGUI(refConstraint.CollisionsState); EditorGUI.showMixedValue = false; if (UnityEngine.GUI.changed) { foreach (var constraint in constraints) { constraint.CollisionsState = collisionsState; } UnityEngine.GUI.changed = false; } EditorGUI.showMixedValue = constraints.Any(constraint => refConstraint.SolveType != constraint.SolveType); var solveType = ConstraintSolveTypeGUI(refConstraint.SolveType); EditorGUI.showMixedValue = false; if (UnityEngine.GUI.changed) { foreach (var constraint in constraints) { constraint.SolveType = solveType; } UnityEngine.GUI.changed = false; } EditorGUI.showMixedValue = constraints.Any(constraint => refConstraint.ConnectedFrameNativeSyncEnabled != constraint.ConnectedFrameNativeSyncEnabled); var frameNativeSync = ConstraintConnectedFrameSyncGUI(refConstraint.ConnectedFrameNativeSyncEnabled); EditorGUI.showMixedValue = false; if (UnityEngine.GUI.changed) { foreach (var constraint in constraints) { constraint.ConnectedFrameNativeSyncEnabled = frameNativeSync; } UnityEngine.GUI.changed = false; } if (differentTypes) { InspectorGUI.WarningLabel("Constraints are of different types.\nRow data editing not supported."); return; } Func <string, EditorDataEntry> selected = (id) => { return(EditorData.Instance.GetData(refConstraint, id, entry => entry.Bool = false)); }; var constraintsParser = (from constraint in constraints select ConstraintUtils.ConstraintRowParser.Create(constraint)).ToArray(); var allElementaryConstraints = constraints.SelectMany(constraint => constraint.GetOrdinaryElementaryConstraints()).ToArray(); Undo.RecordObjects(allElementaryConstraints, "ConstraintTool"); var ecRowDataWrappers = InvokeWrapper.FindFieldsAndProperties <ElementaryConstraintRowData>(); foreach (ConstraintUtils.ConstraintRowParser.RowType rowType in Enum.GetValues(typeof(ConstraintUtils.ConstraintRowParser.RowType))) { if (!InspectorGUI.Foldout(selected("ec_" + rowType.ToString()), GUI.MakeLabel(rowType.ToString() + " properties", true))) { continue; } using (InspectorGUI.IndentScope.Single) { var refTransOrRotRowData = constraintsParser[0][rowType]; foreach (var wrapper in ecRowDataWrappers) { if (!InspectorEditor.ShouldBeShownInInspector(wrapper.Member)) { continue; } for (int i = 0; i < 3; ++i) { var rowDataInstances = (from constraintParser in constraintsParser where constraintParser[rowType][i] != null select constraintParser[rowType][i].RowData).ToArray(); using (new GUI.EnabledBlock(refTransOrRotRowData[i] != null)) { var labelContent = i == 0 ? InspectorGUI.MakeLabel(wrapper.Member) : null; var fieldContent = GUI.MakeLabel(RowLabels[i], RowColors[i]); if (wrapper.IsType <float>()) { EditorGUI.showMixedValue = !wrapper.AreValuesEqual(rowDataInstances); var value = InspectorGUI.CustomFloatField(labelContent, fieldContent, wrapper.Get <float>(refTransOrRotRowData[i]?.RowData)); if (UnityEngine.GUI.changed) { foreach (var constraintParser in constraintsParser) { wrapper.ConditionalSet(constraintParser[rowType][i]?.RowData, value); } } } else if (wrapper.IsType <RangeReal>()) { EditorGUI.showMixedValue = rowDataInstances.Any(rowData => !Equals(wrapper.Get <RangeReal>(refTransOrRotRowData[i]?.RowData).Min, wrapper.Get <RangeReal>(rowData).Min)) || rowDataInstances.Any(rowData => !Equals(wrapper.Get <RangeReal>(refTransOrRotRowData[i]?.RowData).Max, wrapper.Get <RangeReal>(rowData).Max)); var rangeChangeData = InspectorGUI.RangeRealField(labelContent, wrapper.Get <RangeReal>(refTransOrRotRowData[i]?.RowData), GUI.MakeLabel(RowLabels[i], RowColors[i])); if (rangeChangeData.MinChanged || rangeChangeData.MaxChanged) { foreach (var constraintParser in constraintsParser) { var range = wrapper.Get <RangeReal>(constraintParser[rowType][i].RowData); if (rangeChangeData.MinChanged) { range.Min = rangeChangeData.Min; } if (rangeChangeData.MaxChanged) { range.Max = rangeChangeData.Max; } // Validation of Min > Max has to go somewhere else because if e.g., // Min = 50 and the user wants to type Max = 200 we're receiving // Max = 2 as the user types. wrapper.ConditionalSet(constraintParser[rowType][i].RowData, range); } } } } UnityEngine.GUI.changed = false; EditorGUI.showMixedValue = false; } } // For type wrappers. } // Indentation. } // For Translational, Rotational. var ecControllers = refConstraint.GetElementaryConstraintControllers(); if (ecControllers.Length > 0 && InspectorGUI.Foldout(selected("controllers"), GUI.MakeLabel("Controllers", true))) { using (InspectorGUI.IndentScope.Single) { foreach (var refController in ecControllers) { var controllerType = refController.GetControllerType(); var controllerTypeTag = controllerType.ToString()[0].ToString(); var controllerName = ConstraintUtils.FindName(refController); if (controllerName.EndsWith(" Controller")) { controllerName = controllerName.Remove(controllerName.LastIndexOf(" Controller")); } var controllerLabel = GUI.MakeLabel((controllerType == Constraint.ControllerType.Rotational ? GUI.Symbols.CircleArrowAcw.ToString() + " " : GUI.Symbols.ArrowRight.ToString() + " ") + controllerName, true); if (!InspectorGUI.Foldout(selected(controllerTypeTag + controllerName), controllerLabel)) { continue; } var controllers = (from constraint in constraints from controller in constraint.GetElementaryConstraintControllers() where controller.GetType() == refController.GetType() && controller.GetControllerType() == refController.GetControllerType() select controller).ToArray(); using (InspectorGUI.IndentScope.Single) { InspectorEditor.DrawMembersGUI(controllers); InspectorEditor.DrawMembersGUI(controllers, controller => (controller as ElementaryConstraint).RowData[0]); } } } } }