diff --git a/Source/Editor/CustomEditors/CustomEditor.cs b/Source/Editor/CustomEditors/CustomEditor.cs
index 2bc9aaac8..5b86c9b13 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;
@@ -269,10 +270,18 @@ namespace FlaxEditor.CustomEditors
object val = _valueToSet;
_hasValueDirty = false;
_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..704e1c803 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,30 @@ 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();
+ };
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 +90,162 @@ 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];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ {
+ var val = (Quaternion)v;
+ Quaternion.Euler(newValue.X, 0, 0, out Quaternion qVal);
+ v = val * qVal;
+ break;
+ }
+ case ValueChanged.Y:
+ {
+ var val = (Quaternion)v;
+ Quaternion.Euler(0, newValue.Y, 0, out Quaternion qVal);
+ v = val * qVal;
+ break;
+ }
+ case ValueChanged.Z:
+ {
+ var val = (Quaternion)v;
+ Quaternion.Euler(0, 0, newValue.Z, out Quaternion qVal);
+ v = val * qVal;
+ break;
+ }
+ }
+
+ newObjects[i] = v;
+ }
+
+ // Capture last sliding value
+ if (_slidingEnded)
+ _slidingEnded = false;
+ }
+ else
+ {
+ for (int i = 0; i < Values.Count; i++)
+ {
+ object v = Values[i];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ {
+ var val = (Quaternion)v;
+ var euler = val.EulerAngles;
+ Quaternion.Euler(xValue, euler.Y, euler.Z, out Quaternion qVal);
+ v = qVal;
+ break;
+ }
+ case ValueChanged.Y:
+ {
+ var val = (Quaternion)v;
+ var euler = val.EulerAngles;
+ Quaternion.Euler(euler.X, yValue, euler.Z, out Quaternion qVal);
+ v = qVal;
+ break;
+ }
+ case ValueChanged.Z:
+ {
+ var val = (Quaternion)v;
+ var euler = val.EulerAngles;
+ Quaternion.Euler(euler.X, euler.Y, zValue, out Quaternion qVal);
+ v = qVal;
+ break;
+ }
+ }
+
+ 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 +262,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[0];
+ 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
{
diff --git a/Source/Editor/CustomEditors/Editors/Vector3Editor.cs b/Source/Editor/CustomEditors/Editors/Vector3Editor.cs
index 719fbf05d..0e8104fa6 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,121 @@ 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];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ if (v is Vector3 asVector3)
+ v = asVector3 + new Vector3(newValue.X, 0, 0);
+ else if (v is Float3 asFloat3)
+ v = asFloat3 + new Float3(newValue.X, 0, 0);
+ else if (v is Double3 asDouble3)
+ v = asDouble3 + new Double3(newValue.X, 0, 0);
+ break;
+ case ValueChanged.Y:
+ if (v is Vector3 asVector3y)
+ v = asVector3y + new Vector3(0, newValue.Y, 0);
+ else if (v is Float3 asFloat3y)
+ v = asFloat3y + new Float3(0, newValue.Y, 0);
+ else if (v is Double3 asDouble3y)
+ v = asDouble3y + new Double3(0, newValue.Y, 0);
+ break;
+ case ValueChanged.Z:
+ if (v is Vector3 asVector3z)
+ v = asVector3z + new Vector3(0, 0, newValue.Z);
+ else if (v is Float3 asFloat3z)
+ v = asFloat3z + new Float3(0, 0, newValue.Z);
+ else if (v is Double3 asDouble3z)
+ v = asDouble3z + new Double3(0, 0, newValue.Z);
+ break;
+ }
+
+ 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];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ if (v is Vector3 vx3)
+ v = new Vector3(xValue, vx3.Y, vx3.Z);
+ else if (v is Float3 fx3)
+ v = new Float3(xValue, fx3.Y, fx3.Z);
+ else if (v is Double3 dx3)
+ v = new Double3(xValue, dx3.Y, dx3.Z);
+ break;
+ case ValueChanged.Y:
+ if (v is Vector3 vy3)
+ v = new Vector3(vy3.X, yValue, vy3.Z);
+ else if (v is Float3 fy3)
+ v = new Float3(fy3.X, yValue, fy3.Z);
+ else if (v is Double3 dy3)
+ v = new Double3(dy3.X, yValue, dy3.Z);
+ break;
+ case ValueChanged.Z:
+ if (v is Vector3 vz3)
+ v = new Vector3(vz3.X, vz3.Y, zValue);
+ else if (v is Float3 fz3)
+ v = new Float3(fz3.X, fz3.Y, zValue);
+ else if (v is Double3 dz3)
+ v = new Double3(dz3.X, dz3.Y, zValue);
+ break;
+ }
+
+ 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 +356,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 +442,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;
+ }
}
}
}
@@ -259,6 +482,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 +516,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,32 +561,239 @@ 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)
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];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ if (v is Vector3 asVector3)
+ v = asVector3 + new Vector3(newValue.X, 0, 0);
+ else if (v is Float3 asFloat3)
+ v = asFloat3 + new Float3((float)newValue.X, 0, 0);
+ else if (v is Double3 asDouble3)
+ v = asDouble3 + new Double3(newValue.X, 0, 0);
+ break;
+ case ValueChanged.Y:
+ if (v is Vector3 asVector3y)
+ v = asVector3y + new Vector3(0, newValue.Y, 0);
+ else if (v is Float3 asFloat3y)
+ v = asFloat3y + new Float3(0, (float)newValue.Y, 0);
+ else if (v is Double3 asDouble3y)
+ v = asDouble3y + new Double3(0, newValue.Y, 0);
+ break;
+ case ValueChanged.Z:
+ if (v is Vector3 asVector3z)
+ v = asVector3z + new Vector3(0, 0, newValue.Z);
+ else if (v is Float3 asFloat3z)
+ v = asFloat3z + new Float3(0, 0, (float)newValue.Z);
+ else if (v is Double3 asDouble3z)
+ v = asDouble3z + new Double3(0, 0, newValue.Z);
+ break;
+ }
+
+ 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];
+ switch (_valueChanged)
+ {
+ case ValueChanged.X:
+ if (v is Vector3 vx3)
+ v = new Vector3(xValue, vx3.Y, vx3.Z);
+ else if (v is Float3 fx3)
+ v = new Float3((float)xValue, fx3.Y, fx3.Z);
+ else if (v is Double3 dx3)
+ v = new Double3(xValue, dx3.Y, dx3.Z);
+ break;
+ case ValueChanged.Y:
+ if (v is Vector3 vy3)
+ v = new Vector3(vy3.X, yValue, vy3.Z);
+ else if (v is Float3 fy3)
+ v = new Float3(fy3.X, (float)yValue, fy3.Z);
+ else if (v is Double3 dy3)
+ v = new Double3(dy3.X, yValue, dy3.Z);
+ break;
+ case ValueChanged.Z:
+ if (v is Vector3 vz3)
+ v = new Vector3(vz3.X, vz3.Y, zValue);
+ else if (v is Float3 fz3)
+ v = new Float3(fz3.X, fz3.Y, (float)zValue);
+ else if (v is Double3 dz3)
+ v = new Double3(dz3.X, dz3.Y, zValue);
+ break;
+ }
+
+ 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);
+ }
}
- ///
+ ///
public override void Refresh()
{
base.Refresh();
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 +807,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 5dc6adcc2..2defd573b 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;
@@ -379,10 +380,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]);
+ }
}
}