Ver Fonte

ShaderGraph: input not required, text & mod box, sampler RGBA alone

Tom SPIRA há 6 anos atrás
pai
commit
445e15e255

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

@@ -47,15 +47,17 @@ class Box {
 		element.attr("id", node.id);
 		setPosition(x, y);
 
+		if (Reflect.hasField(metas, "noheader")) {
+			HEADER_HEIGHT = 0;
+			hasHeader = false;
+		}
+
 		// outline of box
 		editor.rect(element, -1, -1, width+2, getHeight()+2).addClass("outline");
 
 		// header
 
-		if (Reflect.hasField(metas, "noheader")) {
-			HEADER_HEIGHT = 0;
-			hasHeader = false;
-		} else {
+		if (hasHeader) {
 			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");
@@ -203,7 +205,7 @@ class Box {
 	}
 	public function getNodesHeight() {
 		var maxNb = Std.int(Math.max(inputs.length, outputs.length));
-		if (!hadToShowInputs && maxNb == 1 && propsHeight > 0) {
+		if (!hadToShowInputs && maxNb <= 1 && propsHeight > 0) {
 			return 0;
 		}
 		return NODE_MARGIN * (maxNb+1) + NODE_RADIUS * maxNb;

+ 2 - 1
hide/view/shadereditor/ShaderEditor.hx

@@ -697,6 +697,7 @@ class ShaderEditor extends hide.view.Graph {
 		} catch (e : Dynamic) {
 			if (Std.is(e, String)) {
 				var str : String = e;
+				trace(str);
 				if (str.split(":")[0] == "An error occurred compiling the shaders") {
 					var strSplitted = str.split("(output_");
 					if (strSplitted.length >= 2) {
@@ -984,7 +985,7 @@ class ShaderEditor extends hide.view.Graph {
 						elt.hide();
 						continue;
 					}
-					if (elt.children().first().html().toLowerCase().indexOf(value.toLowerCase()) != -1) {
+					if (value.length == 0 || elt.children().first().html().toLowerCase().indexOf(value.toLowerCase()) == 1) {
 						if (isFirst) {
 							this.selectedNode = elt;
 							isFirst = false;

+ 11 - 1
hrt/shgraph/ParseFieldsMacro.hx

@@ -30,6 +30,7 @@ class ParseFieldsMacro {
 							var get_sel = "get_" + sel;
 							var propSel = "prop_" + sel;
 							var hasProperty = false;
+							var isRequired = true;
 							var nameInput = "input";
 							if (m.params.length >= 1) {
 								switch(m.params[0].expr) {
@@ -55,6 +56,15 @@ class ParseFieldsMacro {
 									default:
 								}
 							}
+							if (m.params.length >= 3) {
+								switch(m.params[2].expr) {
+									case EConst(CIdent(b)):
+										if (b == "false") {
+											isRequired = false;
+										}
+									default:
+								}
+							}
 							if (hasProperty) {
 								var sfields = macro class {
 									inline function $get_sel() : NodeVar {
@@ -78,7 +88,7 @@ class ParseFieldsMacro {
 								Context.error('Input ${sel} has not affectation', f.pos);
 
 							var enumValue = ["ShaderType", "SType", e.toString().split(".").pop()];
-							mapInputs.push(macro $v{sel} => { name : $v{nameInput}, type : ${enumValue.toFieldExpr()}, hasProperty: $v{hasProperty} });
+							mapInputs.push(macro $v{sel} => { name : $v{nameInput}, type : ${enumValue.toFieldExpr()}, hasProperty: $v{hasProperty}, isRequired : $v{isRequired} });
 							f.kind = FProp("get", "null", TPath({ pack: ["hrt", "shgraph"], name: "NodeVar" }));
 							f.meta = saveMeta;
 							inputsList.push(f.name);

+ 1 - 1
hrt/shgraph/ShaderGraph.hx

@@ -194,7 +194,7 @@ class ShaderGraph {
 			if (input != null) {
 				res = res.concat(buildNodeVar(input));
 			} else if (node.getInputInfo(key).hasProperty) {
-			} else if (isSubGraph) {
+			} else if (!node.getInputInfo(key).isRequired) {
 			} else {
 				throw ShaderException.t("This box has inputs not connected", node.id);
 			}

+ 1 - 1
hrt/shgraph/ShaderNode.hx

@@ -2,7 +2,7 @@ package hrt.shgraph;
 
 using hxsl.Ast;
 
-typedef InputInfo = { name : String, type : ShaderType.SType, hasProperty : Bool, ?id : Int };
+typedef InputInfo = { name : String, type : ShaderType.SType, hasProperty : Bool, isRequired : Bool, ?id : Int };
 typedef OutputInfo = { name : String, type : ShaderType.SType, ?id : Int };
 
 @:autoBuild(hrt.shgraph.ParseFieldsMacro.build())

+ 46 - 16
hrt/shgraph/nodes/Combine.hx

@@ -10,15 +10,16 @@ using hxsl.Ast;
 @group("Channel")
 class Combine extends ShaderNode {
 
-	@input("R") var r = SType.Float;
-	@input("G") var g = SType.Float;
-	@input("B") var b = SType.Float;
-	@input("A") var a = SType.Float;
+	@input("R", false, false) var r = SType.Float;
+	@input("G", false, false) var g = SType.Float;
+	@input("B", false, false) var b = SType.Float;
+	@input("A", false, false) var a = SType.Float;
 
-	@output() var output = SType.Vec4;
+	@output() var output = SType.Variant;
 
 	var components = [X, Y, Z, W];
 	var componentsString = ["r", "g", "b", "a"];
+	var numberOutputs = 0;
 
 	function generateOutputComp(idx : Int) : TExpr {
 		var comp = components[idx];
@@ -40,11 +41,47 @@ class Combine extends ShaderNode {
 	}
 
 	override public function computeOutputs() {
-		addOutput("output", TVec(4, VFloat));
+		numberOutputs = 1;
+		if (a != null && !a.isEmpty()) {
+			numberOutputs = 4;
+		} else if (b != null && !b.isEmpty()) {
+			numberOutputs = 3;
+		} else if (g != null && !g.isEmpty()) {
+			numberOutputs = 2;
+		}
+		if (numberOutputs == 1) {
+			addOutput("output", TFloat);
+		} else {
+			addOutput("output", TVec(numberOutputs, VFloat));
+		}
 	}
 
 	override public function build(key : String) : TExpr {
 
+		var args = [];
+		var valueArgs = [];
+		var opTGlobal : TGlobal = Vec4;
+		if (numberOutputs >= 1) {
+			args.push({ name: "r", type : TFloat });
+			valueArgs.push(r.getVar());
+			opTGlobal = ToFloat;
+		}
+		if (numberOutputs >= 2) {
+			args.push({ name: "g", type : TFloat });
+			valueArgs.push(g.getVar());
+			opTGlobal = Vec2;
+		}
+		if (numberOutputs >= 3) {
+			args.push({ name: "b", type : TFloat });
+			valueArgs.push(g.getVar());
+			opTGlobal = Vec3;
+		}
+		if (numberOutputs >= 4) {
+			args.push({ name: "a", type : TFloat });
+			valueArgs.push(a.getVar());
+			opTGlobal = Vec4;
+		}
+
 		return {
 			p : null,
 			t : output.type,
@@ -55,22 +92,15 @@ class Combine extends ShaderNode {
 			},
 			{
 				e: TCall({
-					e: TGlobal(Vec4),
+					e: TGlobal(opTGlobal),
 					p: null,
 					t: TFun([
 						{
 							ret: output.type,
-							args: [
-							{ name: "r", type : TFloat },
-							{ name: "g", type : TFloat },
-							{ name: "b", type : TFloat },
-							{ name: "a", type : TFloat }]
+							args: args
 						}
 					])
-				}, [(r != null) ? r.getVar() : { e: TConst(CFloat(0.0)), p: null, t: TFloat },
-					(g != null) ? g.getVar() : { e: TConst(CFloat(0.0)), p: null, t: TFloat },
-					(b != null) ? b.getVar() : { e: TConst(CFloat(0.0)), p: null, t: TFloat },
-					(a != null) ? a.getVar() : { e: TConst(CFloat(1.0)), p: null, t: TFloat }]
+				}, valueArgs
 				),
 				p: null,
 				t: output.type

+ 25 - 0
hrt/shgraph/nodes/Mod.hx

@@ -0,0 +1,25 @@
+package hrt.shgraph.nodes;
+
+using hxsl.Ast;
+
+@name("Modulo")
+@description("The output is the result of X modulo MOD")
+@width(80)
+@group("Math")
+class Mod extends ShaderFunction {
+
+	@input("x") var x = SType.Float;
+	@input("mod") var mod = SType.Float;
+
+	public function new() {
+		super(Mod);
+	}
+
+	override public function computeOutputs() {
+		if (x != null && !x.isEmpty())
+			addOutput("output", x.getType());
+		else
+			removeOutput("output");
+	}
+
+}

+ 82 - 5
hrt/shgraph/nodes/Sampler.hx

@@ -5,17 +5,94 @@ using hxsl.Ast;
 @name("Sampler")
 @description("Get color from texture and UV")
 @group("Input")
-class Sampler extends ShaderFunction {
+class Sampler extends ShaderNode {
 
 	@input("texture") var texture = SType.Sampler;
 	@input("uv") var uv = SType.Vec2;
 
-	public function new() {
-		super(Texture);
-	}
+	@output("rgba") var rgba = SType.Vec4;
+	@output("r") var r = SType.Float;
+	@output("g") var g = SType.Float;
+	@output("b") var b = SType.Float;
+	@output("a") var a = SType.Float;
+
+	var components = [X, Y, Z, W];
+	var componentsString = ["r", "g", "b", "a"];
 
 	override public function computeOutputs() {
-		addOutput("output", TVec(4, VFloat));
+		addOutput("rgba", TVec(4, VFloat));
+		addOutput("r", TFloat);
+		addOutput("g", TFloat);
+		addOutput("b", TFloat);
+		addOutput("a", TFloat);
+	}
+
+	override public function build(key : String) : TExpr {
+		if (key == "rgba") {
+			var args = [];
+			var varArgs = [];
+
+			for (k in getInputInfoKeys()) {
+				args.push({ name: k, type: getInput(k).getType() });
+				var wantedType = ShaderType.getType(getInputInfo(k).type);
+				varArgs.push(getInput(k).getVar((wantedType != null) ? wantedType : null));
+			}
+
+			return {
+						p : null,
+						t : rgba.type,
+						e : TBinop(OpAssign, {
+							e: TVar(rgba),
+							p: null,
+							t: rgba.type
+						}, {
+							e: TCall({
+								e: TGlobal(Texture),
+								p: null,
+								t: TFun([
+									{
+										ret: rgba.type,
+										args: args
+									}
+								])
+							}, varArgs),
+							p: null,
+							t: rgba.type
+						})
+					};
+		} else {
+			var arrayExpr = [];
+			if (!outputCompiled.get("rgba")) {
+				arrayExpr.push({ e : TVarDecl(rgba), t : rgba.type, p : null });
+				arrayExpr.push(build("rgba"));
+				outputCompiled.set("rgba", true);
+			}
+			var compIdx = componentsString.indexOf(key);
+			arrayExpr.push({ e: TBinop(OpAssign, {
+						e: TVar(getOutput(key)),
+						p: null,
+						t: getOutput(key).type
+					}, {e: TSwiz({
+							e: TVar(rgba),
+							p: null,
+							t: rgba.type
+						},
+						[components[compIdx]]),
+						p: null,
+						t: getOutput(key).type }),
+					p: null,
+					t: getOutput(key).type
+				});
+			if (arrayExpr.length > 1) {
+				return {
+					p : null,
+					t : TVoid,
+					e : TBlock(arrayExpr)
+				};
+			} else {
+				return arrayExpr[0];
+			}
+		}
 	}
 
 }

+ 3 - 2
hrt/shgraph/nodes/SubGraph.hx

@@ -44,12 +44,12 @@ class SubGraph extends ShaderNode {
 						var shaderParam = Std.instance(node.instance, ShaderParam);
 						var paramName = subShaderGraph.getParameter(shaderParam.parameterId).name;
 
-						inputsInfo.set(prefixSubGraph+node.id, { name : paramName , type: ShaderType.getSType(shaderParam.variable.type), hasProperty: false, id : node.id });
+						inputsInfo.set(prefixSubGraph+node.id, { name : paramName , type: ShaderType.getSType(shaderParam.variable.type), hasProperty: false, isRequired : false, id : node.id });
 						inputInfoKeys.push(prefixSubGraph+node.id);
 					case "ShaderInput":
 						var shaderInput = Std.instance(node.instance, ShaderInput);
 
-						inputsInfo.set(prefixSubGraph+node.id, { name : "*" + shaderInput.variable.name , type: ShaderType.getSType(shaderInput.variable.type), hasProperty: false, id : node.id });
+						inputsInfo.set(prefixSubGraph+node.id, { name : "*" + shaderInput.variable.name , type: ShaderType.getSType(shaderInput.variable.type), hasProperty: false, isRequired : false, id : node.id });
 						inputInfoKeys.push(prefixSubGraph+node.id);
 					case "ShaderOutput":
 						var shaderOutput = Std.instance(node.instance, ShaderOutput);
@@ -61,6 +61,7 @@ class SubGraph extends ShaderNode {
 					default:
 						var shaderConst = Std.instance(node.instance, ShaderConst);
 						if (shaderConst != null) { // input static become properties
+							if (shaderConst.name.length == 0) continue;
 							if (Std.is(shaderConst, BoolConst)) {
 								parameters.push({ name : shaderConst.name, type : TBool, defaultValue : null, id : shaderConst.id });
 							} else if (Std.is(shaderConst, FloatConst)) {

+ 39 - 0
hrt/shgraph/nodes/Text.hx

@@ -0,0 +1,39 @@
+package hrt.shgraph.nodes;
+
+using hxsl.Ast;
+
+@name("Text")
+@description("Only UI, to add text")
+@group("Other")
+@width(200)
+@color("#c7c700")
+@noheader()
+class Text extends ShaderNode {
+
+	@prop() var text : String = "";
+
+	override public function build(key : String) : TExpr {
+		return null;
+	}
+
+	#if editor
+	override public function getPropertiesHTML(width : Float) : Array<hide.Element> {
+		var elements = super.getPropertiesHTML(width);
+		var element = new hide.Element('<div style="width: ${width-35}px; height: 35px"></div>');
+		element.append(new hide.Element('<input type="text" id="value" style="width: ${width-35}px; height: 22px; font-size: 16px;" placeholder="Name" value="${this.text}" />'));
+
+		var input = element.children("input");
+		input.on("keydown", function(e) {
+			e.stopPropagation();
+		});
+		input.on("change", function(e) {
+			this.text = input.val();
+		});
+
+		elements.push(element);
+
+		return elements;
+	}
+	#end
+
+}