Ver código fonte

more inspect support

ncannasse 10 anos atrás
pai
commit
92c5c04865
3 arquivos alterados com 293 adições e 38 exclusões
  1. 213 35
      hxd/net/CdbInspector.hx
  2. 43 1
      hxd/net/inspect.css
  3. 37 2
      hxd/net/inspect.hss

+ 213 - 35
hxd/net/CdbInspector.hx

@@ -10,6 +10,8 @@ enum Property {
 	PColor( name : String, hasAlpha : Bool, get : Void -> h3d.Vector, set : h3d.Vector -> Void );
 	PGroup( name : String, props : Array<Property> );
 	PTexture( name : String, get : Void -> h3d.mat.Texture, set : h3d.mat.Texture -> Void );
+	PFloats( name : String, get : Void -> Array<Float>, set : Array<Float> -> Void );
+	PPopup( p : Property, menu : Array<String>, click : JQuery -> Int -> Void );
 }
 
 private class CdbEvent implements h3d.IDrawable {
@@ -28,6 +30,8 @@ private class SceneObject {
 	public var j : cdb.jq.JQuery;
 	public var jchild : cdb.jq.JQuery;
 	public var childs : Array<SceneObject>;
+	public var visible = true;
+	public var culled = false;
 	public function new(o, p) {
 		this.o = o;
 		this.parent = p;
@@ -83,15 +87,15 @@ class CdbInspector extends cdb.jq.Client {
 			}
 		}
 		connect();
-		/*oldLog = haxe.Log.trace;
-		haxe.Log.trace = onTrace;*/
+		oldLog = haxe.Log.trace;
+		haxe.Log.trace = onTrace;
 	}
 
 	function onTrace( v : Dynamic, ?pos : haxe.PosInfos ) {
 		if( !connected )
 			oldLog(v, pos);
 		else {
-			J("<div>").addClass("line").text(pos.fileName+"(" + pos.lineNumber + ") : " + Std.string(v)).appendTo(J("#log"));
+			J("<pre>").addClass("line").text(pos.fileName+"(" + pos.lineNumber + ") : " + Std.string(v)).appendTo(J("#log"));
 		}
 	}
 
@@ -125,12 +129,13 @@ class CdbInspector extends cdb.jq.Client {
 	}
 
 	function refresh() {
+		sceneObjects = [];
 		j.html('
 			<div id="scene" class="panel" caption="Scene">
 				<ul id="scontent" class="elt">
 				</ul>
 			</div>
-			<div id="material" class="panel" caption="Material">
+			<div id="props" class="panel" caption="Properties">
 			</div>
 			<div id="log" class="panel" caption="Log">
 			</div>
@@ -139,7 +144,7 @@ class CdbInspector extends cdb.jq.Client {
 		var scene = J("#scene");
 		scene.dock(root, Left, 0.2);
 		J("#log").dock(root, Down, 0.3);
-		J("#material").dock(scene.get(), Down, 0.5);
+		J("#props").dock(scene.get(), Down, 0.5);
 	}
 
 	public function sync() {
@@ -154,7 +159,26 @@ class CdbInspector extends cdb.jq.Client {
 			so = new SceneObject(o, p);
 			sceneObjects.insert(scenePosition, so);
 			so.j = J("<li>");
-			so.j.html('<div class="content">${o.toString()}</div>');
+			var icon = null;
+			if( Std.is(o, h3d.scene.Skin) )
+				icon = "child"
+			else if( Std.is(o, h3d.scene.Mesh) )
+				icon = "cube";
+			else if( Std.is(o, h3d.scene.CustomObject) )
+				icon = "globe";
+			else if( Std.is(o, h3d.scene.Scene) )
+				icon = "picture-o";
+			else if( Std.is(o, h3d.scene.Light) )
+				icon = "lightbulb-o";
+			else
+				icon = "circle-o";
+			so.j.html('<i class="fa fa-$icon"></i><div class="content">${o.name == null ? o.toString() : o.name}</div>');
+			so.j.find("i").click(function(_) {
+				if( o.numChildren > 0 ) {
+					so.j.toggleClass("expand");
+					so.jchild.slideToggle(50);
+				}
+			});
 			so.j.find(".content").click(function(_) {
 				J("#scene").find(".selected").removeClass("selected");
 				so.j.addClass("selected");
@@ -163,6 +187,15 @@ class CdbInspector extends cdb.jq.Client {
 			so.j.appendTo( p != null ? p.jchild : J("#scontent") );
 			if( p != null ) p.childs.push(so);
 		}
+		if( o.visible != so.visible ) {
+			so.visible = o.visible;
+			so.j.toggleClass("hidden");
+		}
+		@:privateAccess if( o.culled != so.culled ) {
+			so.culled = o.culled;
+			so.j.toggleClass("culled");
+		}
+
 		scenePosition++;
 		if( o.numChildren > 0 ) {
 			if( so.jchild == null ) {
@@ -180,20 +213,33 @@ class CdbInspector extends cdb.jq.Client {
 		}
 	}
 
-	function makeProps( props : Array<Property> ) {
+	function makeProps( props : Array<Property>, expandLevel = 1 ) {
 		var t = J("<table>");
 		t.addClass("props");
 		for( p in props )
-			addProp(t, p, 0);
+			addProp(t, p, [], expandLevel);
 		return t;
 	}
 
-	function addProp( t : JQuery, p : Property, gid : Int ) {
+	public function createPanel( name : String ) {
+		var panel = J('<div>');
+		panel.addClass("panel");
+		panel.attr("caption", ""+name);
+		panel.appendTo(j);
+		panel.dock(root, Fill);
+		return panel;
+	}
+
+	function addProp( t : JQuery, p : Property, gids : Array<Int>, expandLevel ) {
 		var j = J("<tr>");
 		j.addClass("prop");
-		j.addClass("g_" + gid);
+		for( g in gids )
+			j.addClass("g_" + g);
 		j.addClass(p.getName().toLowerCase());
-		if( gid > 0 ) j.style("display", "none");
+		if( gids.length > expandLevel )
+			j.style("display", "none");
+		if( gids.length > 0 )
+			j.addClass("gs_" + gids[gids.length - 1]);
 		j.appendTo(t);
 
 		var jname = J("<th>");
@@ -205,17 +251,26 @@ class CdbInspector extends cdb.jq.Client {
 		case PGroup(name, props):
 
 			jname.attr("colspan", "2");
-			jname.html('<i class="icon-arrow-right"/> ' + StringTools.htmlEscape(name));
+			jname.style("padding-left", (gids.length * 16) + "px");
+			jname.html('<i class="fa ' + (gids.length + 1 > expandLevel ? 'fa-arrow-right' : 'fa-arrow-down') +'"/> ' + StringTools.htmlEscape(name));
 			var gid = t.get().childs.length;
 			j.click(function(_) {
 				var i = jname.find("i");
-				var show = i.hasClass("icon-arrow-right");
-				i.attr("class", show ? "icon-arrow-down" : "icon-arrow-right");
-				t.find(".g_" + gid).style("display", show?"":"none");
+				var show = i.hasClass("fa-arrow-right");
+				i.attr("class", "fa "+(show ? "fa-arrow-down" : "fa-arrow-right"));
+				if( show )
+					t.find(".gs_" + gid).style("display", "");
+				else {
+					var all = t.find(".g_" + gid);
+					all.style("display", "none");
+					all.find("i.fa-arrow-down").attr("class", "fa fa-arrow-right");
+				}
 			});
 			jprop.remove();
+			gids.push(gid);
 			for( p in props )
-				addProp(t, p, gid);
+				addProp(t, p, gids, expandLevel);
+			gids.pop();
 
 		case PBool(name, get, set):
 			jname.text(name);
@@ -260,6 +315,17 @@ class CdbInspector extends cdb.jq.Client {
 			jname.text(name);
 			jprop.text("" + get());
 			j.dblclick(function(_) editValue(jprop, function() return "" + get(), function(s) { var i = Std.parseFloat(s); if( !Math.isNaN(i) ) set(i); } ));
+
+		case PFloats(name, get, set):
+			jname.text(name);
+			var values = get();
+			jprop.html("<table><tr></tr></table>");
+			var jt = jprop.find("tr");
+			for( i in 0...values.length ) {
+				var jv = J("<td>").appendTo(jt);
+				jv.text(""+values[i]);
+				jv.dblclick(function(_) editValue(jv, function() return "" + values[i], function(s) { var f = Std.parseFloat(s); if( !Math.isNaN(f) ) { values[i] = f; set(values); } }));
+			}
 		case PString(name, get, set):
 			jname.text(name);
 			jprop.text("" + get());
@@ -299,12 +365,27 @@ class CdbInspector extends cdb.jq.Client {
 						if( resPath == null ) resPath = "res";
 						path = hxd.File.applicationPath() + resPath + "/" + res.entry.path;
 					}
-				} else if( t.name != null && (t.name.charCodeAt(0) == '/'.code || t.name.charCodeAt(1) == ':'.code) )
+				} else if( t != null && t.name != null && (t.name.charCodeAt(0) == '/'.code || t.name.charCodeAt(1) == ':'.code) )
 					path = t.name;
 
-				if( path == null )
-					jprop.text(""+t);
-				else
+				if( path == null ) {
+					if( t == null )
+						jprop.text("");
+					else {
+						jprop.html(StringTools.htmlEscape("" + t) + " <button>View</button>");
+						jprop.find("button").click(function(_) {
+							var p = createPanel("" + t);
+							p.html("Loading...");
+							haxe.Timer.delay(function() {
+								var bmp = t.captureBitmap();
+								var png = bmp.toPNG();
+								bmp.dispose();
+								var pngBase64 = new haxe.crypto.BaseCode(haxe.io.Bytes.ofString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")).encodeBytes(png).toString();
+								p.html('<img src="data:image/png;base64,$pngBase64" style="background:#696969"/>');
+							},0);
+						});
+					}
+				} else
 					jprop.html('<img src="file://$path"/>');
 			}
 			init();
@@ -322,7 +403,15 @@ class CdbInspector extends cdb.jq.Client {
 
 				});
 			});
+		case PPopup(p, menu, click):
+			j.remove();
+			j = addProp(t, p, gids, expandLevel);
+			j.mousedown(function(e) {
+				if( e.which == 3 )
+					j.special("popupMenu", menu, function(i) click(j,i));
+			});
 		}
+		return j;
 	}
 
 	function editValue( j : JQuery, get : Void -> String, set : String -> Void ) {
@@ -342,7 +431,7 @@ class CdbInspector extends cdb.jq.Client {
 		});
 	}
 
-	function makeShaderProps( s : hxsl.Shader ) {
+	function getShaderProps( s : hxsl.Shader ) {
 		var props = [];
 		var data = @:privateAccess s.shader;
 		for( v in data.data.vars ) {
@@ -365,6 +454,21 @@ class CdbInspector extends cdb.jq.Client {
 					props.push(PColor(v.name, size == 4, function() return Reflect.field(s, name), set));
 				case TSampler2D, TSamplerCube:
 					props.push(PTexture(v.name, function() return Reflect.field(s, name), set));
+				case TVec(size, VFloat):
+					props.push(PFloats(v.name, function() {
+						var v : h3d.Vector = Reflect.field(s, name);
+						var vl = [v.x, v.y];
+						if( size > 2 ) vl.push(v.z);
+						if( size > 3 ) vl.push(v.w);
+						return vl;
+					}, function(vl) {
+						set(new h3d.Vector(vl[0], vl[1], vl[2], vl[3]));
+					}));
+				case TArray(_):
+					props.push(PString(v.name, function() {
+						var a : Array<Dynamic> = Reflect.field(s, name);
+						return a == null ? "NULL" : "(" + a.length + " elements)";
+					}, function(val) {}));
 				default:
 					props.push(PString(v.name, function() return ""+Reflect.field(s,name), function(val) { } ));
 				}
@@ -379,20 +483,18 @@ class CdbInspector extends cdb.jq.Client {
 		return PGroup("shader "+name, props);
 	}
 
-	function selectObject( o : h3d.scene.Object ) {
-
-		if( !o.isMesh() )
-			return;
-
-		var mat = o.toMesh().material;
-		var j = J("#material");
-		j.text("");
-		j.attr("caption", "Material - " + (mat.name == null ? "@" + o.toString() : mat.name));
+	function colorize( code : String ) {
+		code = code.split("\t").join("    ");
+		code = StringTools.htmlEscape(code);
+		code = ~/\b((var)|(function)|(if)|(else)|(for)|(while))\b/g.replace(code, "<span class='kwd'>$1</span>");
+		code = ~/(@[A-Za-z]+)/g.replace(code, "<span class='meta'>$1</span>");
+		return code;
+	}
 
+	function getMaterialProps( mat : h3d.mat.Material ) {
 		var props = [];
-
+		props.push(PString("name", function() return mat.name == null ? "" : mat.name, function(n) mat.name = n == "" ? null : n));
 		for( pass in mat.getPasses() ) {
-
 			var pl = [
 				PBool("Lights", function() return pass.enableLights, function(v) pass.enableLights = v),
 				PEnum("Cull", h3d.mat.Data.Face, function() return pass.culling, function(v) pass.culling = v),
@@ -404,11 +506,87 @@ class CdbInspector extends cdb.jq.Client {
 
 			var shaders = [for( s in pass.getShaders() ) s];
 			shaders.reverse();
-			for( s in shaders )
-				pl.push(makeShaderProps(s));
+			for( index in 0...shaders.length ) {
+				var s = shaders[index];
+				var p = getShaderProps(s);
+				p = PPopup(p, ["Toggle", "View Source"], function(j, i) {
+					switch( i ) {
+					case 0:
+						if( index == 0 ) return; // Don't allow toggle base shader
+						if( !pass.removeShader(s) )
+							pass.addShaderAt(s, shaders.length - (index + 2));
+						j.toggleClass("disable");
+					case 1:
+						var shader = @:privateAccess s.shader;
+						var p = createPanel(shader.data.name+" shader");
+						var toString = hxsl.Printer.shaderToString;
+						var code = toString(shader.data);
+						p.html("<pre class='code'>"+colorize(code)+"</pre>");
+					}
+
+				});
+				pl.push(p);
+			}
 
-			props.push(PGroup("pass "+pass.name,pl));
+			var p = PGroup("pass " + pass.name, pl);
+			p = PPopup(p, ["Toggle", "View Shader"], function(j, i) {
+				switch( i ) {
+				case 0:
+					if( !mat.removePass(pass) )
+						mat.addPass(pass);
+					j.toggleClass("disable");
+				case 1:
+					var p = createPanel(pass.name+" shader");
+
+					var shader = scene.renderer.compileShader(pass);
+					var toString = hxsl.Printer.shaderToString;
+					var code = toString(shader.vertex.data) + "\n\n" + toString(shader.fragment.data);
+					p.html("<pre class='code'>"+colorize(code)+"</pre>");
+				}
+			});
+			props.push(p);
 		}
+		return PGroup("Material",props);
+	}
+
+	function getLightProps( l : h3d.scene.Light ) {
+		var props = [];
+		props.push(PColor("color", false, function() return l.color, function(c) l.color.load(c)));
+		props.push(PInt("priority", function() return l.priority, function(p) l.priority = p));
+		props.push(PBool("enableSpecular", function() return l.enableSpecular, function(b) l.enableSpecular = b));
+		var dl = Std.instance(l, h3d.scene.DirLight);
+		if( dl != null )
+			props.push(PFloats("direction", function() return [dl.direction.x, dl.direction.y, dl.direction.z], function(fl) dl.direction.set(fl[0], fl[1], fl[2])));
+		var pl = Std.instance(l, h3d.scene.PointLight);
+		if( pl != null )
+			props.push(PFloats("params", function() return [pl.params.x, pl.params.y, pl.params.z], function(fl) pl.params.set(fl[0], fl[1], fl[2], fl[3])));
+		return PGroup("Light", props);
+	}
+
+
+	function selectObject( o : h3d.scene.Object ) {
+
+		var props = [];
+
+		props.push(PString("name", function() return o.name == null ? "" : o.name, function(v) o.name = v == "" ? null : v));
+		props.push(PFloat("x", function() return o.x, function(v) o.x = v));
+		props.push(PFloat("y", function() return o.y, function(v) o.y = v));
+		props.push(PFloat("z", function() return o.z, function(v) o.z = v));
+		props.push(PBool("visible", function() return o.visible, function(v) o.visible = v));
+
+		if( o.isMesh() )
+			props.push(getMaterialProps(o.toMesh().material));
+		else {
+			var c = Std.instance(o, h3d.scene.CustomObject);
+			if( c != null )
+				props.push(getMaterialProps(c.material));
+			var l = Std.instance(o, h3d.scene.Light);
+			if( l != null )
+				props.push(getLightProps(l));
+		}
+
+		var j = J("#props");
+		j.text("");
 
 		var t = makeProps(props);
 		t.appendTo(j);

+ 43 - 1
hxd/net/inspect.css

@@ -3,14 +3,29 @@
 	-moz-user-select : none;
 	-webkit-user-select : none;
 }
+.jqpage pre, .dialog-floating pre {
+	user-select : text;
+	-moz-user-select : text;
+	-webkit-user-select : text;
+}
+.jqpage pre .kwd, .dialog-floating pre .kwd {
+	color : #1518FF;
+}
+.jqpage pre .meta, .dialog-floating pre .meta {
+	color : #156018;
+}
 .jqpage .panel, .dialog-floating .panel {
 	overflow : auto;
+	background-color : white;
 }
 .jqpage #log, .dialog-floating #log {
 	font-family : Courier;
 }
 .jqpage #log .line, .dialog-floating #log .line {
 	padding : 1px 3px;
+	user-select : all;
+	-moz-user-select : all;
+	-webkit-user-select : all;
 }
 .jqpage #log .line:nth-child(even), .dialog-floating #log .line:nth-child(even) {
 	background-color : #eee;
@@ -21,15 +36,37 @@
 .jqpage #scene ul.elt li, .dialog-floating #scene ul.elt li {
 	cursor : pointer;
 }
+.jqpage #scene ul.elt li>.content, .dialog-floating #scene ul.elt li>.content {
+	margin-left : 4px;
+	display : inline-block;
+	zoom : 1;
+	*display : inline;
+	height : 18px;
+}
 .jqpage #scene ul.elt li .content:hover, .dialog-floating #scene ul.elt li .content:hover {
 	background-color : #eee;
 }
 .jqpage #scene ul.elt ul, .dialog-floating #scene ul.elt ul {
 	padding-left : 20px;
 }
-.jqpage #scene ul.elt li.selected, .dialog-floating #scene ul.elt li.selected {
+.jqpage #scene ul.elt li.selected>.content, .dialog-floating #scene ul.elt li.selected>.content {
 	background-color : #eee;
 }
+.jqpage #scene ul.elt li.hidden, .dialog-floating #scene ul.elt li.hidden {
+	opacity : 0.5;
+	filter : alpha(opacity=50);
+	zoom : 1;
+}
+.jqpage #scene ul.elt li.culled>.content, .dialog-floating #scene ul.elt li.culled>.content {
+	opacity : 0.5;
+	filter : alpha(opacity=50);
+	zoom : 1;
+	font-style : italic;
+}
+.jqpage #scene>ul.elt, .dialog-floating #scene>ul.elt {
+	padding : 5px;
+	padding-bottom : 40px;
+}
 .jqpage table.props tr.pgroup, .dialog-floating table.props tr.pgroup {
 	cursor : pointer;
 }
@@ -41,6 +78,11 @@
 	padding : 2px 4px;
 	cursor : pointer;
 }
+.jqpage table.props tr.disable, .dialog-floating table.props tr.disable {
+	opacity : 0.5;
+	filter : alpha(opacity=50);
+	zoom : 1;
+}
 .jqpage table.props td, .dialog-floating table.props td {
 	height : 24px;
 }

+ 37 - 2
hxd/net/inspect.hss

@@ -4,14 +4,26 @@
 		user-select : none;
 	}
 
+	pre {
+		user-select : text;
+		.kwd {
+			color : #1518FF;
+		}
+		.meta {
+			color : #156018;
+		}
+	}
+
 	.panel {
 		overflow : auto;
+		background-color : white;
 	}
 
 	#log {
 		font-family : Courier;
 		.line {
 			padding : 1px 3px;
+			user-select : all;
 		}
 		CSS(".line:nth-child(even)") {
 			background-color : #eee;
@@ -24,19 +36,37 @@
 			li {
 				cursor : pointer;
 			}
+			li > .content {
+				margin-left : 4px;
+				display : inline-block;
+				height : 18px;
+			}
 			li .content:hover {
 				background-color : #eee;
 			}
 			ul {
 				padding-left : 20px;
 			}
-			li.selected {
+			li.selected > .content {
 				background-color : #eee;
 			}
+			li.hidden {
+				opacity : 0.5;
+			}
+			li.culled > .content {
+				opacity : 0.5;
+				font-style : italic;
+			}
 		}
 	}
 
-	#material {
+	#scene > ul.elt {
+		padding : 5px;
+		padding-bottom : 40px;
+	}
+
+
+	#props {
 	}
 
 	table.props {
@@ -51,6 +81,11 @@
 				cursor : pointer;
 			}
 		}
+
+		tr.disable {
+			opacity : 0.5;
+		}
+
 		td {
 			height : 24px;
 			input, select {