@@ -2268,7 +2268,7 @@ internal static void DoNumberField(RecycledTextEditor editor, Rect position, Rec
22682268 {
22692269 bool changed;
22702270 string allowedCharacters = value.isDouble ? s_AllowedCharactersForFloat : s_AllowedCharactersForInt;
2271- if (draggable)
2271+ if (draggable && GUI.enabled )
22722272 {
22732273 DragNumberValue(dragHotZone, id, ref value, dragSensitivity);
22742274 }
@@ -4197,7 +4197,7 @@ public static Vector2 Vector2Field(Rect position, GUIContent label, Vector2 valu
41974197 internal static Vector2 Vector2Field(Rect position, GUIContent label, Vector2 value, bool setWideMode)
41984198 {
41994199 int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);
4200- position = MultiFieldPrefixLabel(position, id, label, 2, setWideMode);
4200+ position = MultiFieldPrefixLabel(position, id, label, 2, 0, setWideMode);
42014201 position.height = kSingleLineHeight;
42024202 return Vector2Field(position, value);
42034203 }
@@ -4251,40 +4251,107 @@ private static Vector3 Vector3Field(Rect position, Vector3 value)
42514251 return value;
42524252 }
42534253
4254- internal static Vector3 LinkedVector3Field(Rect position, GUIContent label, Vector3 value, ref bool linked )
4254+ internal static Vector3 LinkedVector3Field(Rect position, GUIContent label, Vector3 value, ref bool proportionalScale )
42554255 {
4256- int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);
4257- position = MultiFieldPrefixLabel(position, id, label, 3);
4256+ int axisModified = 0;// use X as default modified axis
4257+ return LinkedVector3Field(position, label, GUIContent.none, value, ref proportionalScale, value, 0, ref axisModified);
4258+ }
4259+
4260+ // Make an X, Y & Z field for entering a [[Vector3]], with a "lock"
4261+ internal static Vector3 LinkedVector3Field(Rect position, GUIContent label, GUIContent toggleContent, Vector3 value, ref bool proportionalScale, Vector3 initialScale, uint mixedValues, ref int axisModified, SerializedProperty property = null, SerializedProperty proportionalScaleProperty = null)
4262+ {
4263+ GUIContent copy = label;
4264+ Rect fullLabelRect = position;
4265+ // If SerializedProperty is passed, make sure to call begin and end for property
4266+
4267+ // Since we have two separate properties to handle, make sure fields are not overlaping each other
4268+ // If only localScale property has override, make sure constrainProportionsScale property is in the layer behind
4269+ if (proportionalScaleProperty != null && property.prefabOverride && !proportionalScale)
4270+ label = BeginPropertyInternal(fullLabelRect, label, proportionalScaleProperty);
4271+
4272+ if (property != null)
4273+ label = BeginPropertyInternal(position, label, property);
4274+
4275+ SerializedProperty copiedProperty = property == null ? property : property.Copy();
42584276 var toggle = EditorStyles.toggle.CalcSize(GUIContent.none);
4277+ int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);
4278+ position = MultiFieldPrefixLabel(position, id, label, 3, toggle.x + kDefaultSpacing, false);
42594279 var toggleRect = position;
42604280 toggleRect.width = toggle.x;
4281+ float toggleOffset = toggleRect.width + kDefaultSpacing;
4282+ toggleRect.x -= toggleOffset;
4283+ toggle.x -= toggleOffset;
42614284 BeginChangeCheck();
42624285 Styles.linkButton.alignment = TextAnchor.MiddleCenter;
4263- linked = Toggle(toggleRect, linked, Styles.linkButton);
4264- if (EndChangeCheck() && linked)
4265- value = Vector3.one * value.x;
4286+
4287+ if (proportionalScaleProperty != null)
4288+ {
4289+ // If localScale property does not have override, make sure proportionalScale is in front layer
4290+ if (!property.prefabOverride || proportionalScale)
4291+ {
4292+ // If proportional scaling is enabled, make sure to use full scale rect, to be able revert all axis and state at the same time,
4293+ // otherwise rect size should match label size
4294+ if (!proportionalScale)
4295+ fullLabelRect.xMax = toggleRect.xMin;
4296+
4297+ label = BeginPropertyInternal(fullLabelRect, label, proportionalScaleProperty);
4298+ }
4299+
4300+ BeginChangeCheck();
4301+ bool previousProportionalScale = proportionalScale;
4302+ proportionalScale = GUI.Toggle(toggleRect, proportionalScale, toggleContent, Styles.linkButton);
4303+ if (previousProportionalScale != proportionalScale)
4304+ proportionalScaleProperty.boolValue = proportionalScale;
4305+ EndChangeCheck();
4306+
4307+ if (proportionalScale)
4308+ EndProperty();
4309+ }
4310+ else
4311+ {
4312+ proportionalScale = GUI.Toggle(toggleRect, proportionalScale, toggleContent, Styles.linkButton);
4313+ }
4314+
42664315 position.x += toggle.x + kDefaultSpacing;
42674316 position.width -= toggle.x + kDefaultSpacing;
42684317 position.height = kSingleLineHeight;
4269- return LinkedVector3Field(position, value, linked);
4318+
4319+ var newValue = LinkedVector3Field(position, value, proportionalScale, mixedValues, initialScale, ref axisModified, copiedProperty);
4320+
4321+ if (property != null)
4322+ EndProperty();
4323+
4324+ if (proportionalScaleProperty != null && property.prefabOverride && !proportionalScale)
4325+ EndProperty();
4326+
4327+ return newValue;
4328+ }
4329+
4330+ static Vector3 LinkedVector3Field(Rect position, Vector3 value, bool proportionalScale)
4331+ {
4332+ int axisModified = 0;// Use X as default modified axis
4333+ return LinkedVector3Field(position, value, proportionalScale, 0, value, ref axisModified);
42704334 }
42714335
42724336 // Make an X, Y & Z field for entering a [[Vector3]].
4273- static Vector3 LinkedVector3Field(Rect position, Vector3 value, bool linked )
4337+ static Vector3 LinkedVector3Field(Rect position, Vector3 value, bool proportionalScale, uint mixedValues, Vector3 initialScale, ref int axisModified, SerializedProperty property = null )
42744338 {
4339+ Vector3 valueAfterChangeCheck = value;
42754340 s_Vector3Floats[0] = value.x;
42764341 s_Vector3Floats[1] = value.y;
42774342 s_Vector3Floats[2] = value.z;
42784343 position.height = kSingleLineHeight;
42794344 BeginChangeCheck();
4280- LockingMultiFloatFieldInternal(position, linked, s_XYZLabels, s_Vector3Floats);
4345+ LockingMultiFloatFieldInternal(position, proportionalScale, mixedValues, s_XYZLabels, s_Vector3Floats, new float[] {initialScale.x, initialScale.y, initialScale.z}, property, EditorGUI.CalcPrefixLabelWidth(s_XYZLabels[0]) + 3 );
42814346 if (EndChangeCheck())
42824347 {
4283- value .x = s_Vector3Floats[0];
4284- value .y = s_Vector3Floats[1];
4285- value .z = s_Vector3Floats[2];
4348+ valueAfterChangeCheck .x = s_Vector3Floats[0];
4349+ valueAfterChangeCheck .y = s_Vector3Floats[1];
4350+ valueAfterChangeCheck .z = s_Vector3Floats[2];
42864351 }
4287- return value;
4352+
4353+ return proportionalScale && valueAfterChangeCheck != value ?
4354+ ConstrainProportionsTransformScale.DoScaleProportions(valueAfterChangeCheck, value, initialScale, ref axisModified) : valueAfterChangeCheck;
42884355 }
42894356
42904357 // Make an X, Y field - not public (use PropertyField instead)
@@ -4735,6 +4802,11 @@ internal static void MultiFloatFieldInternal(Rect position, GUIContent[] subLabe
47354802 }
47364803
47374804 static void LockingMultiFloatFieldInternal(Rect position, bool locked, GUIContent[] subLabels, float[] values, float prefixLabelWidth = -1)
4805+ {
4806+ LockingMultiFloatFieldInternal(position, locked, 0, subLabels, values, null, null, prefixLabelWidth);
4807+ }
4808+
4809+ static void LockingMultiFloatFieldInternal(Rect position, bool locked, uint mixedValues, GUIContent[] subLabels, float[] values, float[] initialValues = null, SerializedProperty property = null, float prefixLabelWidth = -1)
47384810 {
47394811 int eCount = values.Length;
47404812 float w = (position.width - (eCount - 1) * EditorGUI.kSpacingSubLabel) / eCount;
@@ -4743,20 +4815,53 @@ static void LockingMultiFloatFieldInternal(Rect position, bool locked, GUIConten
47434815 int l = EditorGUI.indentLevel;
47444816 EditorGUI.indentLevel = 0;
47454817 var guiEnabledState = GUI.enabled;
4746- for (int i = 0; i < values.Length; i++)
4818+ bool hasMixedValues = mixedValues != 0;
4819+ uint multiselectionLock = ConstrainProportionsTransformScale.GetMultiSelectionLockedFields(property?.serializedObject?.targetObjects);
4820+
4821+ if (initialValues == null)
4822+ initialValues = values;
4823+
4824+ bool mixedValueState = EditorGUI.showMixedValue;
4825+
4826+ for (int i = 0; i < initialValues.Length; i++)
47474827 {
4748- EditorGUIUtility.labelWidth = GetLabelWidth(subLabels[i], prefixLabelWidth);
4828+ if (property != null)
4829+ property.Next(true);
4830+ EditorGUIUtility.labelWidth = prefixLabelWidth > 0 ? prefixLabelWidth : EditorGUI.CalcPrefixLabelWidth(subLabels[i]);
47494831
4750- if (locked && i > 0 )
4832+ if (guiEnabledState )
47514833 {
4752- GUI.enabled = false;
4753- values[i] = values[0];
4834+ if (locked)
4835+ {
4836+ // If initial field value is 0, it must be locked not to break proportions
4837+ GUI.enabled = !Mathf.Approximately(initialValues[i], 0) && (property != null && property.serializedObject.targetObjectsCount > 1 ? !ConstrainProportionsTransformScale.IsBit(multiselectionLock, i) : true);
4838+ }
4839+ else
4840+ {
4841+ GUI.enabled = true;
4842+ }
4843+ }
4844+
4845+ if (hasMixedValues)
4846+ EditorGUI.showMixedValue = ConstrainProportionsTransformScale.IsBit(mixedValues, i);
4847+
4848+ if (property != null)
4849+ {
4850+ EditorGUI.PropertyField(nr, property, subLabels[i]);
4851+ values[i] = property.floatValue;
47544852 }
4853+ else
4854+ {
4855+ values[i] = EditorGUI.FloatField(nr, subLabels[i], values[i]);
4856+ }
4857+
4858+ if (hasMixedValues)
4859+ EditorGUI.showMixedValue = false;
47554860
4756- values[i] = EditorGUI.FloatField(nr, subLabels[i], values[i]);
47574861 nr.x += w + EditorGUI.kSpacingSubLabel;
47584862 }
47594863 GUI.enabled = guiEnabledState;
4864+ EditorGUI.showMixedValue = mixedValueState;
47604865 EditorGUIUtility.labelWidth = t;
47614866 EditorGUI.indentLevel = l;
47624867 }
@@ -6144,7 +6249,6 @@ internal static void HandlePrefixLabelInternal(Rect totalPosition, Rect labelPos
61446249 if (label != null) Highlighter.Handle(totalPosition, label.text);
61456250 }
61466251
6147- // DrawTextDebugHelpers (labelPosition);
61486252 switch (Event.current.type)
61496253 {
61506254 case EventType.Repaint:
@@ -6213,10 +6317,10 @@ internal static bool UseVTMaterial(Texture texture)
62136317
62146318 internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns)
62156319 {
6216- return MultiFieldPrefixLabel(totalPosition, id, label, columns, false);
6320+ return MultiFieldPrefixLabel(totalPosition, id, label, columns, 0, false);
62176321 }
62186322
6219- internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns, bool setWideMode)
6323+ internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns, float labelWidthIndent, bool setWideMode)
62206324 {
62216325 if (!LabelHasContent(label))
62226326 {
@@ -6225,7 +6329,7 @@ internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIConten
62256329
62266330 if (EditorGUIUtility.wideMode || setWideMode)
62276331 {
6228- Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, kSingleLineHeight);
6332+ Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent - labelWidthIndent , kSingleLineHeight);
62296333 Rect fieldPosition = totalPosition;
62306334 fieldPosition.xMin += EditorGUIUtility.labelWidth + kPrefixPaddingRight;
62316335
@@ -9763,11 +9867,19 @@ public static Vector3 Vector3Field(GUIContent label, Vector3 value, params GUILa
97639867 return EditorGUI.Vector3Field(r, label, value);
97649868 }
97659869
9766- // Make an X, Y & Z field for entering a [[Vector3]], with a "lock" to set all values with just the X field.
9767- internal static Vector3 LinkedVector3Field(GUIContent label, Vector3 value, ref bool linked, params GUILayoutOption[] options)
9870+ // Make an X, Y & Z field for entering a [[Vector3]], with a "lock"
9871+ internal static Vector3 LinkedVector3Field(GUIContent label, Vector3 value, ref bool proportionalScale, params GUILayoutOption[] options)
9872+ {
9873+ Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options);
9874+ return EditorGUI.LinkedVector3Field(r, label, value, ref proportionalScale);
9875+ }
9876+
9877+ // Make an X, Y & Z field for entering a [[Vector3]], with a "lock"
9878+ internal static Vector3 LinkedVector3Field(GUIContent label, Vector3 value, Vector3 initialValue, ref bool proportionalScale, params GUILayoutOption[] options)
97689879 {
97699880 Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options);
9770- return EditorGUI.LinkedVector3Field(r, label, value, ref linked);
9881+ int axisModified = 0;// Use X as default modified axis
9882+ return EditorGUI.LinkedVector3Field(r, label, GUIContent.none, value, ref proportionalScale, initialValue, 0, ref axisModified, null);
97719883 }
97729884
97739885 // Make an X, Y, Z & W field for entering a [[Vector4]].
0 commit comments