Selaa lähdekoodia

[shgraph] Reworking parameters

Clément Espeute 1 vuosi sitten
vanhempi
commit
9ee47647a8

+ 70 - 64
bin/style.css

@@ -1934,6 +1934,10 @@ input[type=checkbox]:checked:after {
   visibility: visible;
 }
 /* Shader Editor */
+.shader-editor {
+  display: flex;
+  flex-direction: row;
+}
 .shader-editor #preview {
   z-index: 3;
   position: absolute;
@@ -1941,7 +1945,7 @@ input[type=checkbox]:checked:after {
   height: 300px;
   background-color: #111;
   border: 1px solid #444;
-  right: 290px;
+  right: 35px;
   bottom: 35px;
 }
 .shader-editor #preview .hide-toolbar2 {
@@ -1949,81 +1953,67 @@ input[type=checkbox]:checked:after {
   right: 8px;
   top: 8px;
 }
-.graph-view {
-  outline: none !important;
-}
-.graph-view .mini-preview {
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  z-index: 0;
-}
-.graph-view #graph-root {
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  z-index: 0;
+.shader-editor .flex.vertical {
+  position: relative;
 }
-.graph-view .tabs {
+.shader-editor #rightPanel {
+  flex: 0;
+  min-width: 270px;
   width: 280px;
   padding-top: 10px;
   border-left: 1px solid #444444;
-  z-index: 205;
   background: #222222;
-  height: 100%;
   user-select: none;
+  height: 100%;
 }
-.graph-view .tabs span {
+.shader-editor #rightPanel span {
   margin-left: 5px;
   font-size: 15px;
   font-weight: bold;
 }
-.graph-view .tabs .tab {
-  height: 100%;
-}
-.graph-view .tabs .tab .hide-block {
+.shader-editor #rightPanel .hide-block {
   height: 600px;
 }
-.graph-view .tabs .tab .hide-block #parametersList {
+.shader-editor #rightPanel .hide-block #parametersList {
   height: 100%;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter {
+.shader-editor #rightPanel .hide-block #parametersList .parameter {
   border: 1px solid;
   margin: 5px;
   background-color: #222;
   position: relative;
   /*.content {
-							background-color: #b3b3b3;
-							padding: 5px;
-							box-shadow: inset 0px 13px 6px -15px black;
+						background-color: #b3b3b3;
+						padding: 5px;
+						box-shadow: inset 0px 13px 6px -15px black;
 
-							div {
-								width: 100%;
-								height: 20px;
+						div {
+							width: 100%;
+							height: 20px;
 
-								span {
-									float: left;
-									color: black;
-									font-size: 13px;
-									padding-right: 5px;
-									font-weight: normal;
-								}
+							span {
+								float: left;
+								color: black;
+								font-size: 13px;
+								padding-right: 5px;
+								font-weight: normal;
 							}
-							.texture-preview {
-								background-repeat: no-repeat;
-								background-size: 20px 20px!important;
-								border: 2px #444444 solid;
-								width: 20px;
+						}
+						.texture-preview {
+							background-repeat: no-repeat;
+							background-size: 20px 20px!important;
+							border: 2px #444444 solid;
+							width: 20px;
+						}
+						.action-btns {
+							input {
+								float: right;
 							}
-							.action-btns {
-								input {
-									float: right;
-								}
-							}
-						}*/
+						}
+					}*/
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter.hovertop:before,
-.graph-view .tabs .tab .hide-block #parametersList .parameter.hoverbot:after {
+.shader-editor #rightPanel .hide-block #parametersList .parameter.hovertop:before,
+.shader-editor #rightPanel .hide-block #parametersList .parameter.hoverbot:after {
   display: block;
   position: absolute;
   z-index: 100;
@@ -2031,59 +2021,75 @@ input[type=checkbox]:checked:after {
   width: 100%;
   content: "";
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter:before {
+.shader-editor #rightPanel .hide-block #parametersList .parameter:before {
   border-top: 5px solid red;
   top: -10px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter:after {
+.shader-editor #rightPanel .hide-block #parametersList .parameter:after {
   border-bottom: 5px solid red;
   bottom: -10px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .header {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .header {
   background-color: #d6d6d6;
   height: 20px;
   padding: 5px;
   color: black;
   cursor: pointer;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .header .title {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .header .title {
   float: left;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .header .title input {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .header .title input {
   width: 130px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .header .type {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .header .type {
   float: right;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .header .type span {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .header .type span {
   color: black;
   font-style: italic;
   font-size: 13px;
   padding-right: 5px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .content {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .content {
   padding: 4px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter .content > div {
+.shader-editor #rightPanel .hide-block #parametersList .parameter .content > div {
   margin-top: 2px;
 }
-.graph-view .tabs .tab .hide-block #parametersList .parameter > span {
+.shader-editor #rightPanel .hide-block #parametersList .parameter > span {
   font-size: 12px;
 }
-.graph-view .tabs .tab .options-block {
+.shader-editor #rightPanel .options-block {
   height: max(250px, 25%);
 }
-.graph-view .tabs .tab .options-block > * {
+.shader-editor #rightPanel .options-block > * {
   display: block;
   margin-bottom: 10px;
   width: 100%;
   text-align: center;
   box-sizing: border-box;
 }
-.graph-view .tabs .tab .options-block > div {
+.shader-editor #rightPanel .options-block > div {
   border: 1px solid #666;
   padding: 2px;
 }
+.graph-view {
+  outline: none !important;
+  position: relative;
+}
+.graph-view .mini-preview {
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  z-index: 0;
+}
+.graph-view #graph-root {
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  z-index: 1;
+}
 .graph-view #add-menu {
   position: absolute;
   width: 400px;

+ 125 - 118
bin/style.less

@@ -2157,17 +2157,20 @@ input[type=checkbox] {
 
 /* Shader Editor */
 .shader-editor {
+	display: flex;
+	flex-direction: row;
+
 	#preview {
 		z-index: 3;
 		position: absolute;
-
+		
 		width: 300px;
 		height: 300px;
 
 		background-color: #111;
-		   border: 1px solid #444;
+		border: 1px solid #444;
 
-		right: 290px;
+		right: 35px;
 		bottom: 35px;
 
 		.hide-toolbar2 {
@@ -2176,30 +2179,18 @@ input[type=checkbox] {
 			top: 8px;
 		}
 	}
-}
 
-.graph-view {
-	outline: none !important;
-
-	.mini-preview {
-		position: absolute;
-		top: 0px;
-		left: 0px;
-		z-index: 0;
+	.flex.vertical {
+		position:relative;
 	}
 
-	#graph-root {
-		position: absolute;
-		top: 0px;
-		left: 0px;
-		z-index: 0;
-	}
+	#rightPanel {
+		flex: 0;
+		min-width: 270px;
 
-	.tabs {
 		width: 280px;
 		padding-top: 10px;
 		border-left: 1px solid #444444;
-		z-index: @default-layer + 5;
     	background: #222222;
 		height: 100%;
 		user-select: none;
@@ -2210,130 +2201,146 @@ input[type=checkbox] {
 			font-weight: bold;
 		}
 
+		height: 100%;
+		@options-height: max(250px, 25%);
+		.hide-block {
+			height: 600px;
 
+			#parametersList {
+				height: 100%;
 
-		.tab {
-			height: 100%;
-			@options-height: max(250px, 25%);
-			.hide-block {
-				height: 600px;
-
-				#parametersList {
-					height: 100%;
-
-					.parameter {
-						border: 1px solid;
-						margin: 5px;
-						background-color: #222;
-						position: relative;
-
-						&.hovertop:before, &.hoverbot:after {
-							display: block;
-							position: absolute;
-							z-index: 100;
-							margin: 0 auto;
-							width: 100%;
-							content: "";
-						}
+				.parameter {
+					border: 1px solid;
+					margin: 5px;
+					background-color: #222;
+					position: relative;
 
-						&:before {
-							border-top: 5px solid red;
-							top: -10px;
-						}
+					&.hovertop:before, &.hoverbot:after {
+						display: block;
+						position: absolute;
+						z-index: 100;
+						margin: 0 auto;
+						width: 100%;
+						content: "";
+					}
 
-						&:after {
-							border-bottom: 5px solid red;
-							bottom: -10px;
-						}
+					&:before {
+						border-top: 5px solid red;
+						top: -10px;
+					}
 
+					&:after {
+						border-bottom: 5px solid red;
+						bottom: -10px;
+					}
 
-						.header {
-							background-color: #d6d6d6;
-							height: 20px;
-							padding: 5px;
-							color: black;
-							cursor: pointer;
 
-							.title {
-								float: left;
-								input {
-									width: 130px;
-								}
+					.header {
+						background-color: #d6d6d6;
+						height: 20px;
+						padding: 5px;
+						color: black;
+						cursor: pointer;
+
+						.title {
+							float: left;
+							input {
+								width: 130px;
 							}
+						}
 
-							.type {
-								float: right;
+						.type {
+							float: right;
 
-								span {
-									color: black;
-									font-style: italic;
-									font-size: 13px;
-									padding-right: 5px;
-								}
+							span {
+								color: black;
+								font-style: italic;
+								font-size: 13px;
+								padding-right: 5px;
 							}
 						}
+					}
 
-						.content {
-							padding: 4px;
+					.content {
+						padding: 4px;
 
-							>div {
-								margin-top: 2px;
-							}
+						>div {
+							margin-top: 2px;
 						}
+					}
 
-						/*.content {
-							background-color: #b3b3b3;
-							padding: 5px;
-							box-shadow: inset 0px 13px 6px -15px black;
-
-							div {
-								width: 100%;
-								height: 20px;
-
-								span {
-									float: left;
-									color: black;
-									font-size: 13px;
-									padding-right: 5px;
-									font-weight: normal;
-								}
-							}
-							.texture-preview {
-								background-repeat: no-repeat;
-								background-size: 20px 20px!important;
-								border: 2px #444444 solid;
-								width: 20px;
+					/*.content {
+						background-color: #b3b3b3;
+						padding: 5px;
+						box-shadow: inset 0px 13px 6px -15px black;
+
+						div {
+							width: 100%;
+							height: 20px;
+
+							span {
+								float: left;
+								color: black;
+								font-size: 13px;
+								padding-right: 5px;
+								font-weight: normal;
 							}
-							.action-btns {
-								input {
-									float: right;
-								}
+						}
+						.texture-preview {
+							background-repeat: no-repeat;
+							background-size: 20px 20px!important;
+							border: 2px #444444 solid;
+							width: 20px;
+						}
+						.action-btns {
+							input {
+								float: right;
 							}
-						}*/
-
-						& > span {
-							font-size: 12px;
 						}
+					}*/
+
+					& > span {
+						font-size: 12px;
 					}
 				}
 			}
-			.options-block {
-				height: @options-height;
-				& > * {
-					display: block;
-					margin-bottom: 10px;
-					width: 100%;
-					text-align: center;
-					box-sizing: border-box;
-				}
+		}
+		.options-block {
+			height: @options-height;
+			& > * {
+				display: block;
+				margin-bottom: 10px;
+				width: 100%;
+				text-align: center;
+				box-sizing: border-box;
+			}
 
-				& > div {
-					border: 1px solid #666;
-					padding: 2px;
-				}
+			& > div {
+				border: 1px solid #666;
+				padding: 2px;
 			}
 		}
 	}
+}
+
+.graph-view {
+	outline: none !important;
+	position: relative;
+
+	.mini-preview {
+		position: absolute;
+		top: 0px;
+		left: 0px;
+		z-index: 0;
+	}
+
+	#graph-root {
+		position: absolute;
+		top: 0px;
+		left: 0px;
+		z-index: 1;
+	}
+
 	#add-menu {
 		position: absolute;
 		width: 400px;

+ 18 - 38
hide/view/GraphEditor.hx

@@ -29,9 +29,6 @@ class GraphEditor extends hide.comp.Component {
 	var heapsScene : JQuery;
 	var editorDisplay : SVG;
 	var editorMatrix : JQuery;
-	var statusBar : JQuery;
-	var statusClose : JQuery;
-
 	public var config : hide.Config;
 
 
@@ -77,7 +74,7 @@ class GraphEditor extends hide.comp.Component {
 	var lastCurveX : Float = 0;
 	var lastCurveY : Float = 0;
 
-	var currentUndoBuffer : UndoBuffer = [];
+	public var currentUndoBuffer : UndoBuffer = [];
 
 
 
@@ -91,8 +88,6 @@ class GraphEditor extends hide.comp.Component {
 			<div class="flex-elt graph-view" tabindex="0" >
 				<div class="heaps-scene" tabindex="1" >
 				</div>
-				<div id="rightPanel" class="tabs" >
-				</div>
 			</div>
 		</div>'));
 		this.config = config;
@@ -129,15 +124,7 @@ class GraphEditor extends hide.comp.Component {
 		heapsScene = element.find(".heaps-scene");
 		editorDisplay = new SVG(heapsScene);
 		editorDisplay.element.attr("id", "graph-root");
-		var status = new Element('<div id="status-bar" ><div id="close">-- close --</div><pre></pre></div>');
-		statusBar = status.appendTo(heapsScene).find("pre");
-		statusClose = status.find("#close");
-		statusClose.hide();
-		statusClose.on("click", function(e) {
-			statusBar.html("");
-			statusClose.hide();
-		});
-		statusBar.on("wheel", (e) -> { e.stopPropagation(); });
+
 
 		editorMatrix = editorDisplay.group(editorDisplay.element);
 
@@ -218,7 +205,7 @@ class GraphEditor extends hide.comp.Component {
 				if (recSelection != null) {
 					recSelection.remove();
 					recSelection = null;
-					
+
 					var save : SelectionUndoSave = undoSave;
 
 					for (id => _ in save.newSelections) {
@@ -391,8 +378,9 @@ class GraphEditor extends hide.comp.Component {
 
 	function openAddMenu(x : Int = 0, y : Int = 0) {
 
-		var boundsWidth = Std.parseInt(element.css("width"));
-		var boundsHeight = Std.parseInt(element.css("height"));
+		var boundsWidth = Std.int(element.width());
+		var boundsHeight = Std.int(element.height());
+		trace(boundsHeight);
 
 		var posCursor = new IPoint(Std.int(ide.mouseX - heapsScene.offset().left) + x, Std.int(ide.mouseY - heapsScene.offset().top) + y);
 		if( posCursor.x < 0 )
@@ -415,6 +403,9 @@ class GraphEditor extends hide.comp.Component {
 
 			addMenu.css("left", posCursor.x);
 			addMenu.css("top", posCursor.y);
+
+			trace(posCursor);
+
 			for (c in addMenu.find("#results").children().elements()) {
 				c.show();
 			}
@@ -798,7 +789,7 @@ class GraphEditor extends hide.comp.Component {
 		return {nodeFromId: output.nodeId, outputFromId: output.ioId, nodeToId: input.nodeId, inputToId: input.ioId};
 	}
 
-	function opBox(node: IGraphNode, doAdd: Bool, undoBuffer: UndoBuffer) : Void {
+	public function opBox(node: IGraphNode, doAdd: Bool, undoBuffer: UndoBuffer) : Void {
 		var exec = function(isUndo : Bool) : Void {
 			if (!doAdd) isUndo = !isUndo;
 			if (!isUndo) {
@@ -1072,22 +1063,11 @@ class GraphEditor extends hide.comp.Component {
 	}*/
 
 	function error(str : String, ?idBox : Int) {
-		statusBar.html(str);
-		statusClose.show();
-		statusBar.addClass("error");
-
-		new Element(".box").removeClass("error");
-		if (idBox != null) {
-			var elt = new Element('#${idBox}');
-			elt.addClass("error");
-		}
+		Ide.inst.quickError(str);
 	}
 
 	function info(str : String) {
-		statusBar.html(str);
-		statusClose.show();
-		statusBar.removeClass("error");
-		new Element(".box").removeClass("error");
+		Ide.inst.quickMessage(str);
 	}
 
 	/*function createEdgeInEditorGraph(edge) {
@@ -1422,26 +1402,26 @@ class GraphEditor extends hide.comp.Component {
 		var dy = Math.max(Math.abs(y - (element.offset().top + element.height() / 2)) - element.height() / 2, 0);
 		return dx * dx + dy * dy;
 	}
-	function gX(x : Float) : Float {
+	public function gX(x : Float) : Float {
 		return x*transformMatrix[0] + transformMatrix[4];
 	}
-	function gY(y : Float) : Float {
+	public function gY(y : Float) : Float {
 		return y*transformMatrix[3] + transformMatrix[5];
 	}
-	function gPos(x : Float, y : Float) : Point {
+	public function gPos(x : Float, y : Float) : Point {
 		return new Point(gX(x), gY(y));
 	}
-	function lX(x : Float) : Float {
+	public function lX(x : Float) : Float {
 		var screenOffset = editorDisplay.element.offset();
 		x -= screenOffset.left;
 		return (x - transformMatrix[4])/transformMatrix[0];
 	}
-	function lY(y : Float) : Float {
+	public function lY(y : Float) : Float {
 		var screenOffset = editorDisplay.element.offset();
 		y -= screenOffset.top;
 		return (y - transformMatrix[5])/transformMatrix[3];
 	}
-	function lPos(x : Float, y : Float) : Point {
+	public function lPos(x : Float, y : Float) : Point {
 		return new Point(lX(x), lY(y));
 	}
 

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

@@ -39,6 +39,7 @@ class PreviewShaderBase extends hxsl.Shader {
 
 		@global var global : {
 			var time : Float;
+			var pixelSize : Vec2;
 		};
 
 		@global var camera : {
@@ -138,12 +139,17 @@ class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEd
 	var meshPreviewPrefab : hrt.prefab.Prefab;
 	var meshPreviewprefabWatch : hide.tools.FileWatcher.FileWatchEvent;
 
+	var parametersList : JQuery;
+	var draggedParamId : Int;
+	
+
 	var defaultLight : hrt.prefab.Light;
 
 	var queueReloadMesh = false;
 	
 	override function onDisplay() {
 		super.onDisplay();
+		element.html("");
 		loadSettings();
 		element.addClass("shader-editor");
  		shaderGraph = cast hide.Ide.inst.loadPrefab(state.path, null,  true);
@@ -155,12 +161,394 @@ class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEd
 		graphEditor = new hide.view.GraphEditor(config, this, this.element);
 		graphEditor.onDisplay();
 
+		graphEditor.element.on("drop" ,function(e) {
+			var posCursor = new Point(graphEditor.lX(ide.mouseX - 25), graphEditor.lY(ide.mouseY - 10));
+			var inst = new ShaderParam();
+			@:privateAccess var id = currentGraph.current_node_id++;
+			inst.id = id;
+			inst.parameterId = draggedParamId;
+			inst.variable = shaderGraph.getParameter(inst.parameterId).variable;
+
+			graphEditor.opBox(inst, true, graphEditor.currentUndoBuffer);
+			graphEditor.commitUndo();
+			// var node = Std.downcast(currentGraph.addNode(posCursor.x, posCursor.y, ShaderParam, []), ShaderParam);
+			// node.parameterId = draggedParamId;
+			// var paramShader = shaderGraph.getParameter(draggedParamId);
+			// node.variable = paramShader.variable;
+			// node.setName(paramShader.name);
+			//setDisplayValue(node, paramShader.type, paramShader.defaultValue);
+			//addBox(posCursor, ShaderParam, node);
+		});
+
+		var rightPannel = new Element(
+			'<div id="rightPanel">
+				<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="createParameter" type="button" value="Add parameter" />
+						<select id="domainSelection"></select>
+						<input id="launchCompileShader" type="button" value="Compile shader" />
+
+						<input id="saveShader" type="button" value="Save" />
+						<div>
+							<input id="changeModel" type="button" value="Change Model" />
+							<input id="removeModel" type="button" value="Remove Model" />
+						</div>
+						<input id="centerView" type="button" value="Center Graph" />
+						<div>
+							Display Compiled
+							<input id="displayHxsl" type="button" value="Hxsl" />
+							<input id="displayGlsl" type="button" value="Glsl" />
+							<input id="displayHlsl" type="button" value="Hlsl" />
+							<input id="display2" type="button" value="2" />
+						</div>
+						<input id="togglelight" type="button" value="Toggle Default Lights" />
+						<input id="refreshGraph" type="button" value="Refresh Shader Graph" />
+					</div>
+				</div>
+			</div>'
+		);
+
+		rightPannel.appendTo(element);
+
+		var newParamCtxMenu : Array<hide.comp.ContextMenu.ContextMenuItem> = [
+			{ label : "Number", click : () -> createParameter(TFloat) },
+			{ label : "Vec2", click : () -> createParameter(TVec(2, VFloat)) },
+			{ label : "Vec3", click : () -> createParameter(TVec(3, VFloat)) },
+			{ label : "Color", click : () -> createParameter(TVec(4, VFloat)) },
+			{ label : "Texture", click : () -> createParameter(TSampler(T2D,false)) },
+		];
+
+		rightPannel.find("#createParameter").on("click", function() {
+			new hide.comp.ContextMenu(newParamCtxMenu);
+		});
+
+		parametersList = rightPannel.find("#parametersList");
+		parametersList.on("contextmenu", function(e) {
+			e.preventDefault();
+			e.stopPropagation();
+			new hide.comp.ContextMenu([
+				{
+					label : "Add Parameter",
+					menu : newParamCtxMenu,
+				},
+			]);
+		});
+
+		for (k in shaderGraph.parametersKeys) {
+			var pElt = addParameter(shaderGraph.parametersAvailable.get(k), shaderGraph.parametersAvailable.get(k).defaultValue);
+		}
+
+		rightPannel.find("#display2").click((e) -> {
+			trace(hxsl.Printer.shaderToString(shaderGraph.compile(Fragment).shader.data, true));
+		});
+
+
 		graphEditor.onPreviewUpdate = onPreviewUpdate;
 		graphEditor.onNodePreviewUpdate = onNodePreviewUpdate;
 
 		initMeshPreview();
 	}
 
+	function createParameter(type : Type) {
+		//beforeChange();
+		var paramShaderID = shaderGraph.addParameter(type);
+		//afterChange();
+		var paramShader = shaderGraph.getParameter(paramShaderID);
+
+		var elt = addParameter(paramShader, null);
+		//updateParam(paramShaderID);
+
+		elt.find(".input-title").focus();
+	}
+
+	function moveParameter(parameter : Parameter, up : Bool) {
+		var parameterElt = parametersList.find("#param_" + parameter.id);
+		var parameterPrev = shaderGraph.parametersAvailable.get(shaderGraph.parametersKeys[shaderGraph.parametersKeys.indexOf(parameter.id) + (up? -1 : 1)]);
+		var parameterPrevElt = parametersList.find("#param_" + parameterPrev.id);
+		if (up)
+			parameterElt.insertBefore(parameterPrevElt);
+		else
+			parameterElt.insertAfter(parameterPrevElt);
+		shaderGraph.parametersKeys.remove(parameter.id);
+		shaderGraph.parametersKeys.insert(shaderGraph.parametersKeys.indexOf(parameterPrev.id) + (up? 0 : 1), parameter.id);
+		shaderGraph.checkParameterIndex();
+	}
+
+	// function updateParam(id : Int) {
+	// 	var param = shaderGraph.getParameter(id);
+	// 	setParamValueByName(currentShader, param.name, param.defaultValue);
+	// 	//previewParamDirty = true;
+	// }
+
+	function addParameter(parameter : Parameter, ?value : Dynamic) {
+
+		var elt = new Element('<div id="param_${parameter.id}" class="parameter" draggable="true" ></div>').appendTo(parametersList);
+		elt.on("click", function(e) {e.stopPropagation();});
+		elt.on("contextmenu", function(e) {
+			var elements = [];
+			e.stopPropagation();
+			var newCtxMenu : Array<hide.comp.ContextMenu.ContextMenuItem> = [
+				{ label : "Move up", click : () -> {
+					//beforeChange();
+					moveParameter(parameter, true);
+					//afterChange();
+				}, enabled: shaderGraph.parametersKeys.indexOf(parameter.id) > 0},
+				{ label : "Move down", click : () -> {
+					//beforeChange();
+					moveParameter(parameter, false);
+					//afterChange();
+				}, enabled: shaderGraph.parametersKeys.indexOf(parameter.id) < shaderGraph.parametersKeys.length-1}
+			];
+			new hide.comp.ContextMenu(newCtxMenu);
+			e.preventDefault();
+
+		});
+		var content = new Element('<div class="content" ></div>');
+		content.hide();
+		var defaultValue = new Element("<div><span>Default: </span></div>").appendTo(content);
+
+		var typeName = "";
+		switch(parameter.type) {
+			case TFloat:
+				var parentRange = new Element('<input type="range" min="-1" max="1" />').appendTo(defaultValue);
+				var range = new hide.comp.Range(null, parentRange);
+				var rangeInput = @:privateAccess range.f;
+				rangeInput.on("mousedown", function(e) {
+					elt.attr("draggable", "false");
+					//beforeChange();
+				});
+				rangeInput.on("mouseup", function(e) {
+					elt.attr("draggable", "true");
+					//afterChange();
+				});
+				if (value == null) value = 0;
+				range.value = value;
+				shaderGraph.setParameterDefaultValue(parameter.id, value);
+				range.onChange = function(moving) {
+					if (!shaderGraph.setParameterDefaultValue(parameter.id, range.value))
+						return;
+					//setBoxesParam(parameter.id);
+					//updateParam(parameter.id);
+				};
+				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.ColorBox(null, parentPicker, true, true);
+
+
+				if (value == null)
+					value = [0, 0, 0, 1];
+				var start : h3d.Vector = h3d.Vector.fromArray(value);
+				shaderGraph.setParameterDefaultValue(parameter.id, value);
+				picker.value = start.toColor();
+				picker.onChange = function(move) {
+					var vecColor = h3d.Vector4.fromColor(picker.value);
+					if (!shaderGraph.setParameterDefaultValue(parameter.id, [vecColor.x, vecColor.y, vecColor.z, vecColor.w]))
+						return;
+					//setBoxesParam(parameter.id);
+					//updateParam(parameter.id);
+				};
+			case TVec(n, VFloat):
+				if (value == null)
+					value = [for (i in 0...n) 0.0];
+
+				shaderGraph.setParameterDefaultValue(parameter.id, value);
+				//var row = new Element('<div class="flex"/>').appendTo(defaultValue);
+
+				for( i in 0...n ) {
+					var parentRange = new Element('<input type="range" min="-1" max="1" />').appendTo(defaultValue);
+					var range = new hide.comp.Range(null, parentRange);
+					range.value = value[i];
+
+					var rangeInput = @:privateAccess range.f;
+					rangeInput.on("mousedown", function(e) {
+						elt.attr("draggable", "false");
+						//beforeChange();
+					});
+					rangeInput.on("mouseup", function(e) {
+						elt.attr("draggable", "true");
+						//afterChange();
+					});
+
+					range.onChange = function(move) {
+						value[i] = range.value;
+						if (!shaderGraph.setParameterDefaultValue(parameter.id, value))
+							return;
+						//setBoxesParam(parameter.id);
+						//updateParam(parameter.id);
+					};
+					//if(min == null) min = isColor ? 0.0 : -1.0;
+					//if(max == null)	max = 1.0;
+					//e.attr("min", "" + min);
+					//e.attr("max", "" + max);
+				}
+				typeName = "Vec" + n;
+			case TSampler(_):
+				var parentSampler = new Element('<input type="texturepath" field="sampler2d"/>').appendTo(defaultValue);
+
+				var tselect = new hide.comp.TextureChoice(null, parentSampler);
+				tselect.value = value;
+				tselect.onChange = function(undo: Bool) {
+					//beforeChange();
+					if (!shaderGraph.setParameterDefaultValue(parameter.id, tselect.value))
+						return;
+					//afterChange();
+					//setBoxesParam(parameter.id);
+					//updateParam(parameter.id);
+				}
+				typeName = "Texture";
+
+			default:
+		}
+
+		var header = new Element('<div class="header">
+									<div class="title">
+										<i class="ico ico-chevron-right" ></i>
+										<input class="input-title" type="input" value="${parameter.name}" />
+									</div>
+									<div class="type">
+										<span>${typeName}</span>
+									</div>
+								</div>');
+
+		var internal = new Element('<div><input type="checkbox" name="internal" id="internal"></input><label for="internal">Internal</label><div>').appendTo(content).find("#internal");
+		internal.prop("checked", parameter.internal ?? false);
+
+		internal.on('change', function(e) {
+			//beforeChange();
+			parameter.internal = internal.prop("checked");
+			//afterChange();
+		});
+
+		var perInstanceCb = new Element('<div><input type="checkbox" name="perinstance"/><label for="perinstance">Per instance</label><div>');
+		var shaderParams : Array<ShaderParam> = [];
+		// for (b in listOfBoxes) {
+		// 	var tmpShaderParam = Std.downcast(b.getInstance(), ShaderParam);
+		// 	if (tmpShaderParam != null && tmpShaderParam.parameterId == parameter.id) {
+		// 		shaderParams.push(tmpShaderParam);
+		// 		break;
+		// 	}
+		// }
+
+		var checkbox = perInstanceCb.find("input");
+		if (shaderParams.length > 0)
+			checkbox.prop("checked", shaderParams[0].perInstance);
+		checkbox.on("change", function() {
+			//beforeChange();
+			var checked : Bool = checkbox.prop("checked");
+			for (shaderParam in shaderParams)
+				shaderParam.perInstance = checked;
+			//afterChange();
+			requestRecompile();
+		});
+		perInstanceCb.appendTo(content);
+
+		header.appendTo(elt);
+		content.appendTo(elt);
+		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.downcast(b.getInstance(), ShaderParam);
+				if (shaderParam != null && shaderParam.parameterId == parameter.id) {
+					error("This parameter is used in the graph.");
+					return;
+				}
+			}
+			beforeChange();
+			shaderGraph.removeParameter(parameter.id);
+			afterChange();
+			elt.remove();
+		});*/
+		deleteBtn.appendTo(actionBtns);
+
+
+
+		var inputTitle = elt.find(".input-title");
+		inputTitle.on("click", function(e) {
+			e.stopPropagation();
+		});
+		inputTitle.on("keydown", function(e) {
+			e.stopPropagation();
+		});
+		inputTitle.on("change", function(e) {
+			var newName = inputTitle.val();
+			// if (shaderGraph.setParameterTitle(parameter.id, newName)) {
+			// 	for (b in listOfBoxes) {
+			// 		var shaderParam = Std.downcast(b.getInstance(), ShaderParam);
+			// 		if (shaderParam != null && shaderParam.parameterId == parameter.id) {
+			// 			beforeChange();
+			// 			shaderParam.setName(newName);
+			// 			afterChange();
+			// 		}
+			// 	}
+			// }
+		});
+		inputTitle.on("focus", function() { inputTitle.select(); } );
+
+		// elt.find(".header").on("click", function() {
+		// 	toggleParameter(elt);
+		// });
+
+		elt.on("dragstart", function(e) {
+			draggedParamId = parameter.id;
+		});
+
+		inline function isAfter(e) {
+			return e.clientY > (elt.offset().top + elt.outerHeight() / 2.0);
+		}
+
+		elt.on("dragover", function(e : js.jquery.Event) {
+			var after = isAfter(e);
+			elt.toggleClass("hovertop", !after);
+			elt.toggleClass("hoverbot", after);
+			e.preventDefault();
+		});
+
+		elt.on("dragleave", function(e) {
+			elt.toggleClass("hovertop", false);
+			elt.toggleClass("hoverbot", false);
+		});
+
+		elt.on("dragenter", function(e) {
+			e.preventDefault();
+		});
+
+		elt.on("drop", function(e) {
+			elt.toggleClass("hovertop", false);
+			elt.toggleClass("hoverbot", false);
+			var other = shaderGraph.getParameter(draggedParamId);
+			var after = isAfter(e);
+			moveParameterTo(other, parameter, after);
+		});
+
+		return elt;
+	}
+
+	function moveParameterTo(paramA: Parameter, paramB: Parameter, after: Bool) {
+		if (paramA == paramB)
+			return;
+		var aElt = parametersList.find("#param_" + paramA.id);
+		var bElt = parametersList.find("#param_" + paramB.id);
+
+		if (!after) {
+			aElt.insertBefore(bElt);
+		} else {
+			aElt.insertAfter(bElt);
+		}
+
+		shaderGraph.parametersKeys.remove(paramA.id);
+		shaderGraph.parametersKeys.insert(shaderGraph.parametersKeys.indexOf(paramB.id)+ (after ? 1 : 0) , paramA.id);
+
+		shaderGraph.checkParameterIndex();
+	}
+
+
 	public function loadSettings() {
 		var save = haxe.Json.parse(getDisplayState("previewSettings") ?? "{}");
 		previewSettings = new PreviewSettings();
@@ -180,7 +568,7 @@ class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEd
 		if (meshPreviewScene != null) {
 			meshPreviewScene.element.remove();
 		}
-		var container = new Element('<div id="preview"></div>').appendTo(element);
+		var container = new Element('<div id="preview"></div>').appendTo(graphEditor.element);
 		meshPreviewScene = new hide.comp.Scene(config, null, container);
 		meshPreviewScene.onReady = onMeshPreviewReady;
 		meshPreviewScene.onUpdate = onMeshPreviewUpdate;
@@ -392,6 +780,9 @@ class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEd
 	}
 
 	public function replaceMeshShader(mesh: h3d.scene.Mesh, newShader: hxsl.DynamicShader) {
+		if (newShader == null)
+			return;
+
 		for (m in mesh.getMaterials()) {
 			var found = false;
 
@@ -441,6 +832,13 @@ class ShaderEditor extends hide.view.FileView implements GraphInterface.IGraphEd
 			compileShader();
 		}
 
+		@:privateAccess
+		{
+			var engine = graphEditor.previewsScene.engine;
+			var t = engine.getCurrentTarget();
+			graphEditor.previewsScene.s2d.ctx.globals.set("global.pixelSize", new h3d.Vector(2 / (t == null ? engine.width : t.width), 2 / (t == null ? engine.height : t.height)));	
+		}
+
 		@:privateAccess
 		if (meshPreviewScene.s3d != null) {
 			meshPreviewScene.s3d.renderer.ctx.time = graphEditor.previewsScene.s3d.renderer.ctx.time;

+ 10 - 9
hrt/shgraph/Random.hx

@@ -1,7 +1,7 @@
 package hrt.shgraph;
 
 @name("Random")
-@description("Generate a random value between min and max using the given seed")
+@description("[CURRENTLY BROKEN] Generate a random value between min and max using the given seed")
 @group("Channel")
 class Random extends ShaderNodeHxsl {
 
@@ -11,16 +11,17 @@ class Random extends ShaderNodeHxsl {
 		@sginput(1.0) var max : Float;
 		@sgoutput var output : Float;
 
-		function pcg(v : Int) : Int
-		{
-			var state : Int = v * 0x2C9277B5 + 0xAC564B05;
-			var word = ((state >>> ((state >>> 28) + 4)) ^ state) * 0x108EF2D9;
-			return (word >>> 22) ^ word;
-		}
+		// shadernodeHsxl support for other functions is currently broken
+		// function pcg(v : Int) : Int
+		// {
+		// 	var state : Int = v * 0x2C9277B5 + 0xAC564B05;
+		// 	var word = ((state >>> ((state >>> 28) + 4)) ^ state) * 0x108EF2D9;
+		// 	return (word >>> 22) ^ word;
+		// }
 
 		function fragment() {
-			var rand = pcg(pcg(int(seed.x)) + int(seed.y));
-			output = float(rand & 0xFFFF)/float(0xFFFF) * (max-min) + min;
+			//var rand = pcg(pcg(int(seed.x)) + int(seed.y));
+			output = 0.0;
 		}
 	}
 }

+ 1 - 0
hrt/shgraph/ShaderGlobalInput.hx

@@ -68,6 +68,7 @@ class ShaderGlobalInput extends ShaderNode {
 			var value = input.val();
 			outputs = null;
 			this.variableIdx = value;
+			requestRecompile();
 		});
 
 		elements.push(element);

+ 1 - 0
hrt/shgraph/ShaderInput.hx

@@ -109,6 +109,7 @@ class ShaderInput extends ShaderNode {
 		input.on("change", function(e) {
 			variable = input.val();
 			outputs = null;
+			requestRecompile();
 		});
 
 		elements.push(element);

+ 4 - 0
hrt/shgraph/ShaderNode.hx

@@ -118,6 +118,10 @@ implements hide.view.GraphInterface.IGraphNode
 
 	public function setDefaultParam(name: String, value: String) {
 		Reflect.setField(defaults, name, Std.parseFloat(value));
+		requestRecompile();
+	}
+
+	public function requestRecompile() {
 		Std.downcast(editor.editor, hide.view.shadereditor.ShaderEditor)?.requestRecompile();
 	}
 	#end

+ 1 - 0
hrt/shgraph/ShaderOutput.hx

@@ -94,6 +94,7 @@ class ShaderOutput extends ShaderNode {
 		input.on("change", function(e) {
 			variable = input.val();
 			inputs = null;
+			requestRecompile();
 		});
 
 		elements.push(element);

+ 4 - 2
hrt/shgraph/ShaderParam.hx

@@ -6,11 +6,13 @@ using hxsl.Ast;
 @width(120)
 @color("#d6d6d6")
 class ShaderParam extends ShaderNode {
-
-
 	@prop() public var parameterId : Int;
 	@prop() public var perInstance : Bool;
 
+	public function new() {
+		
+	}
+
 	override function getOutputs() : Array<ShaderNode.OutputInfo> {
 		var t = switch(variable.type) {
 			case TFloat: