A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Diagnostics.Eventing.Reader;
4using System.Linq;
5using System.Reflection;
6using UnityEngine;
7using UnityEditor.Graphing;
8using UnityEditor.Graphing.Util;
9using UnityEditor.ShaderGraph.Internal;
10using Object = UnityEngine.Object;
11
12using UnityEditor.UIElements;
13using UnityEngine.UIElements;
14using UnityEngine.UIElements.StyleSheets;
15using UnityEditor.SearchService;
16
17namespace UnityEditor.ShaderGraph.Drawing.Inspector
18{
19 class MasterPreviewView : VisualElement
20 {
21 PreviewManager m_PreviewManager;
22 GraphData m_Graph;
23
24 PreviewRenderData m_PreviewRenderHandle;
25 Image m_PreviewTextureView;
26
27 public Image previewTextureView
28 {
29 get { return m_PreviewTextureView; }
30 }
31
32 Vector2 m_PreviewScrollPosition;
33 ObjectField m_PreviewMeshPicker;
34
35 Mesh m_PreviousMesh;
36
37 bool m_RecalculateLayout;
38
39 ResizeBorderFrame m_PreviewResizeBorderFrame;
40
41 public ResizeBorderFrame previewResizeBorderFrame
42 {
43 get { return m_PreviewResizeBorderFrame; }
44 }
45
46 VisualElement m_Preview;
47 Label m_Title;
48
49 public VisualElement preview
50 {
51 get { return m_Preview; }
52 }
53
54 List<string> m_DoNotShowPrimitives = new List<string>(new string[] { PrimitiveType.Plane.ToString() });
55 static Type s_ContextualMenuManipulator = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEngine.UIElements.ContextualMenuManipulator");
56 static Type s_ObjectSelector = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEditor.ObjectSelector");
57
58
59 public string assetName
60 {
61 get { return m_Title.text; }
62 set { m_Title.text = value; }
63 }
64
65 public MasterPreviewView(PreviewManager previewManager, GraphData graph)
66 {
67 style.overflow = Overflow.Hidden;
68 m_PreviewManager = previewManager;
69 m_Graph = graph;
70
71 styleSheets.Add(Resources.Load<StyleSheet>("Styles/MasterPreviewView"));
72
73 m_PreviewRenderHandle = previewManager.masterRenderData;
74 if (m_PreviewRenderHandle != null)
75 {
76 m_PreviewRenderHandle.onPreviewChanged += OnPreviewChanged;
77 }
78
79 var topContainer = new VisualElement() { name = "top" };
80 {
81 m_Title = new Label() { name = "title" };
82 m_Title.text = "Main Preview";
83
84 topContainer.Add(m_Title);
85 }
86 Add(topContainer);
87
88 m_Preview = new VisualElement { name = "middle" };
89 {
90 m_PreviewTextureView = CreatePreview(Texture2D.blackTexture);
91 m_PreviewScrollPosition = new Vector2(0f, 0f);
92 preview.Add(m_PreviewTextureView);
93 preview.AddManipulator(new Scrollable(OnScroll));
94 }
95 Add(preview);
96
97 m_PreviewResizeBorderFrame = new ResizeBorderFrame(this, this) { name = "resizeBorderFrame" };
98 m_PreviewResizeBorderFrame.maintainAspectRatio = true;
99 Add(m_PreviewResizeBorderFrame);
100
101 m_RecalculateLayout = false;
102 this.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
103 }
104
105 Image CreatePreview(Texture texture)
106 {
107 if (m_PreviewRenderHandle?.texture != null)
108 {
109 texture = m_PreviewRenderHandle.texture;
110 }
111
112 var image = new Image { name = "preview", image = texture, scaleMode = ScaleMode.ScaleAndCrop };
113 image.AddManipulator(new Draggable(OnMouseDragPreviewMesh, true));
114 image.AddManipulator((IManipulator)Activator.CreateInstance(s_ContextualMenuManipulator, (Action<ContextualMenuPopulateEvent>)BuildContextualMenu));
115 return image;
116 }
117
118 void BuildContextualMenu(ContextualMenuPopulateEvent evt)
119 {
120 foreach (var primitiveTypeName in Enum.GetNames(typeof(PrimitiveType)))
121 {
122 if (m_DoNotShowPrimitives.Contains(primitiveTypeName))
123 continue;
124 evt.menu.AppendAction(primitiveTypeName, e => ChangePrimitiveMesh(primitiveTypeName), DropdownMenuAction.AlwaysEnabled);
125 }
126
127 evt.menu.AppendAction("Sprite", e => ChangeMeshSprite(), DropdownMenuAction.AlwaysEnabled);
128 evt.menu.AppendAction("Custom Mesh", e => ChangeMeshCustom(), DropdownMenuAction.AlwaysEnabled);
129 }
130
131 void OnPreviewChanged()
132 {
133 m_PreviewTextureView.image = m_PreviewRenderHandle?.texture ?? Texture2D.blackTexture;
134 if (m_PreviewRenderHandle != null && m_PreviewRenderHandle.shaderData.isOutOfDate)
135 m_PreviewTextureView.tintColor = new Color(1.0f, 1.0f, 1.0f, 0.3f);
136 else
137 m_PreviewTextureView.tintColor = Color.white;
138 m_PreviewTextureView.MarkDirtyRepaint();
139 }
140
141 void ChangePrimitiveMesh(string primitiveName)
142 {
143 Mesh changedPrimitiveMesh = Resources.GetBuiltinResource(typeof(Mesh), string.Format("{0}.fbx", primitiveName)) as Mesh;
144
145 ChangeMesh(changedPrimitiveMesh);
146 }
147
148 void ChangeMesh(Mesh mesh)
149 {
150 Mesh changedMesh = mesh;
151
152 m_PreviewManager.UpdateMasterPreview(ModificationScope.Node);
153
154 if (m_Graph.previewData.serializedMesh.mesh != changedMesh)
155 {
156 m_Graph.previewData.rotation = Quaternion.identity;
157 m_PreviewScrollPosition = Vector2.zero;
158 }
159
160 m_Graph.previewData.preventRotation = false;
161 m_Graph.previewData.serializedMesh.mesh = changedMesh;
162 }
163
164 private static EditorWindow Get()
165 {
166 PropertyInfo P = s_ObjectSelector.GetProperty("get", BindingFlags.Public | BindingFlags.Static);
167 return P.GetValue(null, null) as EditorWindow;
168 }
169
170 void OnMeshChanged(Object obj)
171 {
172 var mesh = obj as Mesh;
173 if (mesh == null)
174 mesh = m_PreviousMesh;
175 ChangeMesh(mesh);
176 }
177
178 void ChangeMeshSprite()
179 {
180 ChangePrimitiveMesh(PrimitiveType.Quad.ToString());
181
182 m_Graph.previewData.rotation = Quaternion.identity;
183 m_Graph.previewData.preventRotation = true;
184 }
185
186 void ChangeMeshCustom()
187 {
188 var ShowMethod = s_ObjectSelector.GetMethod("Show", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(UnityEngine.Object), typeof(Type), typeof(UnityEngine.Object), typeof(bool), typeof(List<int>), typeof(Action<UnityEngine.Object>), typeof(Action<UnityEngine.Object>), typeof(bool) }, new ParameterModifier[8]);
189 m_PreviousMesh = m_Graph.previewData.serializedMesh.mesh;
190 ShowMethod.Invoke(Get(), new object[] { null, typeof(Mesh), null, false, null, (Action<Object>)OnMeshChanged, (Action<Object>)OnMeshChanged, false });
191 }
192
193 void OnGeometryChanged(GeometryChangedEvent evt)
194 {
195 if (m_RecalculateLayout)
196 {
197 WindowDockingLayout dockingLayout = new WindowDockingLayout();
198 dockingLayout.CalculateDockingCornerAndOffset(layout, parent.layout);
199 dockingLayout.ClampToParentWindow();
200 dockingLayout.ApplyPosition(this);
201 m_RecalculateLayout = false;
202 }
203
204 var currentWidth = m_PreviewRenderHandle?.texture != null ? m_PreviewRenderHandle.texture.width : -1;
205 var currentHeight = m_PreviewRenderHandle?.texture != null ? m_PreviewRenderHandle.texture.height : -1;
206
207 var targetWidth = Mathf.Max(1f, m_PreviewTextureView.contentRect.width);
208 var targetHeight = Mathf.Max(1f, m_PreviewTextureView.contentRect.height);
209
210 if (Mathf.Approximately(currentWidth, targetHeight) && Mathf.Approximately(currentHeight, targetWidth))
211 return;
212
213 m_PreviewTextureView.style.width = evt.newRect.width;
214 m_PreviewTextureView.style.height = evt.newRect.height - 40.0f;
215 m_PreviewManager.ResizeMasterPreview(new Vector2(evt.newRect.width, evt.newRect.width));
216 }
217
218 void OnScroll(float scrollValue)
219 {
220 float rescaleAmount = -scrollValue * .03f;
221 m_Graph.previewData.scale = Mathf.Clamp(m_Graph.previewData.scale + rescaleAmount, 0.2f, 5f);
222
223 m_PreviewManager.UpdateMasterPreview(ModificationScope.Node);
224 }
225
226 void OnMouseDragPreviewMesh(Vector2 deltaMouse)
227 {
228 if (m_Graph.previewData.preventRotation) return;
229
230 Vector2 previewSize = m_PreviewTextureView.contentRect.size;
231
232 m_PreviewScrollPosition -= deltaMouse * (Event.current.shift ? 3f : 1f) / Mathf.Min(previewSize.x, previewSize.y) * 140f;
233 m_PreviewScrollPosition.y = Mathf.Clamp(m_PreviewScrollPosition.y, -90f, 90f);
234 Quaternion previewRotation = Quaternion.Euler(m_PreviewScrollPosition.y, 0, 0) * Quaternion.Euler(0, m_PreviewScrollPosition.x, 0);
235 m_Graph.previewData.rotation = previewRotation;
236
237 m_PreviewManager.UpdateMasterPreview(ModificationScope.Node);
238 }
239 }
240}