Skip to content

Commit 0cee9f2

Browse files
committed
Initial commit
0 parents  commit 0cee9f2

File tree

10 files changed

+353
-0
lines changed

10 files changed

+353
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
*
2+
3+
# Include Github info.
4+
!.github
5+
!.gitignore
6+
!LICENSE
7+
!README.md
8+
9+
# Include everything in Assets/Nessie/
10+
!Assets/
11+
!Assets/Nessie
12+
!Assets/Nessie/**

Assets/Nessie/ASE.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Nessie/ASE/Editor.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using UnityEditor;
5+
using UnityEngine;
6+
using HarmonyLib;
7+
using AmplifyShaderEditor;
8+
9+
namespace Nessie.ASE
10+
{
11+
[InitializeOnLoad]
12+
internal class ColorDebug
13+
{
14+
#region Private Fields
15+
16+
private const string m_harmonyID = "Nessie.ASE.ColorDebugPatch";
17+
18+
private static bool m_useHotkey = true;
19+
20+
private static Texture2D m_previewPixel;
21+
22+
#endregion Private Fields
23+
24+
#region Public Fields
25+
26+
public static bool UseHotkey { get { return m_useHotkey; } set { m_useHotkey = value; } }
27+
28+
public static Texture2D PreviewPixel
29+
{
30+
get
31+
{
32+
if (m_previewPixel == null)
33+
m_previewPixel = new Texture2D(
34+
1, 1,
35+
UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32B32A32_SFloat,
36+
UnityEngine.Experimental.Rendering.TextureCreationFlags.None);
37+
38+
return m_previewPixel;
39+
}
40+
}
41+
42+
#endregion Public Fields
43+
44+
#region Injection Methods
45+
46+
static ColorDebug()
47+
{
48+
AssemblyReloadEvents.afterAssemblyReload += PostAssemblyReload;
49+
}
50+
51+
static void PostAssemblyReload()
52+
{
53+
Harmony harmony = new Harmony(m_harmonyID);
54+
55+
harmony.PatchAll();
56+
}
57+
58+
[HarmonyPatch(typeof(ParentGraph), nameof(ParentGraph.Draw))]
59+
static class PatchDrawPreview
60+
{
61+
static void Postfix(DrawInfo drawInfo, List<ParentNode> ___m_nodes)
62+
{
63+
if (drawInfo.CurrentEventType == EventType.Repaint && (!UseHotkey || Event.current.control))
64+
{
65+
ParentNode node = GetActiveNode(drawInfo, ___m_nodes);
66+
if (node)
67+
ShowColorTooltip(drawInfo, node);
68+
}
69+
}
70+
}
71+
72+
[HarmonyPatch(typeof(AmplifyShaderEditorWindow), nameof(AmplifyShaderEditorWindow.OnDisable))]
73+
static class PatchDisable
74+
{
75+
static void Postfix()
76+
{
77+
if (m_previewPixel == null)
78+
UnityEngine.Object.DestroyImmediate(PreviewPixel);
79+
}
80+
}
81+
82+
#endregion Injection Methods
83+
84+
#region ASE Methods
85+
86+
static void ShowColorTooltip(DrawInfo drawInfo, ParentNode node)
87+
{
88+
bool isTextureNode = node.GetType().IsSubclassOf(typeof(TexturePropertyNode));
89+
bool drawPreview = isTextureNode ? ((TexturePropertyNode)node).IsValid : GetPrivateField<bool>(node, "m_drawPreview");
90+
Rect previewRect = GetPrivateField<Rect>(node, "m_previewRect");
91+
if (previewRect.Contains(drawInfo.MousePosition) && (node.ShowPreview || node.ContainerGraph.ParentWindow.GlobalPreview) && drawPreview)
92+
{
93+
Vector2 mousePos = drawInfo.MousePosition;
94+
Vector2 mouseRel = mousePos - new Vector2(previewRect.x, previewRect.y);
95+
96+
// Push a single pixel from a RT into a Tex2D.
97+
RenderTexture previousRT = RenderTexture.active;
98+
RenderTexture.active = node.PreviewTexture;
99+
PreviewPixel.ReadPixels(new Rect(mouseRel.x, mouseRel.y, 1, 1), 0, 0, false);
100+
RenderTexture.active = previousRT;
101+
102+
// Each channel is represented with a full 32-bit float.
103+
byte[] bytes = PreviewPixel.GetRawTextureData();
104+
float colorR = BitConverter.ToSingle(bytes, 0);
105+
float colorG = BitConverter.ToSingle(bytes, 4);
106+
float colorB = BitConverter.ToSingle(bytes, 8);
107+
float colorA = BitConverter.ToSingle(bytes, 12);
108+
109+
string[] colorValues = new string[]
110+
{
111+
$"R: {colorR.ToString()}",
112+
$"G: {colorG.ToString()}",
113+
$"B: {colorB.ToString()}",
114+
$"A: {colorA.ToString()}"
115+
};
116+
117+
Array previewChannels = GetPrivateField<Array>(typeof(ParentNode), node, "m_previewChannels");
118+
int activeChannels = GetActiveChannels(node);
119+
int usedChannels = 0;
120+
string labelText = "";
121+
for (int i = 0; i < activeChannels; i++)
122+
{
123+
if ((bool)previewChannels.GetValue(i))
124+
labelText += usedChannels++ >= 1 ? $"\n{colorValues[i]}" : colorValues[i];
125+
}
126+
if (usedChannels == 0) return;
127+
128+
GUIStyle labelStyle = new GUIStyle(UIUtils.Textfield);
129+
labelStyle.padding.left += 2;
130+
labelStyle.padding.right += 2;
131+
labelStyle.padding.top += 2;
132+
labelStyle.padding.bottom += 2;
133+
Vector2 rectSize = labelStyle.CalcSize(new GUIContent(labelText));
134+
Rect labelRect = new Rect(mousePos.x + EditorGUIUtility.singleLineHeight / 1.5f, mousePos.y + EditorGUIUtility.singleLineHeight / 1.5f, rectSize.x + 1, rectSize.y);
135+
136+
GUI.Label(labelRect, labelText, labelStyle);
137+
}
138+
}
139+
140+
static ParentNode GetActiveNode(DrawInfo drawInfo, List<ParentNode> nodes)
141+
{
142+
int nodeCount = nodes.Count;
143+
for (int i = nodeCount - 1; i >= 0; i--)
144+
{
145+
ParentNode node = nodes[i];
146+
if (node.IsVisible && !node.IsMoving)
147+
{
148+
if (node.GlobalPosition.Contains(drawInfo.MousePosition)) return node;
149+
}
150+
}
151+
152+
return null;
153+
}
154+
155+
static int GetActiveChannels(ParentNode node)
156+
{
157+
switch (node.OutputPorts[0].DataType)
158+
{
159+
case WirePortDataType.FLOAT:
160+
return 1;
161+
case WirePortDataType.FLOAT2:
162+
return 2;
163+
case WirePortDataType.COLOR:
164+
case WirePortDataType.FLOAT4:
165+
case WirePortDataType.SAMPLER1D:
166+
case WirePortDataType.SAMPLER2D:
167+
case WirePortDataType.SAMPLER3D:
168+
case WirePortDataType.SAMPLERCUBE:
169+
case WirePortDataType.SAMPLER2DARRAY:
170+
return 4;
171+
default:
172+
return 3;
173+
}
174+
}
175+
176+
#endregion ASE Methods
177+
178+
#region Reflections
179+
180+
static T GetPrivateField<T>(object obj, string fieldName)
181+
{
182+
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
183+
Type type = obj.GetType();
184+
FieldInfo finfo = type.GetField(fieldName, bindingFlags);
185+
186+
return (T)finfo.GetValue(obj);
187+
}
188+
189+
static T GetPrivateField<T>(Type type, object obj, string fieldName)
190+
{
191+
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
192+
FieldInfo finfo = type.GetField(fieldName, bindingFlags);
193+
194+
return (T)finfo.GetValue(obj);
195+
}
196+
197+
#endregion Reflections
198+
}
199+
}

Assets/Nessie/ASE/Editor/ColorDebug.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Nessie/ASE/Plugins.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
886 KB
Binary file not shown.

Assets/Nessie/ASE/Plugins/0Harmony.dll.meta

Lines changed: 76 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Nestorboy
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# ASE Color Debug
2+
A custom Amplify Shader Editor feature which enables the ability to display the color values of a given pixel from a node preview.
3+
4+
### Description
5+
Whilst hovering your mouse over a node preview, you can hold down Control and a tiny display next to the mouse will show up.
6+
The color debugger will only display the color channels which are enabled on the node preview.
7+
Each channel is displayed and represented using a full 32-bit float, it also includes negatives, NaNs, and infinities.
8+
9+
### Requirements
10+
- [Amplify Shader Editor](http://amplify.pt/unity/amplify-shader-editor/)

0 commit comments

Comments
 (0)