asecli 0.6.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- asecli/__init__.py +3 -0
- asecli/bridge/__init__.py +40 -0
- asecli/bridge/_editor_port_contract.py +131 -0
- asecli/bridge/_editor_primitives.py +205 -0
- asecli/bridge/_editor_spec_grammar.py +245 -0
- asecli/bridge/_editor_spec_io.py +26 -0
- asecli/bridge/_editor_spec_validation.py +218 -0
- asecli/bridge/_gui_handoff_store.py +78 -0
- asecli/bridge/_gui_project.py +35 -0
- asecli/bridge/_gui_resource_store.py +159 -0
- asecli/bridge/_gui_resource_upgrade.py +122 -0
- asecli/bridge/editor_create.py +173 -0
- asecli/bridge/editor_spec.py +250 -0
- asecli/bridge/graph_geometry.py +249 -0
- asecli/bridge/graph_geometry_parser.py +57 -0
- asecli/bridge/graph_inspect.py +136 -0
- asecli/bridge/gui_handoff.py +100 -0
- asecli/bridge/gui_presentation.py +70 -0
- asecli/bridge/gui_provider_detection.py +197 -0
- asecli/bridge/gui_runtime_probe.py +25 -0
- asecli/bridge/gui_support.py +240 -0
- asecli/bridge/gui_support_resource.py +58 -0
- asecli/bridge/mcp_client.py +231 -0
- asecli/bridge/recompile.py +107 -0
- asecli/bridge/resource_text.py +12 -0
- asecli/bridge/resources/asecli_material_gui.authoring.part00.cs.txt +238 -0
- asecli/bridge/resources/asecli_material_gui.authoring.part01.cs.txt +235 -0
- asecli/bridge/resources/asecli_material_gui.authoring.store.cs.txt +125 -0
- asecli/bridge/resources/asecli_material_gui.condition.cs.txt +99 -0
- asecli/bridge/resources/asecli_material_gui.hydration.cs.txt +105 -0
- asecli/bridge/resources/asecli_material_gui.part00.cs.txt +300 -0
- asecli/bridge/resources/asecli_material_gui.part01.cs.txt +290 -0
- asecli/bridge/resources/asecli_material_gui.reconciliation.cs.txt +174 -0
- asecli/bridge/resources/asecli_material_gui.transaction.cs.txt +108 -0
- asecli/bridge/resources/editor_create.part00.cs.txt +176 -0
- asecli/bridge/resources/editor_create.part01.cs.txt +145 -0
- asecli/bridge/resources/editor_create.part02.cs.txt +139 -0
- asecli/bridge/resources/editor_create.part03.cs.txt +161 -0
- asecli/bridge/resources/editor_create.part04.cs.txt +114 -0
- asecli/bridge/resources/wire_route.transaction.cs.txt +140 -0
- asecli/bridge/wire_route.py +127 -0
- asecli/checks/__init__.py +10 -0
- asecli/checks/checksum.py +53 -0
- asecli/checks/local_vars.py +135 -0
- asecli/checks/usage.py +141 -0
- asecli/checks/validate.py +129 -0
- asecli/cli/__init__.py +1 -0
- asecli/cli/commands.py +237 -0
- asecli/cli/commentary_command.py +158 -0
- asecli/cli/create_command.py +250 -0
- asecli/cli/custom_gui_command.py +170 -0
- asecli/cli/gui_provider.py +30 -0
- asecli/cli/gui_support_command.py +35 -0
- asecli/cli/io.py +214 -0
- asecli/cli/layout_command.py +213 -0
- asecli/cli/main.py +245 -0
- asecli/cli/recompile_metadata.py +53 -0
- asecli/cli/skill_command.py +121 -0
- asecli/cli/usage_command.py +42 -0
- asecli/core/__init__.py +84 -0
- asecli/core/comment_bounds.py +166 -0
- asecli/core/comment_layout.py +167 -0
- asecli/core/comment_metrics.py +132 -0
- asecli/core/comment_purpose.py +140 -0
- asecli/core/commentary.py +225 -0
- asecli/core/compiled_metadata.py +135 -0
- asecli/core/compiled_properties.py +190 -0
- asecli/core/custom_gui.py +250 -0
- asecli/core/custom_gui_versions.py +35 -0
- asecli/core/fishbone_placement.py +159 -0
- asecli/core/fishbone_topology.py +186 -0
- asecli/core/graph_ops.py +122 -0
- asecli/core/layout.py +174 -0
- asecli/core/layout_audit.py +237 -0
- asecli/core/layout_audit_geometry.py +247 -0
- asecli/core/layout_audit_repeated.py +44 -0
- asecli/core/layout_graph.py +113 -0
- asecli/core/local_vars.py +54 -0
- asecli/core/material_gui_condition.py +68 -0
- asecli/core/material_gui_protocol.py +35 -0
- asecli/core/material_gui_spec.py +191 -0
- asecli/core/meticulous_layout.py +114 -0
- asecli/core/model.py +237 -0
- asecli/core/property_presentation.py +233 -0
- asecli/core/wire_geometry.py +83 -0
- asecli/core/wire_router.py +248 -0
- asecli/schema/__init__.py +49 -0
- asecli/schema/data/observed.json +16 -0
- asecli/schema/data/schemas.json +14106 -0
- asecli/skills/asecli/SKILL.md +275 -0
- asecli/skills/asecli/references/layout-standard.md +99 -0
- asecli/skills/asecli/references/master-output-settings-standard.md +51 -0
- asecli/skills/asecli/references/material-property-standard.md +108 -0
- asecli-0.6.2.dist-info/METADATA +594 -0
- asecli-0.6.2.dist-info/RECORD +98 -0
- asecli-0.6.2.dist-info/WHEEL +4 -0
- asecli-0.6.2.dist-info/entry_points.txt +2 -0
- asecli-0.6.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
var payloadJson = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String("{payload_base64}"));
|
|
2
|
+
var payload = Newtonsoft.Json.Linq.JObject.Parse(payloadJson);
|
|
3
|
+
var assetPath = (string)payload["asset_path"];
|
|
4
|
+
var temporaryAssetPath = (string)payload["temporary_asset_path"];
|
|
5
|
+
var template = (Newtonsoft.Json.Linq.JObject)payload["template"];
|
|
6
|
+
var nodes = (Newtonsoft.Json.Linq.JArray)payload["nodes"];
|
|
7
|
+
var connections = (Newtonsoft.Json.Linq.JArray)payload["connections"];
|
|
8
|
+
var previousWindow = AmplifyShaderEditor.UIUtils.CurrentWindow;
|
|
9
|
+
var previousSelection = UnityEditor.Selection.activeObject;
|
|
10
|
+
AmplifyShaderEditor.AmplifyShaderEditorWindow win = null;
|
|
11
|
+
bool committed = false;
|
|
12
|
+
bool success = false;
|
|
13
|
+
bool stateRestored = false;
|
|
14
|
+
System.Exception failure = null;
|
|
15
|
+
try
|
|
16
|
+
{
|
|
17
|
+
if ((int)payload["version"] != 1)
|
|
18
|
+
throw new System.Exception("unsupported EditorGraphSpec version");
|
|
19
|
+
string aseVersion = AmplifyShaderEditor.VersionInfo.StaticToString();
|
|
20
|
+
if (aseVersion != "1.9.6.2")
|
|
21
|
+
throw new System.Exception("unsupported ASE version: " + aseVersion);
|
|
22
|
+
if (string.IsNullOrEmpty(assetPath) || !assetPath.StartsWith("Assets/") ||
|
|
23
|
+
!assetPath.EndsWith(".shader") || assetPath.Contains("..") || assetPath.Contains("\\"))
|
|
24
|
+
throw new System.Exception("unsafe target asset path");
|
|
25
|
+
if (string.IsNullOrEmpty(temporaryAssetPath) || !temporaryAssetPath.StartsWith("Assets/") ||
|
|
26
|
+
!temporaryAssetPath.EndsWith(".shader") || temporaryAssetPath.Contains("..") ||
|
|
27
|
+
temporaryAssetPath.Contains("\\") || temporaryAssetPath == assetPath)
|
|
28
|
+
throw new System.Exception("unsafe temporary asset path");
|
|
29
|
+
string targetDirectory = System.IO.Path.GetDirectoryName(assetPath).Replace("\\", "/");
|
|
30
|
+
string temporaryDirectory = System.IO.Path.GetDirectoryName(temporaryAssetPath).Replace("\\", "/");
|
|
31
|
+
if (targetDirectory != temporaryDirectory ||
|
|
32
|
+
!System.IO.Path.GetFileName(temporaryAssetPath).StartsWith("ASECLI-Temp-"))
|
|
33
|
+
throw new System.Exception("temporary asset must be a controlled sibling of the target");
|
|
34
|
+
if (UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath) != null ||
|
|
35
|
+
System.IO.File.Exists(System.IO.Path.GetFullPath(assetPath)))
|
|
36
|
+
throw new System.Exception("target asset already exists");
|
|
37
|
+
if (UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(temporaryAssetPath) != null ||
|
|
38
|
+
System.IO.File.Exists(System.IO.Path.GetFullPath(temporaryAssetPath)))
|
|
39
|
+
throw new System.Exception("temporary asset already exists");
|
|
40
|
+
|
|
41
|
+
var publicInstance = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance;
|
|
42
|
+
var publicStatic = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static;
|
|
43
|
+
var privateInstance = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
|
|
44
|
+
var createTemplateMethod = typeof(AmplifyShaderEditor.AmplifyShaderEditorWindow).GetMethod(
|
|
45
|
+
"CreateNewTemplateShader", publicStatic, null,
|
|
46
|
+
new System.Type[] { typeof(string), typeof(string), typeof(string) }, null);
|
|
47
|
+
var createNodeMethod = typeof(AmplifyShaderEditor.AmplifyShaderEditorWindow).GetMethod(
|
|
48
|
+
"CreateNode", publicInstance, null,
|
|
49
|
+
new System.Type[] { typeof(System.Type), typeof(UnityEngine.Vector2), typeof(AmplifyShaderFunction), typeof(bool) }, null);
|
|
50
|
+
var createConnectionMethod = typeof(AmplifyShaderEditor.ParentGraph).GetMethod(
|
|
51
|
+
"CreateConnection", publicInstance, null,
|
|
52
|
+
new System.Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool) }, null);
|
|
53
|
+
var saveMethod = typeof(AmplifyShaderEditor.AmplifyShaderEditorWindow).GetMethod(
|
|
54
|
+
"SaveToDisk", publicInstance, null, new System.Type[] { typeof(bool) }, null);
|
|
55
|
+
var loadMethod = typeof(AmplifyShaderEditor.AmplifyShaderEditorWindow).GetMethod(
|
|
56
|
+
"LoadFromDisk", publicInstance, null,
|
|
57
|
+
new System.Type[] { typeof(string), typeof(AmplifyShaderFunction) }, null);
|
|
58
|
+
var expressionNameField = typeof(AmplifyShaderEditor.CustomExpressionNode).GetField("m_customExpressionName", privateInstance);
|
|
59
|
+
var expressionItemsField = typeof(AmplifyShaderEditor.CustomExpressionNode).GetField("m_items", privateInstance);
|
|
60
|
+
var expressionCodeField = typeof(AmplifyShaderEditor.CustomExpressionNode).GetField("m_code", privateInstance);
|
|
61
|
+
var expressionOutputField = typeof(AmplifyShaderEditor.CustomExpressionNode).GetField("m_outputTypeIdx", privateInstance);
|
|
62
|
+
var expressionFunctionField = typeof(AmplifyShaderEditor.CustomExpressionNode).GetField("m_functionMode", privateInstance);
|
|
63
|
+
var rawPropertyNameMethod = typeof(AmplifyShaderEditor.PropertyNode).GetMethod(
|
|
64
|
+
"SetRawPropertyName", publicInstance, null, new System.Type[] { typeof(string) }, null);
|
|
65
|
+
var propertyInspectorProperty = typeof(AmplifyShaderEditor.PropertyNode).GetProperty(
|
|
66
|
+
"PropertyInspectorName", publicInstance);
|
|
67
|
+
var precisionField = typeof(AmplifyShaderEditor.ParentNode).GetField(
|
|
68
|
+
"m_currentPrecisionType", privateInstance);
|
|
69
|
+
var rangedMinField = typeof(AmplifyShaderEditor.RangedFloatNode).GetField(
|
|
70
|
+
"m_min", privateInstance);
|
|
71
|
+
var rangedMaxField = typeof(AmplifyShaderEditor.RangedFloatNode).GetField(
|
|
72
|
+
"m_max", privateInstance);
|
|
73
|
+
if (createTemplateMethod == null || createNodeMethod == null || createConnectionMethod == null ||
|
|
74
|
+
saveMethod == null || loadMethod == null || expressionNameField == null ||
|
|
75
|
+
expressionItemsField == null || expressionCodeField == null ||
|
|
76
|
+
expressionOutputField == null || expressionFunctionField == null ||
|
|
77
|
+
rawPropertyNameMethod == null || propertyInspectorProperty == null ||
|
|
78
|
+
propertyInspectorProperty.GetSetMethod() == null || precisionField == null ||
|
|
79
|
+
rangedMinField == null || rangedMaxField == null)
|
|
80
|
+
throw new System.Exception("required ASE API member is missing");
|
|
81
|
+
|
|
82
|
+
var primitiveTypes = new System.Collections.Generic.Dictionary<string, System.Type> {
|
|
83
|
+
{ "add", typeof(AmplifyShaderEditor.SimpleAddOpNode) }, { "sub", typeof(AmplifyShaderEditor.SimpleSubtractOpNode) },
|
|
84
|
+
{ "mul", typeof(AmplifyShaderEditor.SimpleMultiplyOpNode) }, { "div", typeof(AmplifyShaderEditor.SimpleDivideOpNode) },
|
|
85
|
+
{ "min", typeof(AmplifyShaderEditor.SimpleMinOpNode) }, { "max", typeof(AmplifyShaderEditor.SimpleMaxOpNode) },
|
|
86
|
+
{ "remainder", typeof(AmplifyShaderEditor.SimpleRemainderNode) }, { "saturate", typeof(AmplifyShaderEditor.SaturateNode) },
|
|
87
|
+
{ "one_minus", typeof(AmplifyShaderEditor.OneMinusNode) }, { "negate", typeof(AmplifyShaderEditor.NegateNode) },
|
|
88
|
+
{ "abs", typeof(AmplifyShaderEditor.AbsOpNode) }, { "floor", typeof(AmplifyShaderEditor.FloorOpNode) },
|
|
89
|
+
{ "ceil", typeof(AmplifyShaderEditor.CeilOpNode) }, { "fract", typeof(AmplifyShaderEditor.FractNode) },
|
|
90
|
+
{ "round", typeof(AmplifyShaderEditor.RoundOpNode) }, { "trunc", typeof(AmplifyShaderEditor.TruncOpNode) },
|
|
91
|
+
{ "sign", typeof(AmplifyShaderEditor.SignOpNode) }, { "sqrt", typeof(AmplifyShaderEditor.SqrtOpNode) },
|
|
92
|
+
{ "rsqrt", typeof(AmplifyShaderEditor.RSqrtOpNode) }, { "rcp", typeof(AmplifyShaderEditor.ReciprocalOpNode) },
|
|
93
|
+
{ "normalize", typeof(AmplifyShaderEditor.NormalizeNode) }, { "length", typeof(AmplifyShaderEditor.LengthOpNode) },
|
|
94
|
+
{ "clamp", typeof(AmplifyShaderEditor.ClampOpNode) }, { "step", typeof(AmplifyShaderEditor.StepOpNode) },
|
|
95
|
+
{ "smoothstep", typeof(AmplifyShaderEditor.SmoothstepOpNode) }, { "lerp", typeof(AmplifyShaderEditor.LerpOp) },
|
|
96
|
+
{ "pow", typeof(AmplifyShaderEditor.PowerNode) }, { "exp", typeof(AmplifyShaderEditor.ExpOpNode) },
|
|
97
|
+
{ "exp2", typeof(AmplifyShaderEditor.Exp2OpNode) }, { "log", typeof(AmplifyShaderEditor.LogOpNode) },
|
|
98
|
+
{ "log2", typeof(AmplifyShaderEditor.Log2OpNode) }, { "log10", typeof(AmplifyShaderEditor.Log10OpNode) },
|
|
99
|
+
{ "sin", typeof(AmplifyShaderEditor.SinOpNode) }, { "cos", typeof(AmplifyShaderEditor.CosOpNode) },
|
|
100
|
+
{ "tan", typeof(AmplifyShaderEditor.TanOpNode) }, { "asin", typeof(AmplifyShaderEditor.ASinOpNode) },
|
|
101
|
+
{ "acos", typeof(AmplifyShaderEditor.ACosOpNode) }, { "atan", typeof(AmplifyShaderEditor.ATanOpNode) },
|
|
102
|
+
{ "atan2", typeof(AmplifyShaderEditor.ATan2OpNode) }, { "sinh", typeof(AmplifyShaderEditor.SinhOpNode) },
|
|
103
|
+
{ "cosh", typeof(AmplifyShaderEditor.CoshOpNode) }, { "tanh", typeof(AmplifyShaderEditor.TanhOpNode) },
|
|
104
|
+
{ "radians", typeof(AmplifyShaderEditor.RadiansOpNode) }, { "degrees", typeof(AmplifyShaderEditor.DegreesOpNode) },
|
|
105
|
+
{ "fmod", typeof(AmplifyShaderEditor.FmodOpNode) }, { "remap", typeof(AmplifyShaderEditor.TFHCRemapNode) },
|
|
106
|
+
{ "dot", typeof(AmplifyShaderEditor.DotProductOpNode) }, { "cross", typeof(AmplifyShaderEditor.CrossProductOpNode) },
|
|
107
|
+
{ "distance", typeof(AmplifyShaderEditor.DistanceOpNode) }, { "reflect", typeof(AmplifyShaderEditor.ReflectOpNode) },
|
|
108
|
+
{ "refract", typeof(AmplifyShaderEditor.RefractOpVec) }, { "rotate_axis", typeof(AmplifyShaderEditor.RotateAboutAxisNode) },
|
|
109
|
+
{ "append", typeof(AmplifyShaderEditor.DynamicAppendNode) }, { "swizzle", typeof(AmplifyShaderEditor.SwizzleNode) },
|
|
110
|
+
{ "component_mask", typeof(AmplifyShaderEditor.ComponentMaskNode) }, { "split", typeof(AmplifyShaderEditor.BreakToComponentsNode) },
|
|
111
|
+
{ "luminance", typeof(AmplifyShaderEditor.LuminanceNode) }, { "desaturate", typeof(AmplifyShaderEditor.DesaturateOpNode) },
|
|
112
|
+
{ "contrast", typeof(AmplifyShaderEditor.SimpleContrastOpNode) }, { "posterize", typeof(AmplifyShaderEditor.PosterizeNode) },
|
|
113
|
+
{ "rgb_to_hsv", typeof(AmplifyShaderEditor.RGBToHSVNode) }, { "hsv_to_rgb", typeof(AmplifyShaderEditor.HSVToRGBNode) },
|
|
114
|
+
{ "gamma_to_linear", typeof(AmplifyShaderEditor.GammaToLinearNode) }, { "linear_to_gamma", typeof(AmplifyShaderEditor.LinearToGammaNode) },
|
|
115
|
+
{ "not", typeof(AmplifyShaderEditor.NotNode) }, { "nand", typeof(AmplifyShaderEditor.NandNode) },
|
|
116
|
+
{ "and", typeof(AmplifyShaderEditor.AllOpNode) }, { "or", typeof(AmplifyShaderEditor.AnyOpNode) },
|
|
117
|
+
{ "select", typeof(AmplifyShaderEditor.StaticSwitch) }, { "texcoord", typeof(AmplifyShaderEditor.TextureCoordinatesNode) },
|
|
118
|
+
{ "world_position", typeof(AmplifyShaderEditor.WorldPosInputsNode) }, { "time", typeof(AmplifyShaderEditor.SimpleTimeNode) },
|
|
119
|
+
{ "vertex_color", typeof(AmplifyShaderEditor.VertexColorNode) }, { "vertex_id", typeof(AmplifyShaderEditor.VertexIdVariableNode) },
|
|
120
|
+
{ "instance_id", typeof(AmplifyShaderEditor.InstanceIdNode) }, { "world_normal", typeof(AmplifyShaderEditor.WorldNormalVector) },
|
|
121
|
+
};
|
|
122
|
+
System.Func<string, System.Type> primitiveClass = delegate (string op) {
|
|
123
|
+
System.Type found = null;
|
|
124
|
+
primitiveTypes.TryGetValue(op, out found);
|
|
125
|
+
return found;
|
|
126
|
+
};
|
|
127
|
+
System.Func<string, System.Type> constClass = delegate (string value) {
|
|
128
|
+
string s = value.Trim();
|
|
129
|
+
if (System.Text.RegularExpressions.Regex.IsMatch(s, @"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$"))
|
|
130
|
+
return typeof(AmplifyShaderEditor.RangedFloatNode);
|
|
131
|
+
if (s.StartsWith("float2")) return typeof(AmplifyShaderEditor.Vector2Node);
|
|
132
|
+
if (s.StartsWith("float3")) return typeof(AmplifyShaderEditor.Vector3Node);
|
|
133
|
+
if (s.StartsWith("float4")) return typeof(AmplifyShaderEditor.Vector4Node);
|
|
134
|
+
return null;
|
|
135
|
+
};
|
|
136
|
+
System.Func<string, float[]> parseFloats = delegate (string value) {
|
|
137
|
+
int a = value.IndexOf('(');
|
|
138
|
+
int b = value.IndexOf(')');
|
|
139
|
+
if (a < 0 || b < 0 || b <= a) return new float[0];
|
|
140
|
+
string[] parts = value.Substring(a + 1, b - a - 1).Split(',');
|
|
141
|
+
float[] result = new float[parts.Length];
|
|
142
|
+
for (int i = 0; i < parts.Length; i++)
|
|
143
|
+
result[i] = float.Parse(parts[i].Trim(), System.Globalization.CultureInfo.InvariantCulture);
|
|
144
|
+
return result;
|
|
145
|
+
};
|
|
146
|
+
System.Action<AmplifyShaderEditor.ParentNode, string> writeConst = delegate (AmplifyShaderEditor.ParentNode node, string value) {
|
|
147
|
+
if (node is AmplifyShaderEditor.RangedFloatNode)
|
|
148
|
+
((AmplifyShaderEditor.RangedFloatNode)node).Value = float.Parse(value.Trim(), System.Globalization.CultureInfo.InvariantCulture);
|
|
149
|
+
else if (node is AmplifyShaderEditor.Vector2Node) { float[] f = parseFloats(value); ((AmplifyShaderEditor.Vector2Node)node).Value = new UnityEngine.Vector2(f[0], f[1]); }
|
|
150
|
+
else if (node is AmplifyShaderEditor.Vector3Node) { float[] f = parseFloats(value); ((AmplifyShaderEditor.Vector3Node)node).Value = new UnityEngine.Vector3(f[0], f[1], f[2]); }
|
|
151
|
+
else if (node is AmplifyShaderEditor.Vector4Node) { float[] f = parseFloats(value); ((AmplifyShaderEditor.Vector4Node)node).Value = new UnityEngine.Vector4(f[0], f[1], f[2], f[3]); }
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
string templateGuid = (string)template["guid"];
|
|
155
|
+
string shaderName = (string)template["shader_name"];
|
|
156
|
+
var shader = AmplifyShaderEditor.AmplifyShaderEditorWindow.CreateNewTemplateShader(
|
|
157
|
+
templateGuid, temporaryAssetPath, shaderName + ".shader");
|
|
158
|
+
win = AmplifyShaderEditor.UIUtils.CurrentWindow as AmplifyShaderEditor.AmplifyShaderEditorWindow;
|
|
159
|
+
if (shader == null || win == null || win.CurrentGraph == null || win.CurrentGraph.CurrentMasterNode == null)
|
|
160
|
+
throw new System.Exception("ASE template graph was not created");
|
|
161
|
+
win.Show();
|
|
162
|
+
var layoutEvent = new UnityEngine.Event();
|
|
163
|
+
layoutEvent.type = UnityEngine.EventType.Layout;
|
|
164
|
+
win.SendEvent(layoutEvent);
|
|
165
|
+
var repaintEvent = new UnityEngine.Event();
|
|
166
|
+
repaintEvent.type = UnityEngine.EventType.Repaint;
|
|
167
|
+
win.SendEvent(repaintEvent);
|
|
168
|
+
|
|
169
|
+
var graph = win.CurrentGraph;
|
|
170
|
+
var aliasIds = new System.Collections.Generic.Dictionary<string, int>();
|
|
171
|
+
var recipePrimitiveIds = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, int>>();
|
|
172
|
+
var recipePrimitiveClasses = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, string>>();
|
|
173
|
+
var recipeOutputIds = new System.Collections.Generic.Dictionary<string, int>();
|
|
174
|
+
var recipeInputTargets = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<System.Tuple<int, int>>>>();
|
|
175
|
+
int masterId = graph.CurrentMasterNode.UniqueId;
|
|
176
|
+
foreach (Newtonsoft.Json.Linq.JObject nodeSpec in nodes)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
{
|
|
2
|
+
string alias = (string)nodeSpec["alias"];
|
|
3
|
+
string kind = (string)nodeSpec["kind"];
|
|
4
|
+
var position = (Newtonsoft.Json.Linq.JArray)nodeSpec["position"];
|
|
5
|
+
if (kind == "recipe")
|
|
6
|
+
{
|
|
7
|
+
var recipeName = (string)nodeSpec["recipe"];
|
|
8
|
+
var recipeCode = (string)nodeSpec["code"];
|
|
9
|
+
var recipeOutputType = (string)nodeSpec["output_type"];
|
|
10
|
+
var recipeInputs = (Newtonsoft.Json.Linq.JArray)nodeSpec["inputs"];
|
|
11
|
+
var expansion = (Newtonsoft.Json.Linq.JObject)nodeSpec["expansion"];
|
|
12
|
+
var primitiveSpecs = (Newtonsoft.Json.Linq.JArray)expansion["primitives"];
|
|
13
|
+
string expansionOutput = (string)expansion["output"];
|
|
14
|
+
|
|
15
|
+
bool native = true;
|
|
16
|
+
foreach (Newtonsoft.Json.Linq.JObject primitiveSpec in primitiveSpecs)
|
|
17
|
+
{
|
|
18
|
+
string opName = (string)primitiveSpec["op"];
|
|
19
|
+
System.Type resolved = opName == "const" ? constClass((string)primitiveSpec["value"]) : primitiveClass(opName);
|
|
20
|
+
if (resolved == null) { native = false; break; }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!native)
|
|
24
|
+
{
|
|
25
|
+
var expression = win.CreateNode(typeof(AmplifyShaderEditor.CustomExpressionNode),
|
|
26
|
+
new UnityEngine.Vector2((float)position[0], (float)position[1]), null, false) as AmplifyShaderEditor.CustomExpressionNode;
|
|
27
|
+
if (expression == null)
|
|
28
|
+
throw new System.Exception("ASE failed to create recipe fallback expression: " + alias);
|
|
29
|
+
var inputSpecs = recipeInputs;
|
|
30
|
+
var items = new System.Collections.Generic.List<AmplifyShaderEditor.CustomExpressionInputItem>();
|
|
31
|
+
for (int inputIndex = 0; inputIndex < inputSpecs.Count; inputIndex++)
|
|
32
|
+
{
|
|
33
|
+
var inputSpec = (Newtonsoft.Json.Linq.JObject)inputSpecs[inputIndex];
|
|
34
|
+
string inputName = (string)inputSpec["name"];
|
|
35
|
+
var inputType = (AmplifyShaderEditor.WirePortDataType)System.Enum.Parse(
|
|
36
|
+
typeof(AmplifyShaderEditor.WirePortDataType), (string)inputSpec["type"]);
|
|
37
|
+
var item = new AmplifyShaderEditor.CustomExpressionInputItem(
|
|
38
|
+
AmplifyShaderEditor.PrecisionType.Inherit, AmplifyShaderEditor.VariableQualifiers.In,
|
|
39
|
+
string.Empty, false, true, string.Empty);
|
|
40
|
+
item.Type = inputType;
|
|
41
|
+
items.Add(item);
|
|
42
|
+
if (inputIndex == 0)
|
|
43
|
+
expression.InputPorts[0].ChangeProperties(inputName, inputType, false);
|
|
44
|
+
else
|
|
45
|
+
expression.AddInputPort(inputType, false, inputName);
|
|
46
|
+
}
|
|
47
|
+
var outputType = (AmplifyShaderEditor.WirePortDataType)System.Enum.Parse(
|
|
48
|
+
typeof(AmplifyShaderEditor.WirePortDataType), recipeOutputType);
|
|
49
|
+
int outputTypeIndex = recipeOutputType == "INT" ? 0 :
|
|
50
|
+
recipeOutputType == "FLOAT" ? 1 :
|
|
51
|
+
recipeOutputType == "FLOAT2" ? 2 :
|
|
52
|
+
recipeOutputType == "FLOAT3" ? 3 :
|
|
53
|
+
recipeOutputType == "FLOAT4" ? 4 :
|
|
54
|
+
recipeOutputType == "FLOAT3x3" ? 5 : 6;
|
|
55
|
+
expression.OutputPorts[0].ChangeType(outputType, false);
|
|
56
|
+
expressionNameField.SetValue(expression, recipeName);
|
|
57
|
+
expressionItemsField.SetValue(expression, items);
|
|
58
|
+
expressionCodeField.SetValue(expression, recipeCode);
|
|
59
|
+
expressionOutputField.SetValue(expression, outputTypeIndex);
|
|
60
|
+
expressionFunctionField.SetValue(expression, recipeCode.Contains("return"));
|
|
61
|
+
aliasIds.Add(alias, expression.UniqueId);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var inputIndexByName = new System.Collections.Generic.Dictionary<string, int>();
|
|
66
|
+
for (int i = 0; i < recipeInputs.Count; i++)
|
|
67
|
+
inputIndexByName[(string)((Newtonsoft.Json.Linq.JObject)recipeInputs[i])["name"]] = i;
|
|
68
|
+
var idToNode = new System.Collections.Generic.Dictionary<string, AmplifyShaderEditor.ParentNode>();
|
|
69
|
+
var idToClass = new System.Collections.Generic.Dictionary<string, string>();
|
|
70
|
+
foreach (Newtonsoft.Json.Linq.JObject primitiveSpec in primitiveSpecs)
|
|
71
|
+
{
|
|
72
|
+
string pid = (string)primitiveSpec["id"];
|
|
73
|
+
string opName = (string)primitiveSpec["op"];
|
|
74
|
+
System.Type resolved = opName == "const" ? constClass((string)primitiveSpec["value"]) : primitiveClass(opName);
|
|
75
|
+
var pn = win.CreateNode(resolved,
|
|
76
|
+
new UnityEngine.Vector2((float)position[0], (float)position[1]), null, false);
|
|
77
|
+
if (pn == null || pn.GetType() != resolved)
|
|
78
|
+
throw new System.Exception("ASE failed to create recipe primitive: " + pid);
|
|
79
|
+
if (opName == "const")
|
|
80
|
+
writeConst(pn, (string)primitiveSpec["value"]);
|
|
81
|
+
idToNode[pid] = pn;
|
|
82
|
+
idToClass[pid] = resolved.Name;
|
|
83
|
+
}
|
|
84
|
+
var targets = new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<System.Tuple<int, int>>>();
|
|
85
|
+
foreach (Newtonsoft.Json.Linq.JObject primitiveSpec in primitiveSpecs)
|
|
86
|
+
{
|
|
87
|
+
string pid = (string)primitiveSpec["id"];
|
|
88
|
+
var pn = idToNode[pid];
|
|
89
|
+
var args = (Newtonsoft.Json.Linq.JArray)primitiveSpec["args"];
|
|
90
|
+
if (args == null) continue;
|
|
91
|
+
for (int argIndex = 0; argIndex < args.Count; argIndex++)
|
|
92
|
+
{
|
|
93
|
+
string argRef = (string)args[argIndex];
|
|
94
|
+
if (inputIndexByName.ContainsKey(argRef))
|
|
95
|
+
{
|
|
96
|
+
int inputPort = inputIndexByName[argRef];
|
|
97
|
+
if (!targets.ContainsKey(inputPort))
|
|
98
|
+
targets[inputPort] = new System.Collections.Generic.List<System.Tuple<int, int>>();
|
|
99
|
+
targets[inputPort].Add(System.Tuple.Create(pn.UniqueId, argIndex));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
int sourceNodeId = idToNode[argRef].UniqueId;
|
|
103
|
+
graph.CreateConnection(pn.UniqueId, argIndex, sourceNodeId, 0, false);
|
|
104
|
+
if (!pn.GetInputPortByUniqueId(argIndex).IsConnectedTo(sourceNodeId, 0))
|
|
105
|
+
throw new System.Exception("ASE rejected recipe primitive connection");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
recipePrimitiveIds[alias] = new System.Collections.Generic.Dictionary<string, int>();
|
|
109
|
+
recipePrimitiveClasses[alias] = idToClass;
|
|
110
|
+
foreach (System.Collections.Generic.KeyValuePair<string, AmplifyShaderEditor.ParentNode> kv in idToNode)
|
|
111
|
+
recipePrimitiveIds[alias][kv.Key] = kv.Value.UniqueId;
|
|
112
|
+
recipeOutputIds[alias] = idToNode[expansionOutput].UniqueId;
|
|
113
|
+
recipeInputTargets[alias] = targets;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
System.Type nodeType = null;
|
|
118
|
+
if (kind == "sampler") nodeType = typeof(AmplifyShaderEditor.SamplerNode);
|
|
119
|
+
else if (kind == "custom_expression") nodeType = typeof(AmplifyShaderEditor.CustomExpressionNode);
|
|
120
|
+
else if (kind == "primitive")
|
|
121
|
+
{
|
|
122
|
+
nodeType = primitiveClass((string)nodeSpec["op"]);
|
|
123
|
+
if (nodeType == null) throw new System.Exception("primitive op escaped closure: " + (string)nodeSpec["op"]);
|
|
124
|
+
}
|
|
125
|
+
else
|
|
126
|
+
{
|
|
127
|
+
string typeName = (string)nodeSpec["type"];
|
|
128
|
+
if (typeName == "WorldPosInputsNode") nodeType = typeof(AmplifyShaderEditor.WorldPosInputsNode);
|
|
129
|
+
else if (typeName == "TextureCoordinatesNode") nodeType = typeof(AmplifyShaderEditor.TextureCoordinatesNode);
|
|
130
|
+
else if (typeName == "BreakToComponentsNode") nodeType = typeof(AmplifyShaderEditor.BreakToComponentsNode);
|
|
131
|
+
else if (typeName == "SimpleAddOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleAddOpNode);
|
|
132
|
+
else if (typeName == "SimpleSubtractOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleSubtractOpNode);
|
|
133
|
+
else if (typeName == "SimpleMultiplyOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleMultiplyOpNode);
|
|
134
|
+
else if (typeName == "SimpleDivideOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleDivideOpNode);
|
|
135
|
+
else if (typeName == "SimpleMinOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleMinOpNode);
|
|
136
|
+
else if (typeName == "SimpleMaxOpNode") nodeType = typeof(AmplifyShaderEditor.SimpleMaxOpNode);
|
|
137
|
+
else if (typeName == "SaturateNode") nodeType = typeof(AmplifyShaderEditor.SaturateNode);
|
|
138
|
+
else if (typeName == "OneMinusNode") nodeType = typeof(AmplifyShaderEditor.OneMinusNode);
|
|
139
|
+
else if (typeName == "LerpOp") nodeType = typeof(AmplifyShaderEditor.LerpOp);
|
|
140
|
+
else if (typeName == "TexturePropertyNode") nodeType = typeof(AmplifyShaderEditor.TexturePropertyNode);
|
|
141
|
+
else if (typeName == "RangedFloatNode") nodeType = typeof(AmplifyShaderEditor.RangedFloatNode);
|
|
142
|
+
else if (typeName == "Matrix4X4Node") nodeType = typeof(AmplifyShaderEditor.Matrix4X4Node);
|
|
143
|
+
else if (typeName == "Vector4Node") nodeType = typeof(AmplifyShaderEditor.Vector4Node);
|
|
144
|
+
else throw new System.Exception("node type escaped allowlist: " + typeName);
|
|
145
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
var created = win.CreateNode(
|
|
2
|
+
nodeType,
|
|
3
|
+
new UnityEngine.Vector2((float)position[0], (float)position[1]),
|
|
4
|
+
null,
|
|
5
|
+
false);
|
|
6
|
+
if (created == null || created.GetType() != nodeType)
|
|
7
|
+
throw new System.Exception("ASE failed to create node: " + alias);
|
|
8
|
+
aliasIds.Add(alias, created.UniqueId);
|
|
9
|
+
|
|
10
|
+
if (kind == "sampler")
|
|
11
|
+
{
|
|
12
|
+
var sampler = created as AmplifyShaderEditor.SamplerNode;
|
|
13
|
+
sampler.CurrentParameterType = (AmplifyShaderEditor.PropertyType)System.Enum.Parse(
|
|
14
|
+
typeof(AmplifyShaderEditor.PropertyType), (string)nodeSpec["parameter_type"]);
|
|
15
|
+
sampler.SetPropertyName((string)nodeSpec["property_name"]);
|
|
16
|
+
sampler.SetInspectorName((string)nodeSpec["inspector_name"]);
|
|
17
|
+
sampler.AutoRegister = true;
|
|
18
|
+
sampler.OnPropertyNameChanged();
|
|
19
|
+
}
|
|
20
|
+
else if (kind == "property")
|
|
21
|
+
{
|
|
22
|
+
var property = created as AmplifyShaderEditor.PropertyNode;
|
|
23
|
+
if (property == null) throw new System.Exception("property-node cast failed: " + alias);
|
|
24
|
+
property.CurrentParameterType = (AmplifyShaderEditor.PropertyType)System.Enum.Parse(
|
|
25
|
+
typeof(AmplifyShaderEditor.PropertyType), (string)nodeSpec["parameter_type"]);
|
|
26
|
+
property.SetRawPropertyName((string)nodeSpec["property_name"]);
|
|
27
|
+
propertyInspectorProperty.SetValue(property, (string)nodeSpec["inspector_name"], null);
|
|
28
|
+
property.AutoRegister = true;
|
|
29
|
+
property.OnPropertyNameChanged();
|
|
30
|
+
if (property is AmplifyShaderEditor.RangedFloatNode && nodeSpec["default"] != null)
|
|
31
|
+
{
|
|
32
|
+
var ranged = (AmplifyShaderEditor.RangedFloatNode)property;
|
|
33
|
+
ranged.Value = (float)nodeSpec["default"];
|
|
34
|
+
if (nodeSpec["min"] != null)
|
|
35
|
+
{
|
|
36
|
+
rangedMinField.SetValue(ranged, (float)nodeSpec["min"]);
|
|
37
|
+
rangedMaxField.SetValue(ranged, (float)nodeSpec["max"]);
|
|
38
|
+
ranged.SetFloatMode(false);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (property is AmplifyShaderEditor.Vector4Node && nodeSpec["default"] != null)
|
|
42
|
+
{
|
|
43
|
+
var vector = (AmplifyShaderEditor.Vector4Node)property;
|
|
44
|
+
var values = (Newtonsoft.Json.Linq.JArray)nodeSpec["default"];
|
|
45
|
+
vector.Value = new UnityEngine.Vector4((float)values[0], (float)values[1], (float)values[2], (float)values[3]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (kind == "custom_expression")
|
|
49
|
+
{
|
|
50
|
+
var expression = created as AmplifyShaderEditor.CustomExpressionNode;
|
|
51
|
+
string expressionCode = (string)nodeSpec["code"];
|
|
52
|
+
var inputSpecs = (Newtonsoft.Json.Linq.JArray)nodeSpec["inputs"];
|
|
53
|
+
var items = new System.Collections.Generic.List<AmplifyShaderEditor.CustomExpressionInputItem>();
|
|
54
|
+
for (int inputIndex = 0; inputIndex < inputSpecs.Count; inputIndex++)
|
|
55
|
+
{
|
|
56
|
+
var inputSpec = (Newtonsoft.Json.Linq.JObject)inputSpecs[inputIndex];
|
|
57
|
+
string inputName = (string)inputSpec["name"];
|
|
58
|
+
var inputType = (AmplifyShaderEditor.WirePortDataType)System.Enum.Parse(
|
|
59
|
+
typeof(AmplifyShaderEditor.WirePortDataType), (string)inputSpec["type"]);
|
|
60
|
+
var item = new AmplifyShaderEditor.CustomExpressionInputItem(
|
|
61
|
+
AmplifyShaderEditor.PrecisionType.Inherit,
|
|
62
|
+
AmplifyShaderEditor.VariableQualifiers.In,
|
|
63
|
+
string.Empty,
|
|
64
|
+
false,
|
|
65
|
+
true,
|
|
66
|
+
string.Empty);
|
|
67
|
+
item.Type = inputType;
|
|
68
|
+
items.Add(item);
|
|
69
|
+
if (inputIndex == 0)
|
|
70
|
+
expression.InputPorts[0].ChangeProperties(inputName, inputType, false);
|
|
71
|
+
else
|
|
72
|
+
expression.AddInputPort(inputType, false, inputName);
|
|
73
|
+
}
|
|
74
|
+
string outputTypeName = (string)nodeSpec["output_type"];
|
|
75
|
+
var outputType = (AmplifyShaderEditor.WirePortDataType)System.Enum.Parse(
|
|
76
|
+
typeof(AmplifyShaderEditor.WirePortDataType), outputTypeName);
|
|
77
|
+
int outputTypeIndex = outputTypeName == "INT" ? 0 :
|
|
78
|
+
outputTypeName == "FLOAT" ? 1 :
|
|
79
|
+
outputTypeName == "FLOAT2" ? 2 :
|
|
80
|
+
outputTypeName == "FLOAT3" ? 3 :
|
|
81
|
+
outputTypeName == "FLOAT4" ? 4 :
|
|
82
|
+
outputTypeName == "FLOAT3x3" ? 5 : 6;
|
|
83
|
+
expression.OutputPorts[0].ChangeType(outputType, false);
|
|
84
|
+
expressionNameField.SetValue(expression, (string)nodeSpec["name"]);
|
|
85
|
+
expressionItemsField.SetValue(expression, items);
|
|
86
|
+
expressionCodeField.SetValue(expression, expressionCode);
|
|
87
|
+
expressionOutputField.SetValue(expression, outputTypeIndex);
|
|
88
|
+
expressionFunctionField.SetValue(expression, expressionCode.Contains("return"));
|
|
89
|
+
}
|
|
90
|
+
if (nodeSpec["precision"] != null)
|
|
91
|
+
precisionField.SetValue(created,
|
|
92
|
+
(AmplifyShaderEditor.PrecisionType)System.Enum.Parse(
|
|
93
|
+
typeof(AmplifyShaderEditor.PrecisionType), (string)nodeSpec["precision"]));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
foreach (Newtonsoft.Json.Linq.JObject connectionSpec in connections)
|
|
97
|
+
{
|
|
98
|
+
var sourceSpec = (Newtonsoft.Json.Linq.JObject)connectionSpec["from"];
|
|
99
|
+
var destinationSpec = (Newtonsoft.Json.Linq.JObject)connectionSpec["to"];
|
|
100
|
+
string sourceAlias = (string)sourceSpec["node"];
|
|
101
|
+
string destinationAlias = (string)destinationSpec["node"];
|
|
102
|
+
int sourcePortId = (int)sourceSpec["port"];
|
|
103
|
+
int destinationPortId = (int)destinationSpec["port"];
|
|
104
|
+
int sourceNodeId = recipeOutputIds.ContainsKey(sourceAlias) ? recipeOutputIds[sourceAlias] : aliasIds[sourceAlias];
|
|
105
|
+
int sourceOutPort = recipeOutputIds.ContainsKey(sourceAlias) ? 0 : sourcePortId;
|
|
106
|
+
var sourceNode = graph.GetNode(sourceNodeId);
|
|
107
|
+
if (sourceNode == null || sourceNode.GetOutputPortByUniqueId(sourceOutPort) == null)
|
|
108
|
+
throw new System.Exception("connection source endpoint not found");
|
|
109
|
+
|
|
110
|
+
if (destinationAlias == "master")
|
|
111
|
+
{
|
|
112
|
+
graph.CreateConnection(masterId, destinationPortId, sourceNodeId, sourceOutPort, false);
|
|
113
|
+
if (!graph.CurrentMasterNode.GetInputPortByUniqueId(destinationPortId).IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
114
|
+
throw new System.Exception("ASE rejected connection");
|
|
115
|
+
}
|
|
116
|
+
else if (recipeInputTargets.ContainsKey(destinationAlias))
|
|
117
|
+
{
|
|
118
|
+
var targets = recipeInputTargets[destinationAlias];
|
|
119
|
+
if (!targets.ContainsKey(destinationPortId) || targets[destinationPortId].Count == 0)
|
|
120
|
+
throw new System.Exception("recipe input port has no consumer");
|
|
121
|
+
foreach (System.Tuple<int, int> target in targets[destinationPortId])
|
|
122
|
+
{
|
|
123
|
+
graph.CreateConnection(target.Item1, target.Item2, sourceNodeId, sourceOutPort, false);
|
|
124
|
+
if (!graph.GetNode(target.Item1).GetInputPortByUniqueId(target.Item2).IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
125
|
+
throw new System.Exception("ASE rejected recipe input connection");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else
|
|
129
|
+
{
|
|
130
|
+
int destinationNodeId = aliasIds[destinationAlias];
|
|
131
|
+
var destinationNode = graph.GetNode(destinationNodeId);
|
|
132
|
+
if (destinationNode == null ||
|
|
133
|
+
destinationNode.GetInputPortByUniqueId(destinationPortId) == null)
|
|
134
|
+
throw new System.Exception("connection destination endpoint not found");
|
|
135
|
+
graph.CreateConnection(destinationNodeId, destinationPortId, sourceNodeId, sourceOutPort, false);
|
|
136
|
+
if (!destinationNode.GetInputPortByUniqueId(destinationPortId).IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
137
|
+
throw new System.Exception("ASE rejected connection");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
bool saved = win.SaveToDisk(false);
|
|
2
|
+
if (!saved) throw new System.Exception("ASE SaveToDisk returned false");
|
|
3
|
+
var loadResult = win.LoadFromDisk(temporaryAssetPath, null);
|
|
4
|
+
bool reloaded = loadResult == AmplifyShaderEditor.ShaderLoadResult.LOADED ||
|
|
5
|
+
loadResult == AmplifyShaderEditor.ShaderLoadResult.TEMPLATE_LOADED;
|
|
6
|
+
if (!reloaded) throw new System.Exception("ASE temporary LoadFromDisk failed: " + loadResult);
|
|
7
|
+
|
|
8
|
+
graph = win.CurrentGraph;
|
|
9
|
+
var reloadedMaster = graph.CurrentMasterNode as AmplifyShaderEditor.TemplateMultiPassMasterNode;
|
|
10
|
+
var reloadedShader = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Shader>(temporaryAssetPath);
|
|
11
|
+
if (reloadedMaster == null || reloadedMaster.CurrentTemplate == null || reloadedShader == null ||
|
|
12
|
+
reloadedMaster.CurrentTemplate.GUID != templateGuid ||
|
|
13
|
+
reloadedMaster.ShaderName != shaderName || reloadedShader.name != shaderName)
|
|
14
|
+
throw new System.Exception("template or shader identity changed after temporary reload");
|
|
15
|
+
var manifestNodes = new Newtonsoft.Json.Linq.JArray();
|
|
16
|
+
foreach (Newtonsoft.Json.Linq.JObject nodeSpec in nodes)
|
|
17
|
+
{
|
|
18
|
+
string alias = (string)nodeSpec["alias"];
|
|
19
|
+
string kind = (string)nodeSpec["kind"];
|
|
20
|
+
var manifestNode = new Newtonsoft.Json.Linq.JObject();
|
|
21
|
+
manifestNode["alias"] = alias;
|
|
22
|
+
manifestNode["kind"] = kind;
|
|
23
|
+
|
|
24
|
+
if (kind == "recipe" && recipePrimitiveIds.ContainsKey(alias))
|
|
25
|
+
{
|
|
26
|
+
manifestNode["type"] = "Recipe";
|
|
27
|
+
manifestNode["recipe"] = (string)nodeSpec["recipe"];
|
|
28
|
+
manifestNode["output_type"] = (string)nodeSpec["output_type"];
|
|
29
|
+
var manifestExpansion = new Newtonsoft.Json.Linq.JArray();
|
|
30
|
+
var expectedPrimitives = (Newtonsoft.Json.Linq.JArray)((Newtonsoft.Json.Linq.JObject)nodeSpec["expansion"])["primitives"];
|
|
31
|
+
foreach (Newtonsoft.Json.Linq.JObject primitiveSpec in expectedPrimitives)
|
|
32
|
+
{
|
|
33
|
+
string pid = (string)primitiveSpec["id"];
|
|
34
|
+
var pn = graph.GetNode(recipePrimitiveIds[alias][pid]);
|
|
35
|
+
if (pn == null)
|
|
36
|
+
throw new System.Exception("recipe primitive missing after reload: " + pid);
|
|
37
|
+
if (pn.GetType().Name != recipePrimitiveClasses[alias][pid])
|
|
38
|
+
throw new System.Exception("recipe primitive type changed after reload: " + pid);
|
|
39
|
+
var manifestPrimitive = new Newtonsoft.Json.Linq.JObject();
|
|
40
|
+
manifestPrimitive["id"] = pid;
|
|
41
|
+
manifestPrimitive["type"] = pn.GetType().Name;
|
|
42
|
+
manifestExpansion.Add(manifestPrimitive);
|
|
43
|
+
}
|
|
44
|
+
manifestNode["expansion_nodes"] = manifestExpansion;
|
|
45
|
+
manifestNodes.Add(manifestNode);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
var actualNode = graph.GetNode(aliasIds[alias]);
|
|
50
|
+
if (actualNode == null) throw new System.Exception("node missing after reload: " + alias);
|
|
51
|
+
string expectedType = kind == "sampler" ? "SamplerNode" :
|
|
52
|
+
kind == "custom_expression" ? "CustomExpressionNode" :
|
|
53
|
+
kind == "primitive" ? primitiveClass((string)nodeSpec["op"]).Name :
|
|
54
|
+
kind == "recipe" ? "CustomExpressionNode" :
|
|
55
|
+
(string)nodeSpec["type"];
|
|
56
|
+
if (actualNode.GetType().Name != expectedType)
|
|
57
|
+
throw new System.Exception("node type changed after reload: " + alias);
|
|
58
|
+
manifestNode["type"] = actualNode.GetType().Name;
|
|
59
|
+
if (kind == "sampler" || kind == "property")
|
|
60
|
+
{
|
|
61
|
+
var property = actualNode as AmplifyShaderEditor.PropertyNode;
|
|
62
|
+
if (property.PropertyName != (string)nodeSpec["property_name"] ||
|
|
63
|
+
property.PropertyInspectorName != (string)nodeSpec["inspector_name"] ||
|
|
64
|
+
property.CurrentParameterType.ToString() != (string)nodeSpec["parameter_type"])
|
|
65
|
+
throw new System.Exception("property changed after reload: " + alias);
|
|
66
|
+
manifestNode["property_name"] = property.PropertyName;
|
|
67
|
+
manifestNode["inspector_name"] = property.PropertyInspectorName;
|
|
68
|
+
manifestNode["parameter_type"] = property.CurrentParameterType.ToString();
|
|
69
|
+
}
|
|
70
|
+
else if (kind == "custom_expression" || kind == "recipe")
|
|
71
|
+
{
|
|
72
|
+
var expression = actualNode as AmplifyShaderEditor.CustomExpressionNode;
|
|
73
|
+
string actualName = (string)expressionNameField.GetValue(expression);
|
|
74
|
+
string actualCode = (string)expressionCodeField.GetValue(expression);
|
|
75
|
+
string actualOutputType = expression.OutputPorts[0].DataType.ToString();
|
|
76
|
+
if (actualName != (string)nodeSpec[(kind == "recipe") ? "recipe" : "name"] ||
|
|
77
|
+
actualCode != (string)nodeSpec["code"] || actualOutputType != (string)nodeSpec["output_type"])
|
|
78
|
+
throw new System.Exception("custom expression changed after reload: " + alias);
|
|
79
|
+
manifestNode["name"] = actualName;
|
|
80
|
+
manifestNode["code"] = actualCode;
|
|
81
|
+
manifestNode["output_type"] = actualOutputType;
|
|
82
|
+
var manifestInputs = new Newtonsoft.Json.Linq.JArray();
|
|
83
|
+
var expectedInputs = (Newtonsoft.Json.Linq.JArray)nodeSpec["inputs"];
|
|
84
|
+
if (expression.InputPorts.Count != expectedInputs.Count)
|
|
85
|
+
throw new System.Exception("custom expression input count changed after reload: " + alias);
|
|
86
|
+
for (int inputIndex = 0; inputIndex < expectedInputs.Count; inputIndex++)
|
|
87
|
+
{
|
|
88
|
+
var expectedInput = (Newtonsoft.Json.Linq.JObject)expectedInputs[inputIndex];
|
|
89
|
+
var actualInput = expression.InputPorts[inputIndex];
|
|
90
|
+
if (actualInput.Name != (string)expectedInput["name"] ||
|
|
91
|
+
actualInput.DataType.ToString() != (string)expectedInput["type"])
|
|
92
|
+
throw new System.Exception("custom expression input changed after reload: " + alias);
|
|
93
|
+
var manifestInput = new Newtonsoft.Json.Linq.JObject();
|
|
94
|
+
manifestInput["name"] = actualInput.Name;
|
|
95
|
+
manifestInput["type"] = actualInput.DataType.ToString();
|
|
96
|
+
manifestInputs.Add(manifestInput);
|
|
97
|
+
}
|
|
98
|
+
manifestNode["inputs"] = manifestInputs;
|
|
99
|
+
}
|
|
100
|
+
else if (kind == "primitive")
|
|
101
|
+
{
|
|
102
|
+
manifestNode["op"] = (string)nodeSpec["op"];
|
|
103
|
+
}
|
|
104
|
+
if (nodeSpec["precision"] != null)
|
|
105
|
+
manifestNode["precision"] = ((AmplifyShaderEditor.PrecisionType)
|
|
106
|
+
precisionField.GetValue(actualNode)).ToString();
|
|
107
|
+
if (nodeSpec["default"] != null)
|
|
108
|
+
{
|
|
109
|
+
if (actualNode is AmplifyShaderEditor.RangedFloatNode)
|
|
110
|
+
manifestNode["default"] = ((AmplifyShaderEditor.RangedFloatNode)actualNode).Value;
|
|
111
|
+
else if (actualNode is AmplifyShaderEditor.Vector4Node)
|
|
112
|
+
{
|
|
113
|
+
var vector = ((AmplifyShaderEditor.Vector4Node)actualNode).Value;
|
|
114
|
+
manifestNode["default"] = new Newtonsoft.Json.Linq.JArray(vector.x, vector.y, vector.z, vector.w);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (nodeSpec["min"] != null)
|
|
118
|
+
{
|
|
119
|
+
manifestNode["min"] = (float)rangedMinField.GetValue(actualNode);
|
|
120
|
+
manifestNode["max"] = (float)rangedMaxField.GetValue(actualNode);
|
|
121
|
+
}
|
|
122
|
+
manifestNodes.Add(manifestNode);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
var manifestConnections = new Newtonsoft.Json.Linq.JArray();
|
|
126
|
+
foreach (Newtonsoft.Json.Linq.JObject connectionSpec in connections)
|
|
127
|
+
{
|
|
128
|
+
var sourceSpec = (Newtonsoft.Json.Linq.JObject)connectionSpec["from"];
|
|
129
|
+
var destinationSpec = (Newtonsoft.Json.Linq.JObject)connectionSpec["to"];
|
|
130
|
+
string sourceAlias = (string)sourceSpec["node"];
|
|
131
|
+
string destinationAlias = (string)destinationSpec["node"];
|
|
132
|
+
int sourcePortId = (int)sourceSpec["port"];
|
|
133
|
+
int destinationPortId = (int)destinationSpec["port"];
|
|
134
|
+
int sourceNodeId = recipeOutputIds.ContainsKey(sourceAlias) ? recipeOutputIds[sourceAlias] : aliasIds[sourceAlias];
|
|
135
|
+
int sourceOutPort = recipeOutputIds.ContainsKey(sourceAlias) ? 0 : sourcePortId;
|
|
136
|
+
|
|
137
|
+
if (destinationAlias == "master")
|
|
138
|
+
{
|
|
139
|
+
if (!graph.CurrentMasterNode.GetInputPortByUniqueId(destinationPortId).IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
140
|
+
throw new System.Exception("connection missing after reload");
|
|
141
|
+
}
|
|
142
|
+
else if (recipeInputTargets.ContainsKey(destinationAlias))
|
|
143
|
+
{
|
|
144
|
+
var targets = recipeInputTargets[destinationAlias];
|
|
145
|
+
if (!targets.ContainsKey(destinationPortId) || targets[destinationPortId].Count == 0)
|
|
146
|
+
throw new System.Exception("recipe input port has no consumer after reload");
|
|
147
|
+
foreach (System.Tuple<int, int> target in targets[destinationPortId])
|
|
148
|
+
{
|
|
149
|
+
if (!graph.GetNode(target.Item1).GetInputPortByUniqueId(target.Item2).IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
150
|
+
throw new System.Exception("recipe input connection missing after reload");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else
|
|
154
|
+
{
|
|
155
|
+
int destinationNodeId = aliasIds[destinationAlias];
|
|
156
|
+
var destinationPort = graph.GetNode(destinationNodeId).GetInputPortByUniqueId(destinationPortId);
|
|
157
|
+
if (destinationPort == null || !destinationPort.IsConnectedTo(sourceNodeId, sourceOutPort))
|
|
158
|
+
throw new System.Exception("connection missing after reload");
|
|
159
|
+
}
|
|
160
|
+
manifestConnections.Add(connectionSpec.DeepClone());
|
|
161
|
+
}
|