2
0
Эх сурвалжийг харах

Refactored dynamic inputs, and restored boolean conditions

Clement Espeute 1 жил өмнө
parent
commit
f370cab773

+ 13 - 10
hide/view/shadereditor/Box.hx

@@ -88,15 +88,16 @@ class Box {
 			bg.css("fill", color);
 		}
 
-		closePreviewBtn = editor.foreignObject(element, width / 2 - 16, 0, 32,32);
-		closePreviewBtn.append(new JQuery('<div class="close-preview"><span class="ico"></span></div>'));
-
-		refreshCloseIcon();
-		closePreviewBtn.on("click", (e) -> {
-			e.stopPropagation();
-			setPreviewVisibility(!node.showPreview);
-		});
-
+		if (node.canHavePreview()) {
+			closePreviewBtn = editor.foreignObject(element, width / 2 - 16, 0, 32,32);
+			closePreviewBtn.append(new JQuery('<div class="close-preview"><span class="ico"></span></div>'));
+
+			refreshCloseIcon();
+			closePreviewBtn.on("click", (e) -> {
+				e.stopPropagation();
+				setPreviewVisibility(!node.showPreview);
+			});
+		}
 		//editor.line(element, width/2, HEADER_HEIGHT, width/2, 0, {display: "none"}).addClass("nodes-separator");
 	}
 
@@ -106,6 +107,8 @@ class Box {
 	}
 
 	function refreshCloseIcon() {
+		if (closePreviewBtn == null)
+			return;
 		closePreviewBtn.find(".ico").toggleClass("ico-angle-down", !nodeInstance.showPreview);
 		closePreviewBtn.find(".ico").toggleClass("ico-angle-up", nodeInstance.showPreview);
 	}
@@ -259,7 +262,7 @@ class Box {
 			propertiesGroup.find(".properties").attr("height", propsHeight);
 		}
 
-		closePreviewBtn.attr("y",HEADER_HEIGHT + height + propsHeight - 16);
+		closePreviewBtn?.attr("y",HEADER_HEIGHT + height + propsHeight - 16);
 	}
 
 	public function setPosition(x : Float, y : Float) {

+ 56 - 9
hrt/shgraph/ShaderGraph.hx

@@ -10,6 +10,7 @@ import hrt.shgraph.AstTools.*;
 enum ShaderDefInput {
 	Var(name: String);
 	Const(intialValue: Float);
+	ConstBool(initialValue: Bool);
 }
 
 typedef ShaderNodeDefInVar = {v: TVar, internal: Bool, ?defVal: ShaderDefInput, isDynamic: Bool};
@@ -73,6 +74,7 @@ class ShaderGraph extends hrt.prefab.Prefab {
 
 	static var _ = hrt.prefab.Library.register("shgraph", hrt.shgraph.ShaderGraph, "shgraph");
 
+
 	override public function load(json : Dynamic) : Void {
 
 		graphs = [];
@@ -111,6 +113,36 @@ class ShaderGraph extends hrt.prefab.Prefab {
 		return haxe.Json.stringify(save(), "\t");
 	}
 
+	static public function resolveDynamicType(inputTypes: Array<Type>, inVars: Array<ShaderNodeDefInVar>) : Type {
+		var dynamicType : Type = TFloat;
+		for (i => t in inputTypes) {
+			var targetInput = inVars[i];
+			if (targetInput == null)
+				throw "More input types than inputs";
+			if (!targetInput.isDynamic)
+				continue; // Skip variables not marked as dynamic
+			switch (t) {
+				case null:
+				case TFloat:
+					if (dynamicType == null)
+						dynamicType = TFloat;
+				case TVec(size, t1): // Vec2 always convert to it because it's the smallest vec type
+					switch(dynamicType) {
+						case TFloat, null:
+							dynamicType = t;
+						case TVec(size2, t2):
+							if (t1 != t2)
+								throw "Incompatible vectors types";
+							dynamicType = TVec(size < size2 ? size : size2, t1);
+						default:
+					}
+				default:
+					throw "Type " + t + " is incompatible with Dynamic";
+			}
+		}
+		return dynamicType;
+	}
+
 
 	public function compile2(?previewDomain: Domain) : hrt.prefab.ContextShared.ShaderDef {
 		#if !editor
@@ -653,16 +685,24 @@ class Graph {
 
 			var def = node.instance.getShaderDef(domain, getNewVarId, data.inputTypes);
 
-			// Don't cache vars while there still are dynamics inputs as getShaderDef
-			// is responsible for dynamic typing resolution
-			for (input in def.inVars) {
-				if (input.isDynamic)
-					return def;
+			var type = ShaderGraph.resolveDynamicType(data.inputTypes, def.inVars);
+
+			// Don't cache vars while there still are dynamics inputs
+			if (type == null)
+				return def;
+
+			for (v in def.inVars) {
+				if (v.isDynamic) {
+					v.v.type = type;
+					v.isDynamic = false;
+				}
 			}
 
-			for (output in def.outVars) {
-				if (output.isDynamic)
-					throw "Output is dynamic while there is no remaining dynamic inputs.";
+			for (v in def.outVars) {
+				if (v.isDynamic) {
+					v.v.type = type;
+					v.isDynamic = false;
+				}
 			}
 
 			return def;
@@ -1047,6 +1087,13 @@ class Graph {
 										defVal = Std.parseFloat(defaultValue) ?? defVal;
 									}
 									replacement = convertToType(nodeVar.v.type, {e: TConst(CFloat(defVal)), p: pos, t:TFloat});
+								case ConstBool(def):
+									var defVal = def;
+									var defaultValue = Reflect.getProperty(currentNode.instance.defaults, nodeVar.v.name);
+									if (defaultValue != null) {
+										defVal = defaultValue == "true";
+									}
+									replacement = makeExpr(TConst(CBool(defVal)), TBool);
 								case Var(name):
 									var tvar = externs.find((v) -> v.name == name);
 									if (tvar == null) {
@@ -1114,7 +1161,7 @@ class Graph {
 							outputDecls.push(outputVar);
 						}
 
-						if (i == 0 && includePreviews && outputVar != null) {
+						if (i == 0 && includePreviews && outputVar != null && currentNode.instance.canHavePreview()) {
 
 
 							var finalExpr = makeAssign(makeVar(outputPreviewPixelColor), convertToType(outputPreviewPixelColor.type, makeVar(outputVar)));

+ 6 - 2
hrt/shgraph/ShaderNode.hx

@@ -190,8 +190,12 @@ class ShaderNode {
 		}
 	}
 
-	public function shouldShowPreview() {
-		return showPreview;
+	final public function shouldShowPreview() : Bool {
+		return showPreview && canHavePreview();
+	}
+
+	public function canHavePreview() : Bool {
+		return true;
 	}
 
 	public function saveProperties() : Dynamic {

+ 4 - 46
hrt/shgraph/ShaderNodeHxsl.hx

@@ -54,6 +54,8 @@ class ShaderNodeHxsl extends ShaderNode {
 			var outVars : Array<hrt.shgraph.ShaderGraph.ShaderNodeDefOutVar> = [];
 			var externVars = [];
 
+			var classDynamicVal : Array<String> = cast (cl:Dynamic)._dynamicValues;
+
 			for (tvar in data.vars) {
 					var input = false;
 					var output = false;
@@ -72,7 +74,7 @@ class ShaderNodeHxsl extends ShaderNode {
 								def = Var(defStr);
 							}
 						}
-						inVars.push({v:tvar, internal: false, defVal: def, isDynamic: false});
+						inVars.push({v:tvar, internal: false, defVal: def, isDynamic: classDynamicVal.contains(tvar.name)});
 						// TODO : handle default values
 						input = true;
 					}
@@ -94,53 +96,9 @@ class ShaderNodeHxsl extends ShaderNode {
 					}
 			}
 
-			var classDynamicVal : Array<String> = cast (cl:Dynamic)._dynamicValues;
-
-			// DynamicType is the smallest vector type or float if all inputTypes are floats
-			var dynamicType : Type = null;
-			if (inputTypes != null) {
-				dynamicType = TFloat;
-				for (i => t in inputTypes) {
-					var targetInput = inVars[i];
-					if (targetInput == null)
-						throw "More input types than inputs";
-					if (!classDynamicVal.contains(targetInput.v.name))
-						continue; // Skip variables not marked as dynamic
-					switch (t) {
-						case null:
-						case TFloat:
-							if (dynamicType == null)
-								dynamicType = TFloat;
-						case TVec(size, t1): // Vec2 always convert to it because it's the smallest vec type
-							switch(dynamicType) {
-								case TFloat, null:
-									dynamicType = t;
-								case TVec(size2, t2):
-									if (t1 != t2)
-										throw "Incompatible vectors types";
-									dynamicType = TVec(size < size2 ? size : size2, t1);
-								default:
-							}
-						default:
-							throw "Type " + t + " is incompatible with Dynamic";
-					}
-				}
-			}
-
-
-			for (v in inVars) {
-				if (classDynamicVal.contains(v.v.name)) {
-					v.v.type = dynamicType;
-					if (dynamicType == null)
-						v.isDynamic = true;
-				}
-			}
-
 			for (v in outVars) {
 				if (classDynamicVal.contains(v.v.name)) {
-					v.v.type = dynamicType;
-					if (dynamicType == null)
-						v.isDynamic = true;
+					v.isDynamic = true;
 				}
 			}
 

+ 2 - 7
hrt/shgraph/ShaderParam.hx

@@ -61,13 +61,8 @@ class ShaderParam extends ShaderNode {
 	}
 
 
-	override function shouldShowPreview() {
-		if (!super.shouldShowPreview())
-			return false;
-
-		if(this.variable.type == TSampler2D)
-			return false;
-		return true;
+	override public function canHavePreview() {
+		return this.variable.type != TSampler2D;
 	}
 
 	override public function build(key : String) : TExpr {

+ 74 - 47
hrt/shgraph/nodes/Cond.hx

@@ -2,16 +2,40 @@ package hrt.shgraph.nodes;
 
 using hxsl.Ast;
 
+import hrt.shgraph.AstTools.*;
+
 @name("Condition")
 @description("Create a custom condition between two inputs")
 @group("Condition")
 class Cond extends ShaderNode {
 
+	override public function getShaderDef(domain: ShaderGraph.Domain, getNewIdFn : () -> Int, ?inputTypes: Array<Type>) : ShaderGraph.ShaderNodeDef {
+
+		var a : TVar = {name : "a", id: getNewIdFn(), type: TFloat, kind: Local, qualifiers: []};
+		var b : TVar = {name : "b", id: getNewIdFn(), type: TFloat, kind: Local, qualifiers: []};
+
+		var out : TVar = {name: "out", id: getNewIdFn(), type: TBool, kind: Local, qualifiers: []};
+
+		var cond = makeExpr(TBinop(condition, makeVar(a), makeVar(b)), TBool);
+		var expr = makeAssign(makeVar(out), cond);
+		return {
+			expr: expr,
+			inVars: [{v:a, internal: false, defVal: Const(0.0), isDynamic: false}, {v:b, internal: false, defVal: Const(0.0), isDynamic: false}],
+			outVars:[{v:out, internal: false, isDynamic: false}],
+			inits: [],
+			externVars: []
+		};
+	};
+
+	override function canHavePreview():Bool {
+		return false;
+	}
+
 	// @input("Left") var leftVar = SType.Number;
 	// @input("Right") var rightVar = SType.Number;
 
 
-	// @prop() var condition : Binop;
+	@prop() var condition : Binop = OpEq;
 
 	// override public function checkValidityInput(key : String, type : ShaderType.SType) : Bool {
 
@@ -55,51 +79,54 @@ class Cond extends ShaderNode {
 	// 		};
 	// }
 
-	// var availableConditions = [OpEq, OpNotEq, OpGt, OpGte, OpLt, OpLte, OpAnd, OpOr];
-	// var conditionStrings 	= ["==", "!=",    ">",  ">=",  "<",  "<=",  "AND", "OR"];
-
-	// override public function loadProperties(props : Dynamic) {
-	// 	this.condition = std.Type.createEnum(Binop, Reflect.field(props, "Condition"));
-	// }
-
-	// override public function saveProperties() : Dynamic {
-	// 	if (this.condition == null)
-	// 		this.condition = availableConditions[0];
-	// 	var properties = {
-	// 		condition: this.condition.getName()
-	// 	};
-
-	// 	return properties;
-	// }
-
-	// #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 * 0.8}px; height: 40px"></div>');
-	// 	element.append('<span>Condition</span>');
-	// 	element.append(new hide.Element('<select id="condition"></select>'));
-
-	// 	if (this.condition == null) {
-	// 		this.condition = availableConditions[0];
-	// 	}
-	// 	var input = element.children("select");
-	// 	var indexOption = 0;
-	// 	for (c in conditionStrings) {
-	// 		input.append(new hide.Element('<option value="${indexOption}">${c}</option>'));
-	// 		if (this.condition == availableConditions[indexOption]) {
-	// 			input.val(indexOption);
-	// 		}
-	// 		indexOption++;
-	// 	}
-	// 	input.on("change", function(e) {
-	// 		var value = input.val();
-	// 		this.condition = availableConditions[value];
-	// 	});
-
-	// 	elements.push(element);
-
-	// 	return elements;
-	// }
-	// #end
+	static var availableConditions = [OpEq, OpNotEq, OpGt, OpGte, OpLt, OpLte, OpAnd, OpOr];
+	static var conditionStrings 	= ["==", "!=",    ">",  ">=",  "<",  "<=",  "AND", "OR"];
+
+	override public function loadProperties(props : Dynamic) {
+		if (Reflect.hasField(props, "condition"))
+			this.condition = std.Type.createEnum(Binop, Reflect.field(props, "condition"));
+		else
+			this.condition = OpEq;
+	}
+
+	override public function saveProperties() : Dynamic {
+		if (this.condition == null)
+			this.condition = availableConditions[0];
+		var properties = {
+			condition: this.condition.getName()
+		};
+
+		return properties;
+	}
+
+	#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 * 0.8}px; height: 40px"></div>');
+		element.append('<span>Condition</span>');
+		element.append(new hide.Element('<select id="condition"></select>'));
+
+		if (this.condition == null) {
+			this.condition = availableConditions[0];
+		}
+		var input = element.children("select");
+		var indexOption = 0;
+		for (c in conditionStrings) {
+			input.append(new hide.Element('<option value="${indexOption}">${c}</option>'));
+			if (this.condition == availableConditions[indexOption]) {
+				input.val(indexOption);
+			}
+			indexOption++;
+		}
+		input.on("change", function(e) {
+			var value = input.val();
+			this.condition = availableConditions[value];
+		});
+
+		elements.push(element);
+
+		return elements;
+	}
+	#end
 
 }

+ 24 - 0
hrt/shgraph/nodes/IfCondition.hx

@@ -1,6 +1,7 @@
 package hrt.shgraph.nodes;
 
 using hxsl.Ast;
+import hrt.shgraph.AstTools.*;
 
 @name("If")
 @description("Return the correct input according to the condition")
@@ -11,6 +12,29 @@ class IfCondition extends ShaderNode {
 	// @input("True") var trueVar = SType.Variant;
 	// @input("False") var falseVar = SType.Variant;
 
+	override public function getShaderDef(domain: ShaderGraph.Domain, getNewIdFn : () -> Int, ?inputTypes: Array<Type>) : ShaderGraph.ShaderNodeDef {
+
+		var condition : TVar = {name : "condition", id: getNewIdFn(), type: TBool, kind: Local, qualifiers: []};
+
+		var vTrue : TVar = {name : "true", id: getNewIdFn(), type: TFloat, kind: Local, qualifiers: []};
+		var vFalse : TVar = {name : "false", id: getNewIdFn(), type: TFloat, kind: Local, qualifiers: []};
+
+		var out : TVar = {name : "out", id: getNewIdFn(), type: TFloat, kind: Local, qualifiers: []};
+
+		var expr = makeIf(makeVar(condition), makeAssign(makeVar(out), makeVar(vTrue)), makeAssign(makeVar(out), makeVar(vFalse)));
+
+		return {
+			expr: expr,
+			inVars: [
+				{v:condition, internal: false, isDynamic: false, defVal: ConstBool(false)},
+				{v:vTrue, internal: false, defVal: Const(0.0), isDynamic: true}, {v:vFalse, internal: false, defVal: Const(0.0), isDynamic: true}],
+			outVars:[{v:out, internal: false, isDynamic: true}],
+			inits: [],
+			externVars: []
+		};
+	}
+
+
 
 	// override public function checkValidityInput(key : String, type : ShaderType.SType) : Bool {