Merge branch 'multi-select-values' of https://github.com/Tryibion/FlaxEngine into Tryibion-multi-select-values

This commit is contained in:
Wojtek Figat
2024-12-09 18:34:39 +01:00
4 changed files with 644 additions and 68 deletions

View File

@@ -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
{

View File

@@ -33,6 +33,15 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <summary>
/// Whether to use the average for sliding different values.
/// </summary>
public virtual bool AllowSlidingForDifferentValues => true;
private ValueChanged _valueChanged;
private float _defaultSlidingSpeed;
private bool _slidingEnded = false;
/// <inheritdoc />
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);
}
}
/// <inheritdoc />
@@ -112,7 +219,73 @@ namespace FlaxEditor.CustomEditors.Editors
if (HasDifferentValues)
{
// TODO: support different values for ValueBox<T>
// 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;
}
}
}

View File

@@ -7,6 +7,27 @@ using FlaxEngine.GUI;
namespace FlaxEditor.CustomEditors.Editors
{
/// <summary>
/// The value changed by custom Vector3 editors.
/// </summary>
public enum ValueChanged
{
/// <summary>
/// X value changed.
/// </summary>
X = 0,
/// <summary>
/// Y value changed.
/// </summary>
Y = 1,
/// <summary>
/// Z value changed.
/// </summary>
Z = 2
}
/// <summary>
/// Default implementation of the inspector used to edit Vector3 value type properties.
/// </summary>
@@ -49,14 +70,14 @@ namespace FlaxEditor.CustomEditors.Editors
/// </summary>
public bool LinkValues = false;
private enum ValueChanged
{
X = 0,
Y = 1,
Z = 2
}
/// <summary>
/// Whether to use the average for sliding different values.
/// </summary>
public virtual bool AllowSlidingForDifferentValues => true;
private ValueChanged _valueChanged;
private float _defaultSlidingSpeed;
private bool _slidingEnded = false;
/// <inheritdoc />
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<T>
// 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
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <summary>
/// Whether to use the average for sliding different values.
/// </summary>
public virtual bool AllowSlidingForDifferentValues => true;
private ValueChanged _valueChanged;
private float _defaultSlidingSpeed;
private bool _slidingEnded = false;
/// <inheritdoc />
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);
}
}
/// <inheritdoc />
@@ -341,7 +631,79 @@ namespace FlaxEditor.CustomEditors.Editors
if (HasDifferentValues)
{
// TODO: support different values for ValueBox<T>
// 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;
}
}
}
}

View File

@@ -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]);
}
}
}