Files
Test/Library/PackageCache/com.unity.collab-proxy@4628d2ba6ea4/Editor/Diff/Asset/Common/DiffValueDisplay.cs
T
2026-11-01 23:39:55 +02:00

538 lines
19 KiB
C#

using Unity.PlasticSCM.Editor.Diff.Asset.Common.Property;
using Unity.PlasticSCM.Editor.Diff.Asset.Diff.Property;
using Unity.PlasticSCM.Editor.Diff.Asset.Content.Property;
using Unity.PlasticSCM.Editor.UI;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace Unity.PlasticSCM.Editor.Diff.Asset.Common
{
internal class DiffValueDisplay : VisualElement
{
internal DiffValueDisplay()
{
CreateGUI();
}
internal void SetData(
object tag,
string fallbackText,
bool hasContent,
object counterpartTag)
{
HideActiveField();
if (!hasContent)
return;
if (tag is LeafPropertyData leaf)
{
LeafPropertyData? counterpart = counterpartTag is LeafPropertyData cp
? cp
: (LeafPropertyData?)null;
ShowTypedField(leaf, counterpart);
return;
}
ShowField(mTextField);
mTextField.SetValueWithoutNotify(fallbackText ?? string.Empty);
}
void CreateGUI()
{
style.flexGrow = 1;
style.overflow = Overflow.Visible;
mFloatField = AddField(new FloatField { label = string.Empty });
mIntField = AddField(new IntegerField { label = string.Empty });
mToggleField = AddField(new Toggle { label = string.Empty });
mTextField = AddField(new TextField { label = string.Empty });
mColorField = AddField(new ColorField
{
label = string.Empty,
showAlpha = true,
hdr = false,
showEyeDropper = false
});
mCurveField = AddField(new CurveField { label = string.Empty });
mGradientField = AddField(new GradientField { label = string.Empty });
mVector2Field = AddField(new Vector2Field { label = string.Empty });
mVector3Field = AddField(new Vector3Field { label = string.Empty });
mVector4Field = AddField(new Vector4Field { label = string.Empty });
mVector2IntField = AddField(new Vector2IntField { label = string.Empty });
mVector3IntField = AddField(new Vector3IntField { label = string.Empty });
mRectField = AddField(new RectField { label = string.Empty });
mRectIntField = AddField(new RectIntField { label = string.Empty });
mBoundsField = AddField(new BoundsField { label = string.Empty });
mBoundsIntField = AddField(new BoundsIntField { label = string.Empty });
mHash128Field = AddField(new Hash128Field { label = string.Empty });
}
T AddField<T>(T field) where T : VisualElement
{
field.SetEnabled(false);
field.style.opacity = 1f;
field.style.display = DisplayStyle.None;
field.style.flexGrow = 1;
field.style.marginTop = 0;
field.style.marginBottom = 0;
field.style.marginLeft = 0;
field.style.marginRight = 0;
Add(field);
field.RegisterCallback<AttachToPanelEvent>(_ =>
{
StyleColor readonlyBg = new StyleColor(
UnityStyles.Colors.Diff.AssetDiff.ReadonlyFieldBackgroundColor);
field.Query(className: INPUT_CLASS).ForEach(input =>
input.style.backgroundColor = readonlyBg);
field.Query(className: TOGGLE_CHECKMARK_CLASS).ForEach(checkmark =>
checkmark.style.unityBackgroundImageTintColor = new StyleColor(
UnityStyles.Colors.Diff.AssetDiff.ReadonlyToggleTintColor));
});
return field;
}
void HideActiveField()
{
if (mActiveField == null)
return;
mActiveField.style.display = DisplayStyle.None;
mActiveField = null;
}
void ShowField(VisualElement field)
{
field.style.display = DisplayStyle.Flex;
mActiveField = field;
}
void ShowTypedField(LeafPropertyData data, LeafPropertyData? counterpart)
{
switch (data.PropertyType)
{
case SerializedPropertyType.Float:
ShowField(mFloatField);
mFloatField.SetValueWithoutNotify(data.FloatValue);
return;
case SerializedPropertyType.Integer:
if (data.HasFormattedDisplay)
{
ShowField(mTextField);
mTextField.SetValueWithoutNotify(data.StringValue ?? string.Empty);
return;
}
ShowField(mIntField);
mIntField.SetValueWithoutNotify(data.IntValue);
return;
case SerializedPropertyType.LayerMask:
if (data.HasFormattedDisplay)
{
ShowField(mTextField);
mTextField.SetValueWithoutNotify(data.StringValue ?? string.Empty);
return;
}
ShowField(mIntField);
mIntField.SetValueWithoutNotify(data.IntValue);
return;
case SerializedPropertyType.Character:
case SerializedPropertyType.ArraySize:
case SerializedPropertyType.FixedBufferSize:
ShowField(mIntField);
mIntField.SetValueWithoutNotify(data.IntValue);
return;
case SerializedPropertyType.Boolean:
ShowField(mToggleField);
mToggleField.SetValueWithoutNotify(data.BoolValue);
return;
case SerializedPropertyType.String:
ShowField(mTextField);
mTextField.SetValueWithoutNotify(data.StringValue ?? string.Empty);
return;
case SerializedPropertyType.Color:
ShowField(mColorField);
mColorField.SetValueWithoutNotify(data.ColorValue);
return;
case SerializedPropertyType.AnimationCurve:
ShowField(mCurveField);
mCurveField.SetValueWithoutNotify(
data.AnimationCurveValue ?? new AnimationCurve());
return;
case SerializedPropertyType.Gradient:
ShowField(mGradientField);
mGradientField.SetValueWithoutNotify(
data.GradientValue ?? new Gradient());
return;
case SerializedPropertyType.Vector2:
ShowVector2(data.Vector2Value, counterpart);
return;
case SerializedPropertyType.Vector3:
ShowVector3(data.Vector3Value, counterpart);
return;
case SerializedPropertyType.Vector4:
ShowVector4(data.Vector4Value, counterpart);
return;
case SerializedPropertyType.Quaternion:
ShowQuaternion(data.QuaternionValue, counterpart);
return;
case SerializedPropertyType.Vector2Int:
ShowVector2Int(data.Vector2IntValue, counterpart);
return;
case SerializedPropertyType.Vector3Int:
ShowVector3Int(data.Vector3IntValue, counterpart);
return;
case SerializedPropertyType.Rect:
ShowRect(data.RectValue, counterpart);
return;
case SerializedPropertyType.RectInt:
ShowRectInt(data.RectIntValue, counterpart);
return;
case SerializedPropertyType.Bounds:
ShowBounds(data.BoundsValue, counterpart);
return;
case SerializedPropertyType.BoundsInt:
ShowBoundsInt(data.BoundsIntValue, counterpart);
return;
case SerializedPropertyType.Hash128:
ShowField(mHash128Field);
mHash128Field.SetValueWithoutNotify(data.Hash128Value);
return;
default:
ShowField(mTextField);
mTextField.SetValueWithoutNotify(data.StringValue ?? string.Empty);
return;
}
}
void ShowVector2(Vector2 value, LeafPropertyData? counterpart)
{
ShowField(mVector2Field);
mVector2Field.SetValueWithoutNotify(value);
float[] otherValues = TryGetVector2Components(counterpart);
HighlightFloatComponents(
mVector2Field, new[] { value.x, value.y }, otherValues);
}
void ShowVector3(Vector3 value, LeafPropertyData? counterpart)
{
ShowField(mVector3Field);
mVector3Field.SetValueWithoutNotify(value);
float[] otherValues = TryGetVector3Components(counterpart);
HighlightFloatComponents(
mVector3Field, new[] { value.x, value.y, value.z }, otherValues);
}
void ShowVector4(Vector4 value, LeafPropertyData? counterpart)
{
ShowField(mVector4Field);
mVector4Field.SetValueWithoutNotify(value);
float[] otherValues = TryGetVector4Components(counterpart);
HighlightFloatComponents(
mVector4Field,
new[] { value.x, value.y, value.z, value.w },
otherValues);
}
void ShowQuaternion(Quaternion value, LeafPropertyData? counterpart)
{
Vector3 euler = value.eulerAngles;
ShowField(mVector3Field);
mVector3Field.SetValueWithoutNotify(euler);
float[] otherValues = null;
if (counterpart.HasValue &&
counterpart.Value.PropertyType == SerializedPropertyType.Quaternion)
{
Vector3 otherEuler = counterpart.Value.QuaternionValue.eulerAngles;
otherValues = new[] { otherEuler.x, otherEuler.y, otherEuler.z };
}
HighlightFloatComponents(
mVector3Field, new[] { euler.x, euler.y, euler.z }, otherValues);
}
void ShowVector2Int(Vector2Int value, LeafPropertyData? counterpart)
{
ShowField(mVector2IntField);
mVector2IntField.SetValueWithoutNotify(value);
int[] otherValues = TryGetVector2IntComponents(counterpart);
HighlightIntComponents(
mVector2IntField, new[] { value.x, value.y }, otherValues);
}
void ShowVector3Int(Vector3Int value, LeafPropertyData? counterpart)
{
ShowField(mVector3IntField);
mVector3IntField.SetValueWithoutNotify(value);
int[] otherValues = TryGetVector3IntComponents(counterpart);
HighlightIntComponents(
mVector3IntField,
new[] { value.x, value.y, value.z },
otherValues);
}
void ShowRect(Rect value, LeafPropertyData? counterpart)
{
ShowField(mRectField);
mRectField.SetValueWithoutNotify(value);
float[] otherValues = TryGetRectComponents(counterpart);
HighlightFloatComponents(
mRectField,
new[] { value.x, value.y, value.width, value.height },
otherValues);
}
void ShowRectInt(RectInt value, LeafPropertyData? counterpart)
{
ShowField(mRectIntField);
mRectIntField.SetValueWithoutNotify(value);
int[] otherValues = TryGetRectIntComponents(counterpart);
HighlightIntComponents(
mRectIntField,
new[] { value.x, value.y, value.width, value.height },
otherValues);
}
void ShowBounds(Bounds value, LeafPropertyData? counterpart)
{
ShowField(mBoundsField);
mBoundsField.SetValueWithoutNotify(value);
float[] otherValues = TryGetBoundsComponents(counterpart);
HighlightFloatComponents(
mBoundsField,
new[]
{
value.center.x, value.center.y, value.center.z,
value.extents.x, value.extents.y, value.extents.z
},
otherValues);
}
void ShowBoundsInt(BoundsInt value, LeafPropertyData? counterpart)
{
ShowField(mBoundsIntField);
mBoundsIntField.SetValueWithoutNotify(value);
int[] otherValues = TryGetBoundsIntComponents(counterpart);
HighlightIntComponents(
mBoundsIntField,
new[]
{
value.position.x, value.position.y, value.position.z,
value.size.x, value.size.y, value.size.z
},
otherValues);
}
static float[] TryGetVector2Components(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Vector2)
return null;
Vector2 v = counterpart.Value.Vector2Value;
return new[] { v.x, v.y };
}
static float[] TryGetVector3Components(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Vector3)
return null;
Vector3 v = counterpart.Value.Vector3Value;
return new[] { v.x, v.y, v.z };
}
static float[] TryGetVector4Components(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Vector4)
return null;
Vector4 v = counterpart.Value.Vector4Value;
return new[] { v.x, v.y, v.z, v.w };
}
static int[] TryGetVector2IntComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Vector2Int)
return null;
Vector2Int v = counterpart.Value.Vector2IntValue;
return new[] { v.x, v.y };
}
static int[] TryGetVector3IntComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Vector3Int)
return null;
Vector3Int v = counterpart.Value.Vector3IntValue;
return new[] { v.x, v.y, v.z };
}
static float[] TryGetRectComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Rect)
return null;
Rect r = counterpart.Value.RectValue;
return new[] { r.x, r.y, r.width, r.height };
}
static int[] TryGetRectIntComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.RectInt)
return null;
RectInt r = counterpart.Value.RectIntValue;
return new[] { r.x, r.y, r.width, r.height };
}
static float[] TryGetBoundsComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.Bounds)
return null;
Bounds b = counterpart.Value.BoundsValue;
return new[]
{
b.center.x, b.center.y, b.center.z,
b.extents.x, b.extents.y, b.extents.z
};
}
static int[] TryGetBoundsIntComponents(LeafPropertyData? counterpart)
{
if (!counterpart.HasValue ||
counterpart.Value.PropertyType != SerializedPropertyType.BoundsInt)
return null;
BoundsInt b = counterpart.Value.BoundsIntValue;
return new[]
{
b.position.x, b.position.y, b.position.z,
b.size.x, b.size.y, b.size.z
};
}
static void HighlightFloatComponents(
VisualElement vectorField,
float[] values,
float[] counterpartValues)
{
var floatFields = vectorField.Query<FloatField>().ToList();
bool hasComparison = counterpartValues != null;
for (int i = 0; i < floatFields.Count && i < values.Length; i++)
{
bool changed = hasComparison
&& i < counterpartValues.Length
&& !Mathf.Approximately(values[i], counterpartValues[i]);
ApplyInputHighlight(floatFields[i], changed, hasComparison);
}
}
static void HighlightIntComponents(
VisualElement vectorField,
int[] values,
int[] counterpartValues)
{
var intFields = vectorField.Query<IntegerField>().ToList();
bool hasComparison = counterpartValues != null;
for (int i = 0; i < intFields.Count && i < values.Length; i++)
{
bool changed = hasComparison
&& i < counterpartValues.Length
&& values[i] != counterpartValues[i];
ApplyInputHighlight(intFields[i], changed, hasComparison);
}
}
static void ApplyInputHighlight(
VisualElement field, bool highlight, bool hasComparison)
{
VisualElement input = field.Q(className: INPUT_CLASS);
if (input == null)
return;
StyleColor color = highlight
? new StyleColor(UnityStyles.Colors.Diff.AssetDiff.VectorComponentHighlight)
: new StyleColor(StyleKeyword.Null);
input.style.borderTopColor = color;
input.style.borderBottomColor = color;
input.style.borderLeftColor = color;
input.style.borderRightColor = color;
input.style.opacity = (highlight || !hasComparison) ? 1f : 0.4f;
}
VisualElement mActiveField;
FloatField mFloatField;
IntegerField mIntField;
Toggle mToggleField;
TextField mTextField;
ColorField mColorField;
CurveField mCurveField;
GradientField mGradientField;
Vector2Field mVector2Field;
Vector3Field mVector3Field;
Vector4Field mVector4Field;
Vector2IntField mVector2IntField;
Vector3IntField mVector3IntField;
RectField mRectField;
RectIntField mRectIntField;
BoundsField mBoundsField;
BoundsIntField mBoundsIntField;
Hash128Field mHash128Field;
const string INPUT_CLASS = "unity-base-text-field__input";
const string TOGGLE_CHECKMARK_CLASS = "unity-toggle__checkmark";
}
}