Ver Fonte

ShaderGraph : Handle param (float, color, texture)

Tom SPIRA há 6 anos atrás
pai
commit
e583b01f03

+ 10 - 1
bin/style.css

@@ -1077,6 +1077,9 @@ input[type=checkbox]:checked:after {
   padding: 5px;
   box-shadow: inset 0px 13px 6px -15px black;
 }
+.graph-view .tabs .tab .hide-block #parametersList .parameter .content div:first-child {
+  display: inline;
+}
 .graph-view .tabs .tab .hide-block #parametersList .parameter .content div {
   width: 100%;
   height: 20px;
@@ -1088,6 +1091,12 @@ input[type=checkbox]:checked:after {
   padding-right: 5px;
   font-weight: normal;
 }
+.graph-view .tabs .tab .hide-block #parametersList .parameter .content .texture-preview {
+  background-repeat: no-repeat;
+  background-size: 20px 20px!important;
+  border: 2px #444444 solid;
+  width: 20px;
+}
 .graph-view .tabs .tab .hide-block #parametersList .parameter .content .action-btns input {
   float: right;
 }
@@ -1265,7 +1274,7 @@ input[type=checkbox]:checked:after {
   fill: none;
 }
 .graph-view .heaps-scene svg .head-box {
-  fill: #3e3e3e;
+  fill: #155358;
 }
 .graph-view .heaps-scene svg .title-box {
   fill: #ffffff;

+ 11 - 1
bin/style.less

@@ -1195,6 +1195,10 @@ input[type=checkbox] {
 							padding: 5px;
 							box-shadow: inset 0px 13px 6px -15px black;
 
+							div:first-child {
+								display: inline;
+							}
+
 							div {
 								width: 100%;
 								height: 20px;
@@ -1207,6 +1211,12 @@ input[type=checkbox] {
 									font-weight: normal;
 								}
 							}
+							.texture-preview {
+								background-repeat: no-repeat;
+								background-size: 20px 20px!important;
+								border: 2px #444444 solid;
+								width: 20px;
+							}
 							.action-btns {
 								input {
 									float: right;
@@ -1431,7 +1441,7 @@ input[type=checkbox] {
 			}
 
 			.head-box {
-				fill: #3e3e3e;
+				fill: #155358;
 			}
 
 			.title-box {

+ 0 - 12
hide/view/Graph.hx

@@ -68,18 +68,6 @@ class Graph extends FileView {
 					<div class="heaps-scene" tabindex="0" >
 					</div>
 					<div id="rightPanel" class="tabs">
-						<span>Parameters</span>
-						<div class="tab expand" name="Scene" icon="sitemap">
-							<div class="hide-block" >
-								<div id="parametersList" class="hide-scene-tree hide-list">
-								</div>
-							</div>
-							<div class="options-block hide-block">
-								<input id="addParameter" type="button" value="Add parameter" />
-								<input id="launchCompileShader" type="button" value="Compile shader" />
-								<input id="saveShader" type="button" value="Save" />
-							</div>
-						</div>
 					</div>
 				</div>
 			</div>');

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

@@ -15,7 +15,7 @@ class Box {
 	var height : Int;
 	var propsHeight : Int = 0;
 
-	var HEADER_HEIGHT = 27;
+	var HEADER_HEIGHT = 22;
 	@const var NODE_MARGIN = 17;
 	public static var NODE_RADIUS = 5;
 	@const var NODE_TITLE_PADDING = 10;
@@ -24,6 +24,9 @@ class Box {
 	public var inputs : Array<JQuery> = [];
 	public var outputs : Array<JQuery> = [];
 
+	var hasHeader : Bool = true;
+	var color : String;
+
 	var element : JQuery;
 	var propertiesGroup : JQuery;
 
@@ -34,6 +37,9 @@ class Box {
 		if (metas.width != null) {
 			this.width = metas.width[0];
 		}
+		if (Reflect.hasField(metas, "color")) {
+			color = Reflect.field(metas, "color");
+		}
 		var className = (metas.name != null) ? metas.name[0] : "Undefined";
 
 		element = editor.group(parent).addClass("box").addClass("not-selected");
@@ -47,15 +53,20 @@ class Box {
 
 		if (Reflect.hasField(metas, "noheader")) {
 			HEADER_HEIGHT = 0;
+			hasHeader = false;
 		} else {
-			editor.rect(element, 0, 0, this.width, HEADER_HEIGHT).addClass("head-box");
-			editor.text(element, 10, HEADER_HEIGHT-8, className).addClass("title-box");
+			var header = editor.rect(element, 0, 0, this.width, HEADER_HEIGHT).addClass("head-box");
+			if (color != null) header.css("fill", color);
+			editor.text(element, 7, HEADER_HEIGHT-6, className).addClass("title-box");
 		}
 
 		propertiesGroup = editor.group(element).addClass("properties-group");
 
 		// nodes div
-		editor.rect(element, 0, HEADER_HEIGHT, this.width, 0).addClass("nodes");
+		var bg = editor.rect(element, 0, HEADER_HEIGHT, this.width, 0).addClass("nodes");
+		if (!hasHeader && color != null) {
+			bg.css("fill", color);
+		}
 		editor.line(element, width/2, HEADER_HEIGHT, width/2, 0, {display: "none"}).addClass("nodes-separator");
 	}
 
@@ -104,7 +115,8 @@ class Box {
 		}
 
 		// create properties box
-		editor.rect(propertiesGroup, 0, 0, this.width, 0).addClass("properties");
+		var bgParam = editor.rect(propertiesGroup, 0, 0, this.width, 0).addClass("properties");
+		if (!hasHeader && color != null) bgParam.css("fill", color);
 		propsHeight = 5;
 
 		for (p in props) {

+ 121 - 32
hide/view/shadereditor/ShaderEditor.hx

@@ -1,5 +1,6 @@
 package hide.view.shadereditor;
 
+import hrt.shgraph.ShaderParam;
 import hrt.shgraph.ShaderException;
 import haxe.Timer;
 using hxsl.Ast.Type;
@@ -18,6 +19,8 @@ import hrt.shgraph.ShaderNode;
 class ShaderEditor extends hide.view.Graph {
 
 	var parametersList : JQuery;
+	var draggedParamId : Int;
+
 
 	// used to preview
 	var sceneEditor : SceneEditor;
@@ -39,7 +42,7 @@ class ShaderEditor extends hide.view.Graph {
 		shaderGraph = new ShaderGraph(getPath());
 		addMenu = null;
 
-		element.find("#rightPanel").append(new Element('
+		element.find("#rightPanel").html('
 						<span>Parameters</span>
 						<div class="tab expand" name="Scene" icon="sitemap">
 							<div class="hide-block" >
@@ -47,12 +50,21 @@ class ShaderEditor extends hide.view.Graph {
 								</div>
 							</div>
 							<div class="options-block hide-block">
-								<input id="addParameter" type="button" value="Add parameter" />
+								<input id="createParameter" type="button" value="Add parameter" />
 								<input id="launchCompileShader" type="button" value="Compile shader" />
 								<input id="saveShader" type="button" value="Save" />
 							</div>
-						</div>)'));
-
+						</div>)');
+		parent.on("drop", function(e) {
+			var posCursor = new Point(lX(ide.mouseX - 25), lY(ide.mouseY - 10));
+			var node = Std.instance(shaderGraph.addNode(posCursor.x, posCursor.y, ShaderParam), ShaderParam);
+			node.parameterId = draggedParamId;
+			var paramShader = shaderGraph.getParameter(draggedParamId);
+			node.variable = paramShader.variable;
+			node.setName(paramShader.name);
+			node.computeOutputs();
+			addBox(posCursor, ShaderParam, node);
+		});
 
 		var preview = new Element('<div id="preview" ></div>');
 		preview.on("mousedown", function(e) { e.stopPropagation(); });
@@ -125,20 +137,20 @@ class ShaderEditor extends hide.view.Graph {
 			}
 		});
 
-		element.find("#addParameter").on("click", function() {
+		element.find("#createParameter").on("click", function() {
 			function createElement(name : String, type : Type) : Element {
 				var elt = new Element('
 					<div>
 						<span> ${name} </span>
 					</div>');
 				elt.on("click", function() {
-					addParameter(type);
+					createParameter(type);
 				});
 				return elt;
 			}
 
 			customContextMenu([
-				createElement("Boolean", TBool),
+				createElement("Number", TFloat),
 				createElement("Color", TVec(4, VFloat)),
 				createElement("Texture", TSampler2D)
 				]);
@@ -197,7 +209,17 @@ class ShaderEditor extends hide.view.Graph {
 		new Element("svg").ready(function(e) {
 
 			for (node in shaderGraph.getNodes()) {
-				addBox(new Point(node.x, node.y), std.Type.getClass(node.instance), node.instance);
+				var paramNode = Std.instance(node.instance, ShaderParam);
+				if (paramNode != null) {
+					var paramShader = shaderGraph.getParameter(paramNode.parameterId);
+					paramNode.variable = paramShader.variable;
+					paramNode.setName(paramShader.name);
+					paramNode.computeOutputs();
+					shaderGraph.nodeUpdated(paramNode.id);
+					addBox(new Point(node.x, node.y), ShaderParam, paramNode);
+				} else {
+					addBox(new Point(node.x, node.y), std.Type.getClass(node.instance), node.instance);
+				}
 			}
 
 			new Element(".nodes").ready(function(e) {
@@ -221,6 +243,11 @@ class ShaderEditor extends hide.view.Graph {
 				}
 
 			});
+
+
+			for (p in shaderGraph.parametersAvailable) {
+				addParameter(p.id, p.name, p.type, p.defaultValue);
+			}
 		});
 
 	}
@@ -249,37 +276,70 @@ class ShaderEditor extends hide.view.Graph {
 		launchCompileShader();
 	}
 
-	function addParameter(type : Type, ?title : String, ?value : Dynamic) {
-
-		//TODO: link with shadergraph
-		//TODO: drag to graph
-		//TODO: edit => edit everywhere
-		//TODO: type sampler => file choosen
-
-		var exist = (title != null);
-
-		var elt = new Element('<div class="parameter"></div>').appendTo(parametersList);
+	function addParameter(id : Int, name : String, type : Type, ?value : Dynamic) {
+		var elt = new Element('<div class="parameter" draggable="true" ></div>').appendTo(parametersList);
 		var content = new Element('<div class="content" ></div>');
+		content.hide();
 		var defaultValue = new Element("<div><span>Default: </span></div>").appendTo(content);
-		if (!exist) content.hide();
 
 		var typeName = "";
-
 		switch(type) {
-			case TBool:
-				var checkbox = new Element('<input type="checkbox" />');
-				checkbox.prop("checked", ${(value != null && value == "true") ? true : false});
-				defaultValue.append(checkbox);
-				typeName = "Boolean";
+			case TFloat:
+				var inputText = new Element('<input type="text" style="width: 50px" />').appendTo(defaultValue);
+				if (value != null && value.length > 0) inputText.val(value);
+				inputText.on("change", function() {
+					var tmpValue = Std.parseFloat(inputText.val());
+					if (Math.isNaN(tmpValue) ) {
+						inputText.val("0");
+					} else {
+						inputText.val(tmpValue);
+					}
+					shaderGraph.setParameterDefaultValue(id, inputText.val());
+					launchCompileShader();
+				});
+				typeName = "Number";
+			case TVec(4, VFloat):
+				var parentPicker = new Element('<div style="width: 35px; height: 25px; display: inline-block;"></div>').appendTo(defaultValue);
+				var picker = new hide.comp.ColorPicker(true, parentPicker);
+
+				var start : h3d.Vector;
+				if (value != null)
+					start = h3d.Vector.fromArray([value.x, value.y, value.z, value.w]);
+				else
+					start = h3d.Vector.fromArray([0, 0, 0, 1]);
+				picker.value = start.toColor();
+
+				picker.onChange = function(move) {
+					shaderGraph.setParameterDefaultValue(id, h3d.Vector.fromColor(picker.value));
+					launchCompileShader();
+				};
+				typeName = "Color";
+			case TSampler2D:
+				var parentSampler = new Element('<input type="texturepath" field="sampler2d" />').appendTo(defaultValue);
+
+				var tselect = new hide.comp.TextureSelect(null, parentSampler);
+				if (value != null && value.length > 0) tselect.path = value;
+				tselect.onChange = function() {
+					shaderGraph.setParameterDefaultValue(id, tselect.path);
+					launchCompileShader();
+				}
+				typeName = "Texture";
 			default:
-				defaultValue.append(new Element('<input type="text" value="${(value != null) ? value : ""}" />'));
+				var inputText = new Element('<input type="text" />').appendTo(defaultValue);
+				if (value != null && value.length > 0) inputText.val(value);
+				inputText.on("change", function() {
+					if (inputText.val().length > 0) {
+						shaderGraph.setParameterDefaultValue(id, inputText.val());
+						launchCompileShader();
+					}
+				});
 				typeName = "String";
 		}
 
 		var header = new Element('<div class="header">
 									<div class="title">
 										<i class="fa fa-chevron-right" ></i>
-										<input class="input-title" type="input" value="${(title != null) ? title : ""}" />
+										<input class="input-title" type="input" value="${name}" />
 									</div>
 									<div class="type">
 										<span>${typeName}</span>
@@ -291,16 +351,25 @@ class ShaderEditor extends hide.view.Graph {
 		var actionBtns = new Element('<div class="action-btns" ></div>').appendTo(content);
 		var deleteBtn = new Element('<input type="button" value="Delete" />');
 		deleteBtn.on("click", function() {
+			shaderGraph.removeParameter(id);
 			elt.remove();
 		});
 		deleteBtn.appendTo(actionBtns);
 
-
 		var inputTitle = elt.find(".input-title");
 		inputTitle.on("click", function(e) {
 			e.stopPropagation();
 		});
 		inputTitle.on("change", function(e) {
+			var newName = inputTitle.val();
+			if (shaderGraph.setParameterTitle(id, newName)) {
+				for (b in listOfBoxes) {
+					var shaderParam = Std.instance(b.getInstance(), ShaderParam);
+					if (shaderParam != null && shaderParam.parameterId == id) {
+						shaderParam.setName(newName);
+					}
+				}
+			}
 		});
 		elt.find(".header").on("click", function(ev) {
 			elt.find(".content").toggle();
@@ -313,6 +382,27 @@ class ShaderEditor extends hide.view.Graph {
 				icon.removeClass("fa-chevron-down");
 			}
 		});
+
+		elt.on("dragstart", function(e) {
+			draggedParamId = id;
+		});
+
+		return elt;
+	}
+
+	function createParameter(type : Type) {
+
+		//TODO: link with shadergraph
+		//TODO: drag to graph
+		//TODO: edit => edit everywhere
+		//TODO: type sampler => file choosen
+
+		var paramShaderID = shaderGraph.addParameter(type);
+		var paramShader = shaderGraph.getParameter(paramShaderID);
+
+		var elt = addParameter(paramShaderID, paramShader.name, type, null);
+
+		elt.find(".input-title").focus();
 	}
 
 	function launchCompileShader() {
@@ -332,15 +422,12 @@ class ShaderEditor extends hide.view.Graph {
 			saveShader = shaderGenerated.clone();
 		try {
 			var timeStart = Date.now().getTime();
-			var s = new SharedShader("");
-			s.data = shaderGraph.buildFragment();
-			@:privateAccess s.initialize();
 
 			if (shaderGenerated != null)
 				for (m in obj.getMaterials())
 					m.mainPass.removeShader(shaderGenerated);
 
-			shaderGenerated = new hxsl.DynamicShader(s);
+			shaderGenerated = shaderGraph.compile();
 			for (m in obj.getMaterials()) {
 				m.mainPass.addShader(shaderGenerated);
 			}
@@ -384,6 +471,8 @@ class ShaderEditor extends hide.view.Graph {
 		var node = shaderGraph.addNode(p.x, p.y, nodeClass);
 
 		addBox(p, nodeClass, node);
+
+		return node;
 	}
 
 	function createEdgeInShaderGraph() : Bool {

+ 1 - 1
hrt/shgraph/ShaderFunction.hx

@@ -18,7 +18,7 @@ class ShaderFunction extends ShaderNode {
 		var args = [];
 		var varArgs = [];
 
-		for (k in getInputsKey()) {
+		for (k in getInputInfoKeys()) {
 			args.push({ name: k, type: getInput(k).getType() });
 			varArgs.push(getInput(k).getVar());
 		}

+ 81 - 21
hrt/shgraph/ShaderGraph.hx

@@ -1,5 +1,7 @@
 package hrt.shgraph;
 
+import hxsl.SharedShader;
+import hxsl.DynamicShader;
 using hxsl.Ast;
 
 typedef Node = {
@@ -25,16 +27,18 @@ private typedef Parameter = {
 	name : String,
 	type : Type,
 	defaultValue : Dynamic,
+	?id : Int,
 	?variable : TVar
 };
 
 class ShaderGraph {
 
 	var current_node_id = 0;
+	var current_param_id = 0;
 	var filepath : String;
 	var nodes : Map<Int, Node> = [];
 	var allVariables : Array<TVar> = [];
-	public var parametersAvailable : Array<Parameter> = [];
+	public var parametersAvailable : Map<Int, Parameter> = [];
 
 	public function new(filepath : String) {
 		if (filepath == null) return;
@@ -47,11 +51,24 @@ class ShaderGraph {
 			throw "Invalid shader graph parsing ("+e+")";
 		}
 
-		generate(Reflect.getProperty(json, "nodes"), Reflect.getProperty(json, "edges"));
+		generate(Reflect.getProperty(json, "nodes"), Reflect.getProperty(json, "edges"), Reflect.getProperty(json, "parameters"));
 
 	}
 
-	public function generate(nodes : Array<Node>, edges : Array<Edge>) {
+	public function generate(nodes : Array<Node>, edges : Array<Edge>, parameters : Array<Parameter>) {
+
+		for (p in parameters) {
+			var typeString : Array<Dynamic> = Reflect.field(p, "type");
+			if (typeString[1] == null || typeString[1].length == 0)
+				p.type = std.Type.createEnum(Type, typeString[0]);
+			else {
+				var paramsEnum = typeString[1].split(",");
+				p.type = std.Type.createEnum(Type, typeString[0], [Std.parseInt(paramsEnum[0]), std.Type.createEnum(VecType, paramsEnum[1])]);
+			}
+			p.variable = generateParameter(p.name, p.type);
+			this.parametersAvailable.set(p.id, p);
+			current_param_id = p.id + 1;
+		}
 
 		for (n in nodes) {
 			n.outputs = [];
@@ -91,6 +108,7 @@ class ShaderGraph {
 		var output = this.nodes.get(edge.idOutput);
 		node.instance.setInput(edge.nameInput, new NodeVar(output.instance, edge.nameOutput));
 		output.outputs.push(node);
+		#if editor
 		if (hasCycle()){
 			removeEdge(edge.idInput, edge.nameInput, false);
 			return false;
@@ -101,6 +119,7 @@ class ShaderGraph {
 			removeEdge(edge.idInput, edge.nameInput);
 			throw e;
 		}
+		#end
 		return true;
 	}
 
@@ -178,31 +197,46 @@ class ShaderGraph {
 			};
 	}
 
-	public function addParameter(name : String, type : Type, defaultValue : Dynamic) {
-		parametersAvailable.push({name : name, type : type, defaultValue : defaultValue, variable : generateParameter(name, type)});
-		return parametersAvailable.length-1;
+	public function addParameter(type : Type) {
+		var name = "Param_" + current_param_id;
+		parametersAvailable.set(current_param_id, {id: current_param_id, name : name, type : type, defaultValue : null, variable : generateParameter(name, type)});
+		current_param_id++;
+		return current_param_id-1;
+	}
+
+	public function getParameter(id : Int) {
+		return parametersAvailable.get(id);
 	}
 
-	public function setParameter(id : Int, ?newName : String, ?newDefaultValue : Dynamic) {
-		if (parametersAvailable[id] != null) {
+	public function setParameterTitle(id : Int, newName : String) {
+		var p = parametersAvailable.get(id);
+		if (p != null) {
 			if (newName != null) {
-				parametersAvailable[id].name = newName;
-				parametersAvailable[id].variable = generateParameter(newName, parametersAvailable[id].type);
+				for (p in parametersAvailable) {
+					if (p.name == newName) {
+						return false;
+					}
+				}
+				p.name = newName;
+				p.variable = generateParameter(newName, p.type);
+				return true;
 			}
-			if (newDefaultValue != null)
-				parametersAvailable[id].defaultValue = newDefaultValue;
 		}
+		return false;
 	}
 
-	public function removeParameter(name : String) {
-		for (p in parametersAvailable) {
-			if (p.name == name) {
-				parametersAvailable.remove(p);
-				return;
-			}
+	public function setParameterDefaultValue(id : Int, newDefaultValue : Dynamic) {
+		var p = parametersAvailable.get(id);
+		if (p != null) {
+			if (newDefaultValue != null)
+				p.defaultValue = newDefaultValue;
 		}
 	}
 
+	public function removeParameter(id : Int) {
+		parametersAvailable.remove(id);
+	}
+
 	function buildNodeVar(nodeVar : NodeVar) : Array<TExpr>{
 		var node = nodeVar.node;
 		if (node == null)
@@ -232,13 +266,18 @@ class ShaderGraph {
 		return false;
 	}
 
-	public function buildFragment() : ShaderData {
+	public function compile() : DynamicShader {
 
 		allVariables = [];
+		var allParameters = [];
+		var allParamDefaultValue = [];
 		var content = [];
 
 		for (n in nodes) {
 			n.instance.outputCompiled = [];
+			if (Std.is(n.instance, ShaderInput) || Std.is(n.instance, ShaderParam)) {
+				//updateOutputs(n);
+			}
 		}
 
 		for (n in nodes) {
@@ -256,9 +295,15 @@ class ShaderGraph {
 				var nodeVar = new NodeVar(n.instance, "input");
 				content = content.concat(buildNodeVar(nodeVar));
 			}
+			if (Std.is(n.instance, ShaderParam)) {
+				var shaderParam = Std.instance(n.instance, ShaderParam);
+				allVariables.push(shaderParam.variable);
+				allParameters.push(shaderParam.variable);
+				allParamDefaultValue.push(getParameter(shaderParam.parameterId).defaultValue);
+			}
 		}
 
-		return {
+		var shaderData = {
 			funs : [{
 					ret : TVoid, kind : Fragment,
 					ref : {
@@ -277,6 +322,21 @@ class ShaderGraph {
 			name: "MON_FRAGMENT",
 			vars: allVariables
 		};
+
+		var s = new SharedShader("");
+		s.data = shaderData;
+		@:privateAccess s.initialize();
+		var shaderCompiled = new hxsl.DynamicShader(s);
+
+		for (i in 0...allParameters.length) {
+			switch (allParameters[i].type) {
+				case TSampler2D:
+					shaderCompiled.setParamValue(allParameters[i], hxd.Res.load(allParamDefaultValue[i]).toTexture());
+				default:
+					shaderCompiled.setParamValue(allParameters[i], allParamDefaultValue[i]);
+			}
+		}
+		return shaderCompiled;
 	}
 
 	public function save() {
@@ -294,7 +354,7 @@ class ShaderGraph {
 			],
 			edges: edgesJson,
 			parameters: [
-				for (p in parametersAvailable) { name : p.name, type : p.type }
+				for (p in parametersAvailable) { id : p.id, name : p.name, type : [p.type.getName(), p.type.getParameters().toString()], defaultValue : p.defaultValue }
 			]
 		});
 

+ 1 - 0
hrt/shgraph/ShaderInput.hx

@@ -9,6 +9,7 @@ using hxsl.Ast;
 @description("Shader inputs of Heaps, it's dynamic")
 @group("Input")
 @noheader()
+@color("#1F690A")
 class ShaderInput extends ShaderNode {
 
 	@output() var output = SType.Variant;

+ 1 - 1
hrt/shgraph/ShaderNode.hx

@@ -88,7 +88,7 @@ class ShaderNode {
 	}
 
 	public function build(key : String) : TExpr {
-		throw "Not implemented";
+		throw "Build function not implemented";
 	}
 
 	public function checkTypeAndCompatibilyInput(key : String, type : ShaderType.SType) : Bool {

+ 1 - 0
hrt/shgraph/ShaderOutput.hx

@@ -10,6 +10,7 @@ using hxsl.Ast;
 @description("Parameters outputs, it's dynamic")
 @group("Output")
 @noheader()
+@color("#A90707")
 class ShaderOutput extends ShaderNode {
 
 	@input("input") var input = SType.Variant;

+ 26 - 15
hrt/shgraph/ShaderParam.hx

@@ -5,45 +5,56 @@ import hxsl.*;
 
 using hxsl.Ast;
 
-@name("Param")
-@description("Parameters inputs, it's dynamic")
-@group("Input")
 @noheader()
+@width(100)
+@color("#1F690A")
 class ShaderParam extends ShaderNode {
 
 	@output() var output = SType.Variant;
 
-	@prop() public var parameterName : String;
+	@prop() public var parameterId : Int;
 
-	private var variable : TVar;
+	public var variable : TVar;
+	private var parameterName : String;
+
+	override public function computeOutputs() {
+		if (variable != null)
+			addOutput("output", variable.type);
+		else
+			removeOutput("output");
+	}
 
 	override public function getOutput(key : String) : TVar {
 		return variable;
 	}
 
 	override public function loadProperties(props : Dynamic) {
-		parameterName = Reflect.field(props, "parameterName");
+		parameterId = Reflect.field(props, "parameterId");
 	}
 
 	override public function saveProperties() : Dynamic {
 		var parameters = {
-			parameterName: parameterName
+			parameterId: parameterId
 		};
 
 		return parameters;
 	}
 
+	override public function build(key : String) : TExpr {
+		return null;
+	}
+
 	#if editor
+	private var eltName : Element;
+	public function setName(s : String) {
+		parameterName = s;
+		if (eltName != null)
+			eltName.html(s);
+	}
 	override public function getPropertiesHTML(width : Float) : Array<Element> {
 		var elements = super.getPropertiesHTML(width);
-		var element = new Element('<div style="width: 110px; height: 30px"></div>');
-		element.append(new Element('<select class="variable"></select>'));
-
-		var input = element.children("select");
-		input.on("change", function(e) {
-			this.variable = input.val();
-		});
-
+		var element = new Element('<div style="width: 75px; height: 30px"></div>');
+		eltName = new Element('<span class="variable">${parameterName}</span>').appendTo(element);
 
 		elements.push(element);
 

+ 0 - 1
hrt/shgraph/nodes/Cond.hx

@@ -43,7 +43,6 @@ class Cond extends ShaderNode {
 	}
 
 	override public function build(key : String) : TExpr {
-
 		return {
 				p : null,
 				t : output.type,

+ 1 - 1
hrt/shgraph/nodes/Sampler.hx

@@ -6,7 +6,7 @@ using hxsl.Ast;
 
 @name("Sampler")
 @description("Get color from texture and UV")
-@group("AAAAA")
+@group("Input")
 class Sampler extends ShaderFunction {
 
 	@input("texture") var texture = SType.Sampler;

+ 0 - 30
hrt/shgraph/nodes/Texture.hx

@@ -1,30 +0,0 @@
-package hrt.shgraph.nodes;
-
-import hxsl.*;
-
-using hxsl.Ast;
-
-@name("Texture")
-@description("Create a texture from a file")
-@group("AAAA")
-class Texture extends ShaderNode {
-
-	@output("texture") var texture = SType.Sampler;
-
-	@prop("Variable") public var variable : TVar;
-
-	@prop() var fileTexture : String;
-
-	override public function computeOutputs() {
-		addOutput("texture", TSampler2D);
-	}
-
-	override public function getOutput(key : String) : TVar {
-		return variable;
-	}
-
-	override public function build(key : String) : TExpr {
-		return null;
-	}
-
-}