Просмотр исходного кода

[shgraph] Can load shader graph

Clément Espeute 1 год назад
Родитель
Сommit
7b10eaffc1

+ 5 - 4
hide/view/Graph.hx → hide/view/GraphEditor.hx

@@ -23,7 +23,7 @@ typedef UndoFn = (isUndo : Bool) -> Void;
 typedef UndoBuffer = Array<UndoFn>;
 typedef UndoBuffer = Array<UndoFn>;
 
 
 @:access(hide.view.shadereditor.Box)
 @:access(hide.view.shadereditor.Box)
-class Graph extends hide.comp.Component {
+class GraphEditor extends hide.comp.Component {
 	var heapsScene : JQuery;
 	var heapsScene : JQuery;
 	var editor : hide.view.GraphInterface.IGraphEditor;
 	var editor : hide.view.GraphInterface.IGraphEditor;
 	var editorDisplay : SVG;
 	var editorDisplay : SVG;
@@ -239,6 +239,9 @@ class Graph extends hide.comp.Component {
 		}
 		}
 
 
 		var edges = editor.getEdges();
 		var edges = editor.getEdges();
+		for (edge in edges) {
+			createEdge(edge);
+		}
 	}
 	}
 
 
 	function openAddMenu(x : Int = 0, y : Int = 0) {
 	function openAddMenu(x : Int = 0, y : Int = 0) {
@@ -368,14 +371,12 @@ class Graph extends hide.comp.Component {
 			var key = Std.parseInt(this.selectedNode.attr("node"));
 			var key = Std.parseInt(this.selectedNode.attr("node"));
 			var posCursor = new Point(lX(ide.mouseX - 25), lY(ide.mouseY - 10));
 			var posCursor = new Point(lX(ide.mouseX - 25), lY(ide.mouseY - 10));
 
 
-			var instance : IGraphNode = null; // For the lambda capture
-			var instance = nodes[key].onAdd();
+			var instance = nodes[key].onConstructNode();
 
 
 			var createLinkInput = edgeCreationInput;
 			var createLinkInput = edgeCreationInput;
 			var createLinkOutput = edgeCreationOutput;
 			var createLinkOutput = edgeCreationOutput;
 			var fromInput = createLinkInput != null;
 			var fromInput = createLinkInput != null;
 
 
-			instance = nodes[key].onAdd();
 
 
 			if (createLinkInput != null) {
 			if (createLinkInput != null) {
 				createLinkOutput = packIO(instance.getId(), 0);
 				createLinkOutput = packIO(instance.getId(), 0);

+ 3 - 3
hide/view/GraphInterface.hx

@@ -54,7 +54,7 @@ typedef AddNodeMenuEntry = {
         You should generate a unique ID for the new IGraphNode. Don't add the node to your graph datastructure yet,
         You should generate a unique ID for the new IGraphNode. Don't add the node to your graph datastructure yet,
         the Graph editor will call addNode() with this node at the right time.
         the Graph editor will call addNode() with this node at the right time.
     **/
     **/
-    onAdd: () -> IGraphNode,
+    onConstructNode: () -> IGraphNode,
 };
 };
 
 
 
 
@@ -78,8 +78,8 @@ interface IGraphNode {
 }
 }
 
 
 interface IGraphEditor {
 interface IGraphEditor {
-    public function getNodes() : Array<IGraphNode>;
-    public function getEdges() : Array<Edge>;
+    public function getNodes() : Iterator<IGraphNode>;
+    public function getEdges() : Iterator<Edge>;
     public function getAddNodesMenu() : Array<AddNodeMenuEntry>;
     public function getAddNodesMenu() : Array<AddNodeMenuEntry>;
 
 
     public function addNode(node : IGraphNode) : Void;
     public function addNode(node : IGraphNode) : Void;

+ 5 - 5
hide/view/shadereditor/Box.hx

@@ -4,7 +4,7 @@ import hide.comp.SVG;
 import js.jquery.JQuery;
 import js.jquery.JQuery;
 import hide.view.GraphInterface;
 import hide.view.GraphInterface;
 
 
-@:access(hide.view.Graph)
+@:access(hide.view.GraphEditor)
 class Box {
 class Box {
 
 
 	static final boolColor = "#cc0505";
 	static final boolColor = "#cc0505";
@@ -44,7 +44,7 @@ class Box {
 	static final resizeBorder : Int = 8;
 	static final resizeBorder : Int = 8;
 	static final halfResizeBorder : Int = resizeBorder >> 1;
 	static final halfResizeBorder : Int = resizeBorder >> 1;
 
 
-	public function new(editor : Graph, parent : JQuery, node : IGraphNode) {
+	public function new(editor : GraphEditor, parent : JQuery, node : IGraphNode) {
 		this.node = node;
 		this.node = node;
 		info = node.getInfo();
 		info = node.getInfo();
 		width = info.width ?? 150;
 		width = info.width ?? 150;
@@ -273,7 +273,7 @@ class Box {
 		closePreviewBtn.find(".ico").toggleClass("ico-angle-up", viz);
 		closePreviewBtn.find(".ico").toggleClass("ico-angle-up", viz);
 	}
 	}
 
 
-	public function addInput(editor : Graph, name : String, valueDefault : String = null, color : Int) {
+	public function addInput(editor : GraphEditor, name : String, valueDefault : String = null, color : Int) {
 		var node = editor.editorDisplay.group(element).addClass("input-node-group");
 		var node = editor.editorDisplay.group(element).addClass("input-node-group");
 		var nodeHeight = HEADER_HEIGHT + NODE_MARGIN * (inputs.length+1) + NODE_RADIUS * inputs.length;
 		var nodeHeight = HEADER_HEIGHT + NODE_MARGIN * (inputs.length+1) + NODE_RADIUS * inputs.length;
 		var style = {fill : '#${StringTools.hex(color, 6)}'};
 		var style = {fill : '#${StringTools.hex(color, 6)}'};
@@ -327,7 +327,7 @@ class Box {
 		}
 		}
 	}
 	}
 
 
-	public function addOutput(editor : Graph, name : String, color : Int) {
+	public function addOutput(editor : GraphEditor, name : String, color : Int) {
 		var node = editor.editorDisplay.group(element).addClass("output-node-group");
 		var node = editor.editorDisplay.group(element).addClass("output-node-group");
 		var nodeHeight = getNodeHeight(outputs.length);
 		var nodeHeight = getNodeHeight(outputs.length);
 		var style = {fill : '#${StringTools.hex(color, 6)}'};
 		var style = {fill : '#${StringTools.hex(color, 6)}'};
@@ -348,7 +348,7 @@ class Box {
 		return HEADER_HEIGHT + NODE_MARGIN * (id+1) + NODE_RADIUS * (id);
 		return HEADER_HEIGHT + NODE_MARGIN * (id+1) + NODE_RADIUS * (id);
 	}
 	}
 
 
-	public function generateProperties(editor : Graph) {
+	public function generateProperties(editor : GraphEditor) {
 		var props = node.getPropertiesHTML(this.width);
 		var props = node.getPropertiesHTML(this.width);
 
 
 		if (props.length == 0) return;
 		if (props.length == 0) return;

+ 50 - 16
hide/view/shadereditor/ShaderEditor.hx

@@ -202,35 +202,69 @@ class TestNode implements IGraphNode {
 }
 }
 
 
 class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEditor {
 class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEditor {
-	var graph : hide.view.Graph;
+	var graphEditor : hide.view.GraphEditor;
+	var shaderGraph : hrt.shgraph.ShaderGraph;
+	var currentGraph : hrt.shgraph.ShaderGraph.Graph;
 	
 	
 	override function onDisplay() {
 	override function onDisplay() {
 		super.onDisplay();
 		super.onDisplay();
-		if (graph != null)
-			graph.remove();
-		graph = new hide.view.Graph(this, this.element);
-		graph.onDisplay();
+ 		shaderGraph = cast hide.Ide.inst.loadPrefab(state.path, null,  true);
+		currentGraph = shaderGraph.getGraph(Fragment);
+
+		if (graphEditor != null)
+			graphEditor.remove();
+		graphEditor = new hide.view.GraphEditor(this, this.element);
+		graphEditor.onDisplay();
 	}
 	}
 
 
 	/** IGraphEditor interface **/
 	/** IGraphEditor interface **/
-	public function getNodes() : Array<IGraphNode> {
-		return [];
+	public function getNodes() : Iterator<IGraphNode> {
+		return currentGraph.getNodes().iterator();
 	}
 	}
 
 
-	public function getEdges() : Array<Edge> {
-		return [];
+	public function getEdges() : Iterator<Edge> {
+		var edges : Array<Edge> = [];
+		for (id => node in currentGraph.getNodes()) {
+			for (inputId => connection in node.connections) {
+				if (connection != null) {
+					edges.push(
+						{
+							nodeFromId: connection.from.getId(),
+							outputFromId: connection.outputId,
+							nodeToId: id,
+							inputToId: inputId,
+						});
+				}
+			}
+		}
+		return edges.iterator();
 	}
 	}
 
 
 	public function getAddNodesMenu() : Array<AddNodeMenuEntry> {
 	public function getAddNodesMenu() : Array<AddNodeMenuEntry> {
+		var entries : Array<AddNodeMenuEntry> = [];
+
 		var id = 0;
 		var id = 0;
-		return [
-			{
-				name: "Test",
-				description: "Just a test",
-				group: "Test",
-				onAdd: () -> new TestNode(id++),
+		for (i => node in ShaderNode.registeredNodes) {
+			var metas = haxe.rtti.Meta.getType(node);
+			if (metas.group == null) {
+				continue;
 			}
 			}
-		];
+
+			entries.push(
+				{
+					name: metas.name != null ? metas.name[0] : "unknown",
+					group: metas.group[0],
+					description: metas.description != null ? metas.description[0] : "",
+					onConstructNode: () -> {
+						@:privateAccess var id = currentGraph.current_node_id++;
+						var inst = std.Type.createInstance(node, []);
+						inst.setId(id);
+						return inst;
+					},
+				}
+			);
+		}
+		return entries;
 	}
 	}
 
 
 	public function addNode(node: IGraphNode) : Void {
 	public function addNode(node: IGraphNode) : Void {

+ 4 - 4
hrt/shgraph/NodeGenContext.hx

@@ -267,9 +267,9 @@ class NodeGenContext {
 	/**
 	/**
 		API used by ShaderGraphGenContext
 		API used by ShaderGraphGenContext
 	**/
 	**/
-	function initForNode(node: ShaderGraph.Node, nodeInputExprs: Array<TExpr>) {
-		nodeInputInfo = node.instance.getInputs();
-		nodeOutputInfo = node.instance.getOutputs();
+	function initForNode(node: ShaderNode, nodeInputExprs: Array<TExpr>) {
+		nodeInputInfo = node.getInputs();
+		nodeOutputInfo = node.getOutputs();
 		this.node = node;
 		this.node = node;
 		this.nodeInputExprs = nodeInputExprs;
 		this.nodeInputExprs = nodeInputExprs;
 
 
@@ -297,7 +297,7 @@ class NodeGenContext {
 		}
 		}
 	}
 	}
 
 
-	var node : ShaderGraph.Node = null;
+	var node : ShaderNode = null;
 
 
 	var currentPreviewId: Int = -1;
 	var currentPreviewId: Int = -1;
 	var expressions: Array<TExpr> = [];
 	var expressions: Array<TExpr> = [];

+ 24 - 56
hrt/shgraph/ShaderGraph.hx

@@ -135,15 +135,6 @@ typedef ShaderNodeDef = {
 	?functions: Array<TFunction>,
 	?functions: Array<TFunction>,
 };
 };
 
 
-typedef Node = {
-	x : Float,
-	y : Float,
-	id : Int,
-	type : String,
-	?properties : Dynamic,
-	?instance : ShaderNode,
-};
-
 typedef Edge = {
 typedef Edge = {
 	?outputNodeId : Int,
 	?outputNodeId : Int,
 	nameOutput : String, // Fallback if name has changed
 	nameOutput : String, // Fallback if name has changed
@@ -154,7 +145,7 @@ typedef Edge = {
 };
 };
 
 
 typedef Connection = {
 typedef Connection = {
-	from : Node,
+	from : ShaderNode,
 	outputId : Int,
 	outputId : Int,
 };
 };
 
 
@@ -173,14 +164,6 @@ enum Domain {
 	Fragment;
 	Fragment;
 }
 }
 
 
-
-typedef GenNodeInfo = {
-	outputToInputMap: Map<String, Array<{node: Node, inputName: String}>>,
-	inputTypes: Array<Type>,
-	?outputs: Map<String, TVar>,
-	?def: ShaderGraph.ShaderNodeDef,
-}
-
 @:structInit @:publicFields
 @:structInit @:publicFields
 class
 class
 ExternVarDef {
 ExternVarDef {
@@ -203,7 +186,7 @@ class ShaderGraphGenContext {
 	var nodes : Array<{
 	var nodes : Array<{
 		var outputs: Array<Array<{to: Int, input: Int}>>;
 		var outputs: Array<Array<{to: Int, input: Int}>>;
 		var inputs : Array<TExpr>;
 		var inputs : Array<TExpr>;
-		var node : Node;
+		var node : ShaderNode;
 	}>;
 	}>;
 
 
 	var inputNodes : Array<Int> = [];
 	var inputNodes : Array<Int> = [];
@@ -227,7 +210,7 @@ class ShaderGraphGenContext {
 			var node = nodes[nodeId];
 			var node = nodes[nodeId];
 			genContext.initForNode(node.node, node.inputs);
 			genContext.initForNode(node.node, node.inputs);
 
 
-			node.node.instance.generate(genContext);
+			node.node.generate(genContext);
 
 
 			for (outputId => expr in genContext.outputs) {
 			for (outputId => expr in genContext.outputs) {
 				if (expr == null) throw "null expr for output " + outputId;
 				if (expr == null) throw "null expr for output " + outputId;
@@ -280,7 +263,7 @@ class ShaderGraphGenContext {
 
 
 		for (id => node in nodes) {
 		for (id => node in nodes) {
 			if (node == null) continue;
 			if (node == null) continue;
-			var inst = node.node.instance;
+			var inst = node.node;
 			var empty = true;
 			var empty = true;
 			var inputs = inst.getInputs();
 			var inputs = inst.getInputs();
 
 
@@ -290,7 +273,7 @@ class ShaderGraphGenContext {
 				if (connection == null)
 				if (connection == null)
 					continue;
 					continue;
 				empty = false;
 				empty = false;
-				var nodeOutputs = connection.from.instance.getOutputs();
+				var nodeOutputs = connection.from.getOutputs();
 				var outputs = nodes[connection.from.id].outputs;
 				var outputs = nodes[connection.from.id].outputs;
 				if (outputs == null) {
 				if (outputs == null) {
 					outputs = [];
 					outputs = [];
@@ -647,7 +630,7 @@ class Graph {
 	var cachedGen : ShaderNodeDef = null;
 	var cachedGen : ShaderNodeDef = null;
 	var allParamDefaultValue = [];
 	var allParamDefaultValue = [];
 	var current_node_id = 0;
 	var current_node_id = 0;
-	var nodes : Map<Int, Node> = [];
+	var nodes : Map<Int, ShaderNode> = [];
 
 
 	public var parent : ShaderGraph = null;
 	public var parent : ShaderGraph = null;
 
 
@@ -664,23 +647,18 @@ class Graph {
 		generate(Reflect.getProperty(json, "nodes"), Reflect.getProperty(json, "edges"));
 		generate(Reflect.getProperty(json, "nodes"), Reflect.getProperty(json, "edges"));
 	}
 	}
 
 
-	public function generate(nodes : Array<Node>, edges : Array<Edge>) {
+	public function generate(nodes : Array<Dynamic>, edges : Array<Edge>) {
+		current_node_id = 0;
 		for (n in nodes) {
 		for (n in nodes) {
-			var cl = std.Type.resolveClass(n.type);
-			if( cl == null ) throw "Missing shader node "+n.type;
-			n.instance = std.Type.createInstance(cl, []);
-			n.instance.setId(n.id);
-			n.instance.loadProperties(n.properties);
-			this.nodes.set(n.id, n);
-
-			var shaderParam = Std.downcast(n.instance, ShaderParam);
+			var node = ShaderNode.createFromDynamic(n);
+			this.nodes.set(node.id, node);
+			var shaderParam = Std.downcast(node, ShaderParam);
 			if (shaderParam != null) {
 			if (shaderParam != null) {
 				var paramShader = getParameter(shaderParam.parameterId);
 				var paramShader = getParameter(shaderParam.parameterId);
 				shaderParam.variable = paramShader.variable;
 				shaderParam.variable = paramShader.variable;
 			}
 			}
+			current_node_id = hxd.Math.imax(current_node_id, node.id+1);
 		}
 		}
-		if (nodes[nodes.length-1] != null)
-			this.current_node_id = nodes[nodes.length-1].id+1;
 
 
 		// Migration patch
 		// Migration patch
 		for (e in edges) {
 		for (e in edges) {
@@ -699,9 +677,8 @@ class Graph {
 		var node = this.nodes.get(edge.inputNodeId);
 		var node = this.nodes.get(edge.inputNodeId);
 		var output = this.nodes.get(edge.outputNodeId);
 		var output = this.nodes.get(edge.outputNodeId);
 
 
-		var inputs = node.instance.getInputs();
-		var outputs = output.instance.getOutputs();
-
+		var inputs = node.getInputs();
+		var outputs = output.getOutputs();
 
 
 		var outputId = edge.outputId;
 		var outputId = edge.outputId;
 		var inputId = edge.inputId;
 		var inputId = edge.inputId;
@@ -732,7 +709,7 @@ class Graph {
 			}
 			}
 		}
 		}
 
 
-		node.instance.connections[inputId] = {from: output, outputId: outputId};
+		node.connections[inputId] = {from: output, outputId: outputId};
 
 
 		#if editor
 		#if editor
 		if (hasCycle()){
 		if (hasCycle()){
@@ -755,6 +732,10 @@ class Graph {
 		return true;
 		return true;
 	}
 	}
 
 
+	public function addNode(shNode : ShaderNode) {
+		this.nodes.set(shNode.id, shNode);
+	}
+
 	public function areTypesCompatible(input: SgType, output: SgType) : Bool {
 	public function areTypesCompatible(input: SgType, output: SgType) : Bool {
 		return switch (input) {
 		return switch (input) {
 			case SgFloat(_):
 			case SgFloat(_):
@@ -773,9 +754,9 @@ class Graph {
 
 
 	public function removeEdge(idNode, inputId, update = true) {
 	public function removeEdge(idNode, inputId, update = true) {
 		var node = this.nodes.get(idNode);
 		var node = this.nodes.get(idNode);
-		if (node.instance.connections[inputId] == null) return;
+		if (node.connections[inputId] == null) return;
 
 
-		node.instance.connections[inputId] = null;
+		node.connections[inputId] = null;
 	}
 	}
 
 
 	public function setPosition(idNode : Int, x : Float, y : Float) {
 	public function setPosition(idNode : Int, x : Float, y : Float) {
@@ -796,19 +777,6 @@ class Graph {
 		return parent.getParameter(id);
 		return parent.getParameter(id);
 	}
 	}
 
 
-
-	public function addNode(x : Float, y : Float, nameClass : Class<ShaderNode>, args: Array<Dynamic>) {
-		var node : Node = { x : x, y : y, id : current_node_id, type: std.Type.getClassName(nameClass) };
-
-		node.instance = std.Type.createInstance(nameClass, args);
-		node.instance.setId(current_node_id);
-
-		this.nodes.set(node.id, node);
-		current_node_id++;
-
-		return node.instance;
-	}
-
 	public function hasCycle() : Bool {
 	public function hasCycle() : Bool {
 		var ctx = new ShaderGraphGenContext(this, false);
 		var ctx = new ShaderGraphGenContext(this, false);
 		@:privateAccess ctx.initNodes();
 		@:privateAccess ctx.initNodes();
@@ -823,15 +791,15 @@ class Graph {
 	public function saveToDynamic() : Dynamic {
 	public function saveToDynamic() : Dynamic {
 		var edgesJson : Array<Edge> = [];
 		var edgesJson : Array<Edge> = [];
 		for (n in nodes) {
 		for (n in nodes) {
-			for (inputId => connection in n.instance.connections) {
+			for (inputId => connection in n.connections) {
 				if (connection == null) continue;
 				if (connection == null) continue;
 				var outputId = connection.outputId;
 				var outputId = connection.outputId;
-				edgesJson.push({ outputNodeId: connection.from.id, nameOutput: connection.from.instance.getOutputs()[outputId].name, inputNodeId: n.id, nameInput: n.instance.getInputs()[inputId].name, inputId: inputId, outputId: outputId });
+				edgesJson.push({ outputNodeId: connection.from.id, nameOutput: connection.from.getOutputs()[outputId].name, inputNodeId: n.id, nameInput: n.getInputs()[inputId].name, inputId: inputId, outputId: outputId });
 			}
 			}
 		}
 		}
 		var json = {
 		var json = {
 			nodes: [
 			nodes: [
-				for (n in nodes) { x : Std.int(n.x), y : Std.int(n.y), id: n.id, type: n.type, properties : n.instance.saveProperties() }
+				for (n in nodes) n.serializeToDynamic(),
 			],
 			],
 			edges: edgesJson
 			edges: edgesJson
 		};
 		};

+ 75 - 5
hrt/shgraph/ShaderNode.hx

@@ -11,6 +11,10 @@ import hrt.shgraph.AstTools.*;
 import hrt.shgraph.ShaderGraph;
 import hrt.shgraph.ShaderGraph;
 import hrt.shgraph.SgHxslVar.ShaderDefInput;
 import hrt.shgraph.SgHxslVar.ShaderDefInput;
 
 
+#if editor
+import hide.view.GraphInterface; 
+#end
+
 
 
 class AlphaPreview extends hxsl.Shader {
 class AlphaPreview extends hxsl.Shader {
 	static var SRC = {
 	static var SRC = {
@@ -39,13 +43,83 @@ typedef AliasInfo = {?nameSearch: String, ?nameOverride : String, ?description :
 @:autoBuild(hrt.shgraph.Macros.autoRegisterNode())
 @:autoBuild(hrt.shgraph.Macros.autoRegisterNode())
 @:keepSub
 @:keepSub
 @:keep
 @:keep
-class ShaderNode {
+class ShaderNode 
+#if editor
+implements hide.view.GraphInterface.IGraphNode 
+#end
+{
 
 
 	public var id : Int;
 	public var id : Int;
+	public var x : Float;
+	public var y : Float;
 	public var showPreview : Bool = true;
 	public var showPreview : Bool = true;
 	@prop public var nameOverride : String;
 	@prop public var nameOverride : String;
 
 
 
 
+	#if editor
+	// IGraphNode Interface
+	public function getInfo() : GraphNodeInfo {
+		var metas = haxe.rtti.Meta.getType(HaxeType.getClass(this));
+		return {
+			name: nameOverride ?? (metas.name != null ? metas.name[0] : "undefined"),
+			inputs: [
+				for (i in getInputs()) {
+					{
+						name: i.name,
+						color: 0xFF0000,
+					}
+				}
+			],
+			outputs: [
+				for (o in getOutputs()) {
+					{
+						name: o.name,
+						color: 0xFF0000,
+					}
+				}
+			]
+		};
+	}
+
+	public function getId() : Int {
+		return id;
+	}
+
+	public function getPos(p : h2d.col.Point) : Void {
+		p.set(x,y);
+	}
+
+	public function setPos(p : h2d.col.Point) : Void {
+		x = p.x;
+		y = p.y;
+	}
+
+	public function getPropertiesHTML(width : Float) : Array<hide.Element> {
+		return [];
+	}
+	#end
+
+	public function serializeToDynamic() : Dynamic {
+		return {
+			x: x,
+			y: y,
+			id: id,
+			type: std.Type.getClassName(std.Type.getClass(this)),
+			properties: saveProperties(),
+		};
+	}
+
+	public static function createFromDynamic(data: Dynamic) : ShaderNode {
+		var type = std.Type.resolveClass(data.type);
+		var inst = std.Type.createInstance(type, []);
+		inst.x = data.x;
+		inst.y = data.y;
+		inst.id = data.id;
+		inst.connections = [];
+		inst.loadProperties(data.properties);
+		return inst;
+	}
+
 	public var defaults : Dynamic = {};
 	public var defaults : Dynamic = {};
 
 
 	/**
 	/**
@@ -159,10 +233,6 @@ class ShaderNode {
 		return props;
 		return props;
 	}
 	}
 
 
-	function getPropertiesHTML(width : Float) : Array<hide.Element> {
-		return [];
-	}
-
 	static public var registeredNodes = new Map<String, Class<ShaderNode>>();
 	static public var registeredNodes = new Map<String, Class<ShaderNode>>();
 
 
 	static public function register(key : String, cl : Class<ShaderNode>) : Bool {
 	static public function register(key : String, cl : Class<ShaderNode>) : Bool {