diff --git a/Source/Editor/CustomEditors/CustomEditor.cs b/Source/Editor/CustomEditors/CustomEditor.cs index d5f6c5667..6b7bd4601 100644 --- a/Source/Editor/CustomEditors/CustomEditor.cs +++ b/Source/Editor/CustomEditors/CustomEditor.cs @@ -1,6 +1,7 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using FlaxEditor.CustomEditors.GUI; @@ -300,8 +301,16 @@ namespace FlaxEditor.CustomEditors _valueToSet = null; // Assign value - for (int i = 0; i < _values.Count; i++) - _values[i] = val; + if (val is IList l && l.Count == _values.Count) + { + for (int i = 0; i < _values.Count; i++) + _values[i] = l[i]; + } + else + { + for (int i = 0; i < _values.Count; i++) + _values[i] = val; + } } finally { diff --git a/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs b/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs index 96f9d0646..0da35aa4f 100644 --- a/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs @@ -33,6 +33,15 @@ namespace FlaxEditor.CustomEditors.Editors /// public override DisplayStyle Style => DisplayStyle.Inline; + + /// + /// Whether to use the average for sliding different values. + /// + public virtual bool AllowSlidingForDifferentValues => true; + + private ValueChanged _valueChanged; + private float _defaultSlidingSpeed; + private bool _slidingEnded = false; /// public override void Initialize(LayoutElementsContainer layout) @@ -46,18 +55,31 @@ namespace FlaxEditor.CustomEditors.Editors XElement = grid.FloatValue(); XElement.ValueBox.Category = Utils.ValueCategory.Angle; - XElement.ValueBox.ValueChanged += OnValueChanged; - XElement.ValueBox.SlidingEnd += ClearToken; + XElement.ValueBox.ValueChanged += OnXValueChanged; + XElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; + _defaultSlidingSpeed = XElement.ValueBox.SlideSpeed; YElement = grid.FloatValue(); YElement.ValueBox.Category = Utils.ValueCategory.Angle; - YElement.ValueBox.ValueChanged += OnValueChanged; - YElement.ValueBox.SlidingEnd += ClearToken; + YElement.ValueBox.ValueChanged += OnYValueChanged; + YElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; ZElement = grid.FloatValue(); ZElement.ValueBox.Category = Utils.ValueCategory.Angle; - ZElement.ValueBox.ValueChanged += OnValueChanged; - ZElement.ValueBox.SlidingEnd += ClearToken; + ZElement.ValueBox.ValueChanged += OnZValueChanged; + ZElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; if (LinkedLabel != null) { @@ -69,33 +91,118 @@ namespace FlaxEditor.CustomEditors.Editors }; } } - - private void OnValueChanged() + + private void OnXValueChanged() { if (IsSetBlocked) return; + _valueChanged = ValueChanged.X; + OnValueChanged(); + } + private void OnYValueChanged() + { + if (IsSetBlocked) + return; + _valueChanged = ValueChanged.Y; + OnValueChanged(); + } + + private void OnZValueChanged() + { + if (IsSetBlocked) + return; + _valueChanged = ValueChanged.Z; + OnValueChanged(); + } + + private void OnValueChanged() + { var isSliding = XElement.IsSliding || YElement.IsSliding || ZElement.IsSliding; var token = isSliding ? this : null; var useCachedAngles = isSliding && token == _cachedToken; - - float x = (useCachedAngles && !XElement.IsSliding) ? _cachedAngles.X : XElement.ValueBox.Value; - float y = (useCachedAngles && !YElement.IsSliding) ? _cachedAngles.Y : YElement.ValueBox.Value; - float z = (useCachedAngles && !ZElement.IsSliding) ? _cachedAngles.Z : ZElement.ValueBox.Value; - - x = Mathf.UnwindDegrees(x); - y = Mathf.UnwindDegrees(y); - z = Mathf.UnwindDegrees(z); - - if (!useCachedAngles) + + if (HasDifferentValues && Values.Count > 1) { - _cachedAngles = new Float3(x, y, z); + var xValue = XElement.ValueBox.Value; + var yValue = YElement.ValueBox.Value; + var zValue = ZElement.ValueBox.Value; + + xValue = Mathf.UnwindDegrees(xValue); + yValue = Mathf.UnwindDegrees(yValue); + zValue = Mathf.UnwindDegrees(zValue); + + var value = new Float3(xValue, yValue, zValue); + + _cachedToken = token; + + var newObjects = new object[Values.Count]; + // Handle Sliding + if (AllowSlidingForDifferentValues && (isSliding || _slidingEnded)) + { + Float3 average = Float3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var v = (Quaternion)Values[0]; + var euler = v.EulerAngles; + + average += euler; + } + + average /= Values.Count; + + var newValue = value - average; + + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + var val = (Quaternion)v; + Quaternion.Euler(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0, out Quaternion qVal); + v = val * qVal; + + newObjects[i] = v; + } + + // Capture last sliding value + if (_slidingEnded) + _slidingEnded = false; + } + else + { + for (int i = 0; i < Values.Count; i++) + { + object v = Values[i]; + var val = (Quaternion)v; + var euler = val.EulerAngles; + Quaternion.Euler(_valueChanged == ValueChanged.X ? xValue : euler.X, _valueChanged == ValueChanged.Y ? yValue : euler.Y, _valueChanged == ValueChanged.Z ? zValue : euler.Z, out Quaternion qVal); + v = val * qVal; + + newObjects[i] = v; + } + } + + SetValue(newObjects, token); } + else + { + float x = (useCachedAngles && !XElement.IsSliding) ? _cachedAngles.X : XElement.ValueBox.Value; + float y = (useCachedAngles && !YElement.IsSliding) ? _cachedAngles.Y : YElement.ValueBox.Value; + float z = (useCachedAngles && !ZElement.IsSliding) ? _cachedAngles.Z : ZElement.ValueBox.Value; - _cachedToken = token; + x = Mathf.UnwindDegrees(x); + y = Mathf.UnwindDegrees(y); + z = Mathf.UnwindDegrees(z); - Quaternion.Euler(x, y, z, out Quaternion value); - SetValue(value, token); + if (!useCachedAngles) + { + _cachedAngles = new Float3(x, y, z); + } + + _cachedToken = token; + + Quaternion.Euler(x, y, z, out Quaternion value); + SetValue(value, token); + } } /// @@ -112,7 +219,73 @@ namespace FlaxEditor.CustomEditors.Editors if (HasDifferentValues) { - // TODO: support different values for ValueBox + // Get which values are different + bool xDifferent = false; + bool yDifferent = false; + bool zDifferent = false; + Float3 cachedFirstValue = Float3.Zero; + Float3 average = Float3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var value = (Quaternion)Values[i]; + var euler = value.EulerAngles; + + average += euler; + + if (i == 0) + { + cachedFirstValue = euler; + continue; + } + + if (!Mathf.NearEqual(cachedFirstValue.X, value.X)) + xDifferent = true; + if (!Mathf.NearEqual(cachedFirstValue.Y, value.Y)) + yDifferent = true; + if (!Mathf.NearEqual(cachedFirstValue.Z, value.Z)) + zDifferent = true; + } + + average /= Values.Count; + + if (!xDifferent) + { + XElement.ValueBox.Value = cachedFirstValue.X; + } + else + { + if (AllowSlidingForDifferentValues) + XElement.ValueBox.Value = average.X; + else + XElement.ValueBox.SlideSpeed = 0; + XElement.ValueBox.Text = "---"; + } + + if (!yDifferent) + { + YElement.ValueBox.Value = cachedFirstValue.Y; + } + else + { + if (AllowSlidingForDifferentValues) + YElement.ValueBox.Value = average.Y; + else + YElement.ValueBox.SlideSpeed = 0; + YElement.ValueBox.Text = "---"; + } + + if (!zDifferent) + { + ZElement.ValueBox.Value = cachedFirstValue.Z; + } + else + { + if (AllowSlidingForDifferentValues) + ZElement.ValueBox.Value = average.Z; + else + ZElement.ValueBox.SlideSpeed = 0; + ZElement.ValueBox.Text = "---"; + } } else { @@ -121,6 +294,13 @@ namespace FlaxEditor.CustomEditors.Editors XElement.ValueBox.Value = euler.X; YElement.ValueBox.Value = euler.Y; ZElement.ValueBox.Value = euler.Z; + + if (!Mathf.NearEqual(XElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + XElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + if (!Mathf.NearEqual(YElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + YElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + if (!Mathf.NearEqual(ZElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + ZElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; } } } diff --git a/Source/Editor/CustomEditors/Editors/Vector3Editor.cs b/Source/Editor/CustomEditors/Editors/Vector3Editor.cs index 80fe7e205..9e01e8323 100644 --- a/Source/Editor/CustomEditors/Editors/Vector3Editor.cs +++ b/Source/Editor/CustomEditors/Editors/Vector3Editor.cs @@ -7,6 +7,27 @@ using FlaxEngine.GUI; namespace FlaxEditor.CustomEditors.Editors { + /// + /// The value changed by custom Vector3 editors. + /// + public enum ValueChanged + { + /// + /// X value changed. + /// + X = 0, + + /// + /// Y value changed. + /// + Y = 1, + + /// + /// Z value changed. + /// + Z = 2 + } + /// /// Default implementation of the inspector used to edit Vector3 value type properties. /// @@ -49,14 +70,14 @@ namespace FlaxEditor.CustomEditors.Editors /// public bool LinkValues = false; - private enum ValueChanged - { - X = 0, - Y = 1, - Z = 2 - } + /// + /// Whether to use the average for sliding different values. + /// + public virtual bool AllowSlidingForDifferentValues => true; private ValueChanged _valueChanged; + private float _defaultSlidingSpeed; + private bool _slidingEnded = false; /// public override void Initialize(LayoutElementsContainer layout) @@ -83,19 +104,32 @@ namespace FlaxEditor.CustomEditors.Editors XElement.SetLimits(limit); XElement.SetCategory(category); XElement.ValueBox.ValueChanged += OnXValueChanged; - XElement.ValueBox.SlidingEnd += ClearToken; + XElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; + _defaultSlidingSpeed = XElement.ValueBox.SlideSpeed; YElement = grid.FloatValue(); YElement.SetLimits(limit); YElement.SetCategory(category); YElement.ValueBox.ValueChanged += OnYValueChanged; - YElement.ValueBox.SlidingEnd += ClearToken; + YElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; ZElement = grid.FloatValue(); ZElement.SetLimits(limit); ZElement.SetCategory(category); ZElement.ValueBox.ValueChanged += OnZValueChanged; - ZElement.ValueBox.SlidingEnd += ClearToken; + ZElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; if (LinkedLabel != null) { @@ -118,8 +152,7 @@ namespace FlaxEditor.CustomEditors.Editors { if (IsSetBlocked) return; - if (LinkValues) - _valueChanged = ValueChanged.X; + _valueChanged = ValueChanged.X; OnValueChanged(); } @@ -127,8 +160,7 @@ namespace FlaxEditor.CustomEditors.Editors { if (IsSetBlocked) return; - if (LinkValues) - _valueChanged = ValueChanged.Y; + _valueChanged = ValueChanged.Y; OnValueChanged(); } @@ -136,8 +168,7 @@ namespace FlaxEditor.CustomEditors.Editors { if (IsSetBlocked) return; - if (LinkValues) - _valueChanged = ValueChanged.Z; + _valueChanged = ValueChanged.Z; OnValueChanged(); } @@ -191,14 +222,79 @@ namespace FlaxEditor.CustomEditors.Editors var isSliding = XElement.IsSliding || YElement.IsSliding || ZElement.IsSliding; var token = isSliding ? this : null; var value = new Float3(xValue, yValue, zValue); - object v = Values[0]; - if (v is Vector3) - v = (Vector3)value; - else if (v is Float3) - v = (Float3)value; - else if (v is Double3) - v = (Double3)value; - SetValue(v, token); + if (HasDifferentValues && Values.Count > 1) + { + var newObjects = new object[Values.Count]; + // Handle Sliding + if (AllowSlidingForDifferentValues && (isSliding || _slidingEnded)) + { + // TODO: handle linked values + Float3 average = Float3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + var castedValue = Float3.Zero; + if (v is Vector3 asVector3) + castedValue = asVector3; + else if (v is Float3 asFloat3) + castedValue = asFloat3; + else if (v is Double3 asDouble3) + castedValue = asDouble3; + + average += castedValue; + } + + average /= Values.Count; + + var newValue = value - average; + + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + if (v is Vector3 asVector3) + v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0); + else if (v is Float3 asFloat3) + v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0); + else if (v is Double3 asDouble3) + v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0); + + newObjects[i] = v; + } + + // Capture last sliding value + if (_slidingEnded) + _slidingEnded = false; + } + else + { + // TODO: handle linked values + for (int i = 0; i < Values.Count; i++) + { + object v = Values[i]; + if (v is Vector3 asVector3) + v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z); + else if (v is Float3 asFloat3) + v = new Float3(_valueChanged == ValueChanged.X ? xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? zValue : asFloat3.Z); + else if (v is Double3 asDouble3) + v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z); + + newObjects[i] = v; + } + } + + SetValue(newObjects, token); + } + else + { + object v = Values[0]; + if (v is Vector3) + v = (Vector3)value; + else if (v is Float3) + v = (Float3)value; + else if (v is Double3) + v = (Double3)value; + SetValue(v, token); + } } private float GetRatio(float value, float initialValue) @@ -218,7 +314,79 @@ namespace FlaxEditor.CustomEditors.Editors if (HasDifferentValues) { - // TODO: support different values for ValueBox + // Get which values are different + bool xDifferent = false; + bool yDifferent = false; + bool zDifferent = false; + Float3 cachedFirstValue = Float3.Zero; + Float3 average = Float3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + var value = Float3.Zero; + if (v is Vector3 asVector3) + value = asVector3; + else if (v is Float3 asFloat3) + value = asFloat3; + else if (v is Double3 asDouble3) + value = asDouble3; + + average += value; + + if (i == 0) + { + cachedFirstValue = value; + continue; + } + + if (!Mathf.NearEqual(cachedFirstValue.X, value.X)) + xDifferent = true; + if (!Mathf.NearEqual(cachedFirstValue.Y, value.Y)) + yDifferent = true; + if (!Mathf.NearEqual(cachedFirstValue.Z, value.Z)) + zDifferent = true; + } + + average /= Values.Count; + + if (!xDifferent) + { + XElement.ValueBox.Value = cachedFirstValue.X; + } + else + { + if (AllowSlidingForDifferentValues) + XElement.ValueBox.Value = average.X; + else + XElement.ValueBox.SlideSpeed = 0; + XElement.ValueBox.Text = "---"; + } + + if (!yDifferent) + { + YElement.ValueBox.Value = cachedFirstValue.Y; + } + else + { + if (AllowSlidingForDifferentValues) + YElement.ValueBox.Value = average.Y; + else + YElement.ValueBox.SlideSpeed = 0; + YElement.ValueBox.Text = "---"; + } + + if (!zDifferent) + { + ZElement.ValueBox.Value = cachedFirstValue.Z; + } + else + { + if (AllowSlidingForDifferentValues) + ZElement.ValueBox.Value = average.Z; + else + ZElement.ValueBox.SlideSpeed = 0; + ZElement.ValueBox.Text = "---"; + } } else { @@ -232,6 +400,13 @@ namespace FlaxEditor.CustomEditors.Editors XElement.ValueBox.Value = value.X; YElement.ValueBox.Value = value.Y; ZElement.ValueBox.Value = value.Z; + + if (!Mathf.NearEqual(XElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + XElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + if (!Mathf.NearEqual(YElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + YElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + if (!Mathf.NearEqual(ZElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + ZElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; } } } @@ -259,6 +434,15 @@ namespace FlaxEditor.CustomEditors.Editors /// public override DisplayStyle Style => DisplayStyle.Inline; + + /// + /// Whether to use the average for sliding different values. + /// + public virtual bool AllowSlidingForDifferentValues => true; + + private ValueChanged _valueChanged; + private float _defaultSlidingSpeed; + private bool _slidingEnded = false; /// public override void Initialize(LayoutElementsContainer layout) @@ -284,20 +468,33 @@ namespace FlaxEditor.CustomEditors.Editors XElement = grid.DoubleValue(); XElement.SetLimits(limit); XElement.SetCategory(category); - XElement.ValueBox.ValueChanged += OnValueChanged; - XElement.ValueBox.SlidingEnd += ClearToken; + XElement.ValueBox.ValueChanged += OnXValueChanged; + XElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; + _defaultSlidingSpeed = XElement.ValueBox.SlideSpeed; YElement = grid.DoubleValue(); YElement.SetLimits(limit); YElement.SetCategory(category); - YElement.ValueBox.ValueChanged += OnValueChanged; - YElement.ValueBox.SlidingEnd += ClearToken; + YElement.ValueBox.ValueChanged += OnYValueChanged; + YElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; ZElement = grid.DoubleValue(); ZElement.SetLimits(limit); ZElement.SetCategory(category); - ZElement.ValueBox.ValueChanged += OnValueChanged; - ZElement.ValueBox.SlidingEnd += ClearToken; + ZElement.ValueBox.ValueChanged += OnZValueChanged; + ZElement.ValueBox.SlidingEnd += () => + { + _slidingEnded = true; + ClearToken(); + }; if (LinkedLabel != null) { @@ -316,22 +513,115 @@ namespace FlaxEditor.CustomEditors.Editors } } + private void OnXValueChanged() + { + if (IsSetBlocked) + return; + _valueChanged = ValueChanged.X; + OnValueChanged(); + } + + private void OnYValueChanged() + { + if (IsSetBlocked) + return; + _valueChanged = ValueChanged.Y; + OnValueChanged(); + } + + private void OnZValueChanged() + { + if (IsSetBlocked) + return; + _valueChanged = ValueChanged.Z; + OnValueChanged(); + } + private void OnValueChanged() { if (IsSetBlocked || Values == null) return; + var xValue = XElement.ValueBox.Value; + var yValue = YElement.ValueBox.Value; + var zValue = ZElement.ValueBox.Value; + var isSliding = XElement.IsSliding || YElement.IsSliding || ZElement.IsSliding; var token = isSliding ? this : null; - var value = new Double3(XElement.ValueBox.Value, YElement.ValueBox.Value, ZElement.ValueBox.Value); - object v = Values[0]; - if (v is Vector3) - v = (Vector3)value; - else if (v is Float3) - v = (Float3)value; - else if (v is Double3) - v = (Double3)value; - SetValue(v, token); + var value = new Double3(xValue, yValue, zValue); + if (HasDifferentValues && Values.Count > 1) + { + var newObjects = new object[Values.Count]; + // Handle Sliding + if (AllowSlidingForDifferentValues && (isSliding || _slidingEnded)) + { + // TODO: handle linked values + Double3 average = Double3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + var castedValue = Double3.Zero; + if (v is Vector3 asVector3) + castedValue = asVector3; + else if (v is Float3 asFloat3) + castedValue = asFloat3; + else if (v is Double3 asDouble3) + castedValue = asDouble3; + + average += castedValue; + } + + average /= Values.Count; + + var newValue = value - average; + + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + if (v is Vector3 asVector3) + v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0); + else if (v is Float3 asFloat3) + v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? (float)newValue.X : 0, _valueChanged == ValueChanged.Y ? (float)newValue.Y : 0, _valueChanged == ValueChanged.Z ? (float)newValue.Z : 0); + else if (v is Double3 asDouble3) + v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0); + + newObjects[i] = v; + } + + // Capture last sliding value + if (_slidingEnded) + _slidingEnded = false; + } + else + { + // TODO: handle linked values + for (int i = 0; i < Values.Count; i++) + { + object v = Values[i]; + if (v is Vector3 asVector3) + v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z); + else if (v is Float3 asFloat3) + v = new Float3(_valueChanged == ValueChanged.X ? (float)xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? (float)yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? (float)zValue : asFloat3.Z); + else if (v is Double3 asDouble3) + v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z); + + newObjects[i] = v; + } + } + + SetValue(newObjects, token); + } + else + { + object v = Values[0]; + if (v is Vector3) + v = (Vector3)value; + else if (v is Float3) + v = (Float3)value; + else if (v is Double3) + v = (Double3)value; + SetValue(v, token); + } } /// @@ -341,7 +631,79 @@ namespace FlaxEditor.CustomEditors.Editors if (HasDifferentValues) { - // TODO: support different values for ValueBox + // Get which values are different + bool xDifferent = false; + bool yDifferent = false; + bool zDifferent = false; + Double3 cachedFirstValue = Double3.Zero; + Double3 average = Double3.Zero; + for (int i = 0; i < Values.Count; i++) + { + var v = Values[i]; + var value = Double3.Zero; + if (v is Vector3 asVector3) + value = asVector3; + else if (v is Float3 asFloat3) + value = asFloat3; + else if (v is Double3 asDouble3) + value = asDouble3; + + average += value; + + if (i == 0) + { + cachedFirstValue = value; + continue; + } + + if (!Mathd.NearEqual(cachedFirstValue.X, value.X)) + xDifferent = true; + if (!Mathd.NearEqual(cachedFirstValue.Y, value.Y)) + yDifferent = true; + if (!Mathd.NearEqual(cachedFirstValue.Z, value.Z)) + zDifferent = true; + } + + average /= Values.Count; + + if (!xDifferent) + { + XElement.ValueBox.Value = cachedFirstValue.X; + } + else + { + if (AllowSlidingForDifferentValues) + XElement.ValueBox.Value = average.X; + else + XElement.ValueBox.SlideSpeed = 0; + XElement.ValueBox.Text = "---"; + } + + if (!yDifferent) + { + YElement.ValueBox.Value = cachedFirstValue.Y; + } + else + { + if (AllowSlidingForDifferentValues) + YElement.ValueBox.Value = average.Y; + else + YElement.ValueBox.SlideSpeed = 0; + YElement.ValueBox.Text = "---"; + } + + if (!zDifferent) + { + ZElement.ValueBox.Value = cachedFirstValue.Z; + } + else + { + if (AllowSlidingForDifferentValues) + ZElement.ValueBox.Value = average.Z; + else + ZElement.ValueBox.SlideSpeed = 0; + ZElement.ValueBox.Text = "---"; + } } else { @@ -355,6 +717,19 @@ namespace FlaxEditor.CustomEditors.Editors XElement.ValueBox.Value = value.X; YElement.ValueBox.Value = value.Y; ZElement.ValueBox.Value = value.Z; + + if (!Mathf.NearEqual(XElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + { + XElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + } + if (!Mathf.NearEqual(YElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + { + YElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + } + if (!Mathf.NearEqual(ZElement.ValueBox.SlideSpeed, _defaultSlidingSpeed)) + { + ZElement.ValueBox.SlideSpeed = _defaultSlidingSpeed; + } } } } diff --git a/Source/Editor/CustomEditors/Values/ValueContainer.cs b/Source/Editor/CustomEditors/Values/ValueContainer.cs index c583b96c3..601d20bb9 100644 --- a/Source/Editor/CustomEditors/Values/ValueContainer.cs +++ b/Source/Editor/CustomEditors/Values/ValueContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -385,10 +386,21 @@ namespace FlaxEditor.CustomEditors if (instanceValues.Count != Count) throw new ArgumentException(); - for (int i = 0; i < Count; i++) + if (value is IList l && l.Count == Count) { - Info.SetValue(instanceValues[i], value); - this[i] = Info.GetValue(instanceValues[i]); + for (int i = 0; i < Count; i++) + { + Info.SetValue(instanceValues[i], l[i]); + this[i] = Info.GetValue(instanceValues[i]); + } + } + else + { + for (int i = 0; i < Count; i++) + { + Info.SetValue(instanceValues[i], value); + this[i] = Info.GetValue(instanceValues[i]); + } } }