Browse Source

ShaderGraph: Center view, improve UI, fix load hidden tab, clean imports

Tom SPIRA 6 năm trước cách đây
mục cha
commit
257b0294cc

+ 7 - 1
bin/style.css

@@ -1186,7 +1186,7 @@ input[type=checkbox]:checked:after {
 }
 .graph-view #context-menu {
   position: absolute;
-  width: 100px;
+  width: 150px;
   box-shadow: 0px 0px 25px -4px black;
   background-color: #222222;
   border: 1px solid #444;
@@ -1348,6 +1348,12 @@ input[type=checkbox]:checked:after {
   font-size: 15px;
   font-weight: bold;
 }
+.graph-view .paramVisible {
+  color: black!important;
+  font-weight: bold;
+  font-style: italic;
+  letter-spacing: -0.5px;
+}
 /* Golden Layout Fixes */
 .lm_header .lm_tabs {
   z-index: 1;

+ 7 - 1
bin/style.less

@@ -1328,7 +1328,7 @@ input[type=checkbox] {
 	}
 	#context-menu {
 		position: absolute;
-		width: 100px;
+		width: 150px;
 		box-shadow: 0px 0px 25px -4px black;
 
 		background-color: rgb(34, 34, 34);
@@ -1527,6 +1527,12 @@ input[type=checkbox] {
 			font-weight: bold;
 		}
 	}
+	.paramVisible {
+		color: black!important;
+		font-weight: bold;
+		font-style: italic;
+		letter-spacing: -.5px;
+	}
 }
 
 /* Golden Layout Fixes */

+ 36 - 2
hide/view/Graph.hx

@@ -35,7 +35,7 @@ class Graph extends FileView {
 
 	var transformMatrix : Array<Float> = [1, 0, 0, 1, 0, 0];
 	var isPanning : Bool = false;
-
+	static var MAX_ZOOM = 1.2;
 
 	// used for moving when mouse is close to borders
 	static var BORDER_SIZE = 75;
@@ -631,12 +631,42 @@ class Graph extends FileView {
 		}
 	}
 
+	function centerView() {
+		var xMin = listOfBoxes[0].getX();
+		var yMin = listOfBoxes[0].getY();
+		var xMax = xMin + listOfBoxes[0].getWidth();
+		var yMax = yMin + listOfBoxes[0].getHeight();
+		for (i in 1...listOfBoxes.length) {
+			var b = listOfBoxes[i];
+			xMin = Math.min(xMin, b.getX());
+			yMin = Math.min(yMin, b.getY());
+			xMax = Math.max(xMax, b.getX() + b.getWidth());
+			yMax = Math.max(yMax, b.getY() + b.getHeight());
+		}
+		var center = new IPoint(Std.int(xMin + (xMax - xMin)/2), Std.int(yMin + (yMax - yMin)/2));
+		var scale = Math.min(MAX_ZOOM, Math.min((editor.element.width() - 50) / (xMax - xMin), (editor.element.height() - 50) / (yMax - yMin)));
+
+		transformMatrix[4] = editor.element.width()/2 - center.x;
+		transformMatrix[5] = editor.element.height()/2 - center.y;
+
+		transformMatrix[0] = scale;
+		transformMatrix[3] = scale;
+
+		var x = editor.element.width()/2;
+		var y = editor.element.height()/2;
+
+		transformMatrix[4] = x - (x - transformMatrix[4]) * scale;
+		transformMatrix[5] = y - (y - transformMatrix[5]) * scale;
+
+		updateMatrix();
+	}
+
 	function updateMatrix() {
 		editorMatrix.attr({transform: 'matrix(${transformMatrix.join(' ')})'});
 	}
 
 	function zoom(scale : Float, x : Int, y : Int) {
-		if (scale > 1 && transformMatrix[0] > 1.2) {
+		if (scale > 1 && transformMatrix[0] > MAX_ZOOM) {
 			return;
 		}
 
@@ -659,6 +689,10 @@ class Graph extends FileView {
 		updateMatrix();
 	}
 
+	function IsVisible() : Bool {
+		return editor.element.is(":visible");
+	}
+
 	// Useful method
 	function isInside(b : Box, min : Point, max : Point) {
 		if (max.x < b.getX() || min.x > b.getX() + b.getWidth())

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

@@ -67,7 +67,7 @@ class Box {
 		if (!hasHeader && color != null) {
 			bg.css("fill", color);
 		}
-		editor.line(element, width/2, HEADER_HEIGHT, width/2, 0, {display: "none"}).addClass("nodes-separator");
+		//editor.line(element, width/2, HEADER_HEIGHT, width/2, 0, {display: "none"}).addClass("nodes-separator");
 	}
 
 	public function addInput(editor : SVG, name : String, valueDefault : String = null) {

+ 82 - 31
hide/view/shadereditor/ShaderEditor.hx

@@ -1,5 +1,6 @@
 package hide.view.shadereditor;
 
+import h3d.Engine;
 import hrt.shgraph.ShaderParam;
 import hrt.shgraph.ShaderException;
 import haxe.Timer;
@@ -7,7 +8,6 @@ using hxsl.Ast.Type;
 
 import haxe.rtti.Meta;
 import hxsl.Shader;
-import hxsl.SharedShader;
 import hide.comp.SceneEditor;
 import js.jquery.JQuery;
 import h2d.col.Point;
@@ -39,6 +39,7 @@ class ShaderEditor extends hide.view.Graph {
 
 	override function onDisplay() {
 		super.onDisplay();
+		saveDisplayKey = "ShaderGraph:" + getPath().split("\\").join("/").substr(0,-1);
 		shaderGraph = new ShaderGraph(getPath());
 		addMenu = null;
 
@@ -53,6 +54,8 @@ class ShaderEditor extends hide.view.Graph {
 								<input id="createParameter" type="button" value="Add parameter" />
 								<input id="launchCompileShader" type="button" value="Compile shader" />
 								<input id="saveShader" type="button" value="Save" />
+								<input id="changeModel" type="button" value="Change Model" />
+								<input id="centerView" type="button" value="Center View" />
 							</div>
 						</div>)');
 		parent.on("drop", function(e) {
@@ -137,6 +140,12 @@ class ShaderEditor extends hide.view.Graph {
 			}
 		});
 
+		parent.on("contextmenu", function(e) {
+			customContextMenu([]); // TODO: add menu right click
+			e.preventDefault();
+			return false;
+		});
+
 		element.find("#createParameter").on("click", function() {
 			function createElement(name : String, type : Type) : Element {
 				var elt = new Element('
@@ -164,6 +173,21 @@ class ShaderEditor extends hide.view.Graph {
 			save();
 		});
 
+		element.find("#changeModel").on("click", function() {
+			ide.chooseFile(["fbx"], function(path) {
+				if( path == null ) return; // cancel
+				sceneEditor.scene.s3d.removeChild(obj);
+				obj = sceneEditor.scene.loadModel(path, true);
+				saveDisplayState("customModel", path);
+				sceneEditor.scene.s3d.addChild(obj);
+				compileShader();
+			});
+		});
+
+		element.find("#centerView").on("click", function() {
+			centerView();
+		});
+
 		parametersList = element.find("#parametersList");
 
 		editorMatrix.on("change", "input, select", function(ev) {
@@ -223,25 +247,7 @@ class ShaderEditor extends hide.view.Graph {
 			}
 
 			new Element(".nodes").ready(function(e) {
-
-				for (box in listOfBoxes) {
-					for (key in box.getInstance().getInputsKey()) {
-						var input = box.getInstance().getInput(key);
-						if (input != null) {
-							var fromBox : Box = null;
-							for (boxFrom in listOfBoxes) {
-								if (boxFrom.getId() == input.node.id) {
-									fromBox = boxFrom;
-									break;
-								}
-							}
-							var nodeFrom = fromBox.getElement().find('[field=${input.getKey()}]');
-							var nodeTo = box.getElement().find('[field=${key}]');
-							createEdgeInEditorGraph({from: fromBox, nodeFrom: nodeFrom, to : box, nodeTo: nodeTo, elt : createCurve(nodeFrom, nodeTo) });
-						}
-					}
-				}
-
+				generateEdges();
 			});
 
 
@@ -249,7 +255,6 @@ class ShaderEditor extends hide.view.Graph {
 				addParameter(p.id, p.name, p.type, p.defaultValue);
 			}
 		});
-
 	}
 
 	override function save() {
@@ -268,12 +273,49 @@ class ShaderEditor extends hide.view.Graph {
 			lightDirection = this.light.getDirection();
 		}
 
-		obj = sceneEditor.scene.loadModel("fx/Common/PrimitiveShapes/Sphere.fbx", true);
+		var saveCustomModel = getDisplayState("customModel");
+		if (saveCustomModel != null)
+			obj = sceneEditor.scene.loadModel(saveCustomModel, true);
+		else
+			obj = sceneEditor.scene.loadModel("fx/Common/PrimitiveShapes/Sphere.fbx", true);
 		sceneEditor.scene.s3d.addChild(obj);
 
 		element.find("#preview").first().append(sceneEditor.scene.element);
 
-		launchCompileShader();
+		if (IsVisible()) {
+			launchCompileShader();
+		} else {
+			var timer = new Timer(500);
+			timer.run = function() {
+				if (IsVisible()) {
+					generateEdges();
+					launchCompileShader();
+					timer.stop();
+				}
+			}
+		}
+	}
+
+	function generateEdges() {
+		if (IsVisible()) {
+			for (box in listOfBoxes) {
+				for (key in box.getInstance().getInputsKey()) {
+					var input = box.getInstance().getInput(key);
+					if (input != null) {
+						var fromBox : Box = null;
+						for (boxFrom in listOfBoxes) {
+							if (boxFrom.getId() == input.node.id) {
+								fromBox = boxFrom;
+								break;
+							}
+						}
+						var nodeFrom = fromBox.getElement().find('[field=${input.getKey()}]');
+						var nodeTo = box.getElement().find('[field=${key}]');
+						createEdgeInEditorGraph({from: fromBox, nodeFrom: nodeFrom, to : box, nodeTo: nodeTo, elt : createCurve(nodeFrom, nodeTo) });
+					}
+				}
+			}
+		}
 	}
 
 	function addParameter(id : Int, name : String, type : Type, ?value : Dynamic) {
@@ -351,6 +393,13 @@ 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() {
+			for (b in listOfBoxes) {
+				var shaderParam = Std.instance(b.getInstance(), ShaderParam);
+				if (shaderParam != null && shaderParam.parameterId == id) {
+					error("This parameter is used in the graph.");
+					return;
+				}
+			}
 			shaderGraph.removeParameter(id);
 			elt.remove();
 		});
@@ -391,12 +440,6 @@ class ShaderEditor extends hide.view.Graph {
 	}
 
 	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);
 
@@ -421,6 +464,7 @@ class ShaderEditor extends hide.view.Graph {
 		if (shaderGenerated != null)
 			saveShader = shaderGenerated.clone();
 		try {
+			sceneEditor.scene.setCurrent();
 			var timeStart = Date.now().getTime();
 
 			if (shaderGenerated != null)
@@ -437,8 +481,15 @@ class ShaderEditor extends hide.view.Graph {
 		} catch (e : Dynamic) {
 			if (Std.is(e, String)) {
 				var str : String = e;
-				if (str.split(":")[0] == "An error occurred compiling the shaders") { // aie
-					error("Compilation of shader failed > " + str);
+				if (str.split(":")[0] == "An error occurred compiling the shaders") {
+					var strSplitted = str.split("(output_");
+					var idBox = strSplitted[1].split("_")[0];
+					var idBoxParsed = Std.parseInt(idBox);
+					if (Std.string(idBoxParsed) == idBox) {
+						error("Compilation of shader failed > Invalid inputs", idBoxParsed);
+					} else {
+						error("Compilation of shader failed > " + str);
+					}
 					if (shaderGenerated != null)
 						for (m in obj.getMaterials())
 							m.mainPass.removeShader(shaderGenerated);

+ 1 - 3
hrt/shgraph/Operation.hx

@@ -1,7 +1,5 @@
 package hrt.shgraph;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 class Operation extends ShaderNode {
@@ -9,7 +7,7 @@ class Operation extends ShaderNode {
 	@input("A", true) var a = SType.Number;
 	@input("B", true) var b = SType.Number;
 
-	@output() var output = SType.Number;
+	@output("") var output = SType.Number;
 
 	var operation : Binop;
 

+ 0 - 1
hrt/shgraph/ParseFieldsMacro.hx

@@ -1,6 +1,5 @@
 package hrt.shgraph;
 
-import hrt.shgraph.ShaderType;
 import haxe.macro.Context;
 import haxe.macro.Expr;
 using haxe.macro.Tools;

+ 1 - 3
hrt/shgraph/ShaderFunction.hx

@@ -1,12 +1,10 @@
 package hrt.shgraph;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 class ShaderFunction extends ShaderNode {
 
-	@output() var output = SType.Variant;
+	@output("") var output = SType.Variant;
 
 	var func : TGlobal;
 

+ 6 - 0
hrt/shgraph/ShaderGraph.hx

@@ -280,6 +280,8 @@ class ShaderGraph {
 			}
 		}
 
+		var outputs : Array<String> = [];
+
 		for (n in nodes) {
 			if (Std.is(n.instance, ShaderInput)) {
 				var variable = Std.instance(n.instance, ShaderInput).variable;
@@ -289,6 +291,10 @@ class ShaderGraph {
 			}
 			if (Std.is(n.instance, ShaderOutput)) {
 				var variable = Std.instance(n.instance, ShaderOutput).variable;
+				if (outputs.indexOf(variable.name) != -1) {
+					throw ShaderException.t("This output already exists", n.id);
+				}
+				outputs.push(variable.name);
 				if ( !alreadyAddVariable(allVariables, variable) ) {
 					allVariables.push(variable);
 				}

+ 1 - 2
hrt/shgraph/ShaderInput.hx

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

+ 0 - 2
hrt/shgraph/ShaderOutput.hx

@@ -1,8 +1,6 @@
 package hrt.shgraph;
 
 import hide.Element;
-import h3d.Vector;
-import hxsl.*;
 
 using hxsl.Ast;
 

+ 4 - 5
hrt/shgraph/ShaderParam.hx

@@ -1,13 +1,12 @@
 package hrt.shgraph;
 
 import hide.Element;
-import hxsl.*;
 
 using hxsl.Ast;
 
 @noheader()
-@width(100)
-@color("#1F690A")
+@width(120)
+@color("#d6d6d6")
 class ShaderParam extends ShaderNode {
 
 	@output() var output = SType.Variant;
@@ -53,8 +52,8 @@ class ShaderParam extends ShaderNode {
 	}
 	override public function getPropertiesHTML(width : Float) : Array<Element> {
 		var elements = super.getPropertiesHTML(width);
-		var element = new Element('<div style="width: 75px; height: 30px"></div>');
-		eltName = new Element('<span class="variable">${parameterName}</span>').appendTo(element);
+		var element = new Element('<div style="width: 110px; height: 25px"></div>');
+		eltName = new Element('<span class="paramVisible" >${parameterName}</span>').appendTo(element);
 
 		elements.push(element);
 

+ 1 - 2
hrt/shgraph/nodes/Abs.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Abs")
 @description("The output is the result of |A|")
+@width(80)
 @group("Math")
 class Abs extends ShaderFunction {
 

+ 1 - 2
hrt/shgraph/nodes/Add.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Add")
 @description("The output is the result of A + B")
+@width(80)
 @group("Operation")
 class Add extends Operation {
 

+ 1 - 2
hrt/shgraph/nodes/Divide.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Divide")
 @description("The output is the result of A / B")
+@width(80)
 @group("Operation")
 class Divide extends Operation {
 

+ 1 - 2
hrt/shgraph/nodes/Maximum.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Maximum")
 @description("The output is the maximum between A and B")
+@width(80)
 @group("Math")
 class Maximum extends ShaderFunction {
 

+ 1 - 2
hrt/shgraph/nodes/Minimum.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Minimum")
 @description("The output is the minimum between A and B")
+@width(80)
 @group("Math")
 class Minimum extends ShaderFunction {
 

+ 1 - 2
hrt/shgraph/nodes/Multiply.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Multiply")
 @description("The output is the result of A * B")
+@width(80)
 @group("Operation")
 class Multiply extends Operation {
 

+ 0 - 2
hrt/shgraph/nodes/Sampler.hx

@@ -1,7 +1,5 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Sampler")

+ 1 - 2
hrt/shgraph/nodes/Sin.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Sinus")
 @description("The output is the sinus of A")
+@width(80)
 @group("Math")
 class Sin extends ShaderFunction {
 

+ 0 - 2
hrt/shgraph/nodes/Split.hx

@@ -1,7 +1,5 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Split")

+ 1 - 2
hrt/shgraph/nodes/Subtract.hx

@@ -1,11 +1,10 @@
 package hrt.shgraph.nodes;
 
-import hxsl.*;
-
 using hxsl.Ast;
 
 @name("Subtract")
 @description("The output is the result of A - B")
+@width(80)
 @group("Operation")
 class Subtract extends Operation {