A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Collections.ObjectModel;
4using UnityEditor;
5using UnityEngine;
6
7namespace Unity.Mathematics.Editor
8{
9 [CustomPropertyDrawer(typeof(bool2x2)), CustomPropertyDrawer(typeof(bool2x3)), CustomPropertyDrawer(typeof(bool2x4))]
10 [CustomPropertyDrawer(typeof(bool3x2)), CustomPropertyDrawer(typeof(bool3x3)), CustomPropertyDrawer(typeof(bool3x4))]
11 [CustomPropertyDrawer(typeof(bool4x2)), CustomPropertyDrawer(typeof(bool4x3)), CustomPropertyDrawer(typeof(bool4x4))]
12 [CustomPropertyDrawer(typeof(double2x2)), CustomPropertyDrawer(typeof(double2x3)), CustomPropertyDrawer(typeof(double2x4))]
13 [CustomPropertyDrawer(typeof(double3x2)), CustomPropertyDrawer(typeof(double3x3)), CustomPropertyDrawer(typeof(double3x4))]
14 [CustomPropertyDrawer(typeof(double4x2)), CustomPropertyDrawer(typeof(double4x3)), CustomPropertyDrawer(typeof(double4x4))]
15 [CustomPropertyDrawer(typeof(float2x2)), CustomPropertyDrawer(typeof(float2x3)), CustomPropertyDrawer(typeof(float2x4))]
16 [CustomPropertyDrawer(typeof(float3x2)), CustomPropertyDrawer(typeof(float3x3)), CustomPropertyDrawer(typeof(float3x4))]
17 [CustomPropertyDrawer(typeof(float4x2)), CustomPropertyDrawer(typeof(float4x3)), CustomPropertyDrawer(typeof(float4x4))]
18 [CustomPropertyDrawer(typeof(int2x2)), CustomPropertyDrawer(typeof(int2x3)), CustomPropertyDrawer(typeof(int2x4))]
19 [CustomPropertyDrawer(typeof(int3x2)), CustomPropertyDrawer(typeof(int3x3)), CustomPropertyDrawer(typeof(int3x4))]
20 [CustomPropertyDrawer(typeof(int4x2)), CustomPropertyDrawer(typeof(int4x3)), CustomPropertyDrawer(typeof(int4x4))]
21 [CustomPropertyDrawer(typeof(uint2x2)), CustomPropertyDrawer(typeof(uint2x3)), CustomPropertyDrawer(typeof(uint2x4))]
22 [CustomPropertyDrawer(typeof(uint3x2)), CustomPropertyDrawer(typeof(uint3x3)), CustomPropertyDrawer(typeof(uint3x4))]
23 [CustomPropertyDrawer(typeof(uint4x2)), CustomPropertyDrawer(typeof(uint4x3)), CustomPropertyDrawer(typeof(uint4x4))]
24 class MatrixDrawer : PropertyDrawer
25 {
26#if !UNITY_2023_2_OR_NEWER
27 public override bool CanCacheInspectorGUI(SerializedProperty property)
28 {
29 return false;
30 }
31#endif
32
33 public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
34 {
35 if (!property.isExpanded)
36 return EditorGUIUtility.singleLineHeight;
37 var rows = 1 + property.type[property.type.Length - 3] - '0';
38 return rows * EditorGUIUtility.singleLineHeight + (rows - 1) * EditorGUIUtility.standardVerticalSpacing;
39 }
40
41 static ReadOnlyCollection<string> k_ColPropertyPaths =
42 new ReadOnlyCollection<string>(new[] { "c0", "c1", "c2", "c3" });
43 static ReadOnlyCollection<string> k_RowPropertyPaths =
44 new ReadOnlyCollection<string>(new[] { "x", "y", "z", "w" });
45
46 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
47 {
48 position.height = EditorGUIUtility.singleLineHeight;
49 EditorGUI.PropertyField(position, property, label, false);
50
51 if (Event.current.type == EventType.ContextClick && position.Contains(Event.current.mousePosition))
52 {
53 DoUtilityMenu(property);
54 Event.current.Use();
55 }
56
57 if (!property.isExpanded)
58 return;
59
60 var rows = property.type[property.type.Length - 3] - '0';
61 var cols = property.type[property.type.Length - 1] - '0';
62
63 ++EditorGUI.indentLevel;
64 position = EditorGUI.IndentedRect(position);
65 --EditorGUI.indentLevel;
66
67 var elementType = property.FindPropertyRelative("c0.x").propertyType;
68 for (var row = 0; row < rows; ++row)
69 {
70 position.y += position.height + EditorGUIUtility.standardVerticalSpacing;
71 var elementRect = new Rect(position)
72 {
73 width = elementType == SerializedPropertyType.Boolean
74 ? EditorGUIUtility.singleLineHeight
75 : (position.width - (cols - 1) * EditorGUIUtility.standardVerticalSpacing) / cols
76 };
77 for (var col = 0; col < cols; ++col)
78 {
79 EditorGUI.PropertyField(
80 elementRect,
81 property.FindPropertyRelative($"{k_ColPropertyPaths[col]}.{k_RowPropertyPaths[row]}"),
82 GUIContent.none
83 );
84 elementRect.x += elementRect.width + EditorGUIUtility.standardVerticalSpacing;
85 }
86 }
87 }
88
89 Dictionary<SerializedPropertyType, Action<SerializedProperty, bool>> k_UtilityValueSetters =
90 new Dictionary<SerializedPropertyType, Action<SerializedProperty, bool>>
91 {
92 { SerializedPropertyType.Boolean, (property, b) => property.boolValue = b },
93 { SerializedPropertyType.Float, (property, b) => property.floatValue = b ? 1f : 0f },
94 { SerializedPropertyType.Integer, (property, b) => property.intValue = b ? 1 : 0 }
95 };
96
97 void DoUtilityMenu(SerializedProperty property)
98 {
99 var rows = property.type[property.type.Length - 3] - '0';
100 var cols = property.type[property.type.Length - 1] - '0';
101 var elementType = property.FindPropertyRelative("c0.x").propertyType;
102 var setValue = k_UtilityValueSetters[elementType];
103 var menu = new GenericMenu();
104 property = property.Copy();
105 menu.AddItem(
106 EditorGUIUtility.TrTextContent("Set to Zero"),
107 false,
108 () =>
109 {
110 property.serializedObject.Update();;
111 for (var row = 0; row < rows; ++row)
112 for (var col = 0; col < cols; ++col)
113 setValue(
114 property.FindPropertyRelative($"{k_ColPropertyPaths[col]}.{k_RowPropertyPaths[row]}"),
115 false
116 );
117 property.serializedObject.ApplyModifiedProperties();
118 }
119 );
120 if (rows == cols)
121 {
122 menu.AddItem(
123 EditorGUIUtility.TrTextContent("Reset to Identity"),
124 false,
125 () =>
126 {
127 property.serializedObject.Update();
128 for (var row = 0; row < rows; ++row)
129 for (var col = 0; col < cols; ++col)
130 setValue(
131 property.FindPropertyRelative($"{k_ColPropertyPaths[col]}.{k_RowPropertyPaths[row]}"),
132 row == col
133 );
134 property.serializedObject.ApplyModifiedProperties();
135 }
136 );
137 }
138 menu.ShowAsContext();
139 }
140 }
141}