Parcourir la source

CdbInspector in progress

ncannasse il y a 10 ans
Parent
commit
59f185b29a
7 fichiers modifiés avec 325 ajouts et 15 suppressions
  1. 1 1
      .gitignore
  2. 10 0
      h3d/mat/Material.hx
  3. 197 9
      hxd/net/CdbInspector.hx
  4. 37 0
      hxd/net/Socket.hx
  5. 41 0
      hxd/net/inspect.css
  6. 39 0
      hxd/net/inspect.hss
  7. 0 5
      hxd/net/inspect.min.css

+ 1 - 1
.gitignore

@@ -4,4 +4,4 @@
 *.js.map
 bin
 .tmp
-/hxd/net/inspect.css
+/hxd/net/inspect.min.css

+ 10 - 0
h3d/mat/Material.hx

@@ -51,6 +51,16 @@ class Material {
 		return passes;
 	}
 
+	public function getPasses() {
+		var p = passes;
+		var out = [];
+		while( p != null ) {
+			out.push(p);
+			p = p.nextPass;
+		}
+		return out.iterator();
+	}
+
 	public function getPass( name : String ) : Pass {
 		var p = passes;
 		while( p != null ) {

+ 197 - 9
hxd/net/CdbInspector.hx

@@ -1,20 +1,62 @@
 package hxd.net;
 
+enum Property {
+	PBool( name : String, get : Void -> Bool, set : Bool -> Void );
+	PEnum( name : String, e : Enum<Dynamic>, get : Void -> Dynamic, set : Dynamic -> Void );
+}
+
+private class CdbEvent implements h3d.IDrawable {
+	var i : CdbInspector;
+	public function new(i) {
+		this.i = i;
+	}
+	public function render( engine : h3d.Engine ) {
+		i.sync();
+	}
+}
+
+private class SceneObject {
+	public var o : h3d.scene.Object;
+	public var parent : SceneObject;
+	public var j : cdb.jq.JQuery;
+	public var jchild : cdb.jq.JQuery;
+	public var childs : Array<SceneObject>;
+	public function new(o, p) {
+		this.o = o;
+		this.parent = p;
+		childs = [];
+	}
+	public function remove() {
+		for( c in childs )
+			c.remove();
+		j.remove();
+		if( parent != null )
+			parent.childs.remove(this);
+	}
+}
+
+
 class CdbInspector extends cdb.jq.Client {
 
-	static var inst = null;
-	static var CSS = hxd.res.Embed.getFileContent("hxd/net/inspect.min.css");
+	static var CSS = hxd.res.Embed.getFileContent("hxd/net/inspect.css");
 
 	public var host : String = "127.0.0.1";
 	public var port = 6669;
 
+	public var scene(default,set) : h3d.scene.Scene;
+
+	var event : CdbEvent;
 	var sock : hxd.net.Socket;
 	var connected = false;
 	var oldLog : Dynamic -> haxe.PosInfos -> Void;
 
+	var sceneObjects : Array<SceneObject> = [];
+	var scenePosition = 0;
+	var flushWait = false;
+
 	public function new( ?host, ?port ) {
 		super();
-		inst = this; // prevent GC
+		event = new CdbEvent(this);
 		if( host != null )
 			this.host = host;
 		if( port != null )
@@ -22,12 +64,20 @@ class CdbInspector extends cdb.jq.Client {
 		sock = new hxd.net.Socket();
 		sock.onError = function(e) {
 			connected = false;
-			trace(e);
 			haxe.Timer.delay(connect,500);
+		};
+		sock.onData = function() {
+			while( true ) {
+				var len = try sock.input.readUInt16() catch( e : haxe.io.Eof ) -1;
+				if( len < 0 ) break;
+				var data = sock.input.read(len);
+				var msg : cdb.jq.Message.Answer = cdb.BinSerializer.unserialize(data);
+				handle(msg);
+			}
 		}
 		connect();
-		oldLog = haxe.Log.trace;
-		haxe.Log.trace = onTrace;
+		/*oldLog = haxe.Log.trace;
+		haxe.Log.trace = onTrace;*/
 	}
 
 	function onTrace( v : Dynamic, ?pos : haxe.PosInfos ) {
@@ -38,6 +88,14 @@ class CdbInspector extends cdb.jq.Client {
 		}
 	}
 
+	function set_scene(s:h3d.scene.Scene) {
+		if( scene != null )
+			scene.removePass(event);
+		if( s != null )
+			s.addPass(event, true);
+		return scene = s;
+	}
+
 	function connect() {
 		sock.close();
 		sock.connect(host, port, function() {
@@ -47,22 +105,152 @@ class CdbInspector extends cdb.jq.Client {
 	}
 
 	override function sendBytes( msg : haxe.io.Bytes ) {
-		sock.out.wait();
+		if( !flushWait ) {
+			flushWait = true;
+			sock.out.wait();
+			haxe.Timer.delay(function() {
+				flushWait = false;
+				sock.out.flush();
+			},0);
+		}
 		sock.out.writeInt32(msg.length);
 		sock.out.write(msg);
-		sock.out.flush();
 	}
 
 	function refresh() {
 		j.html('
 			<div id="scene" class="panel" caption="Scene">
+				<ul id="scontent" class="elt">
+				</ul>
+			</div>
+			<div id="material" class="panel" caption="Material">
 			</div>
 			<div id="log" class="panel" caption="Log">
 			</div>
 		');
 		send(SetCSS(CSS));
-		J("#scene").dock(root, Left, 0.2);
+		var scene = J("#scene");
+		scene.dock(root, Left, 0.2);
 		J("#log").dock(root, Down, 0.3);
+		J("#material").dock(scene.get(), Down, 0.3);
+	}
+
+	public function sync() {
+		if( scene == null || !connected ) return;
+		scenePosition = 0;
+		syncRec(scene, null);
+	}
+
+	function syncRec( o : h3d.scene.Object, p : SceneObject ) {
+		var so = sceneObjects[scenePosition];
+		if( so == null || so.o != o || so.parent != p ) {
+			so = new SceneObject(o, p);
+			sceneObjects.insert(scenePosition, so);
+			so.j = J("<li>");
+			so.j.html('<div class="content">${o.toString()}</div>');
+			so.j.find(".content").click(function(_) {
+				selectObject(o);
+			});
+			so.j.appendTo( p != null ? p.jchild : J("#scontent") );
+			if( p != null ) p.childs.push(so);
+		}
+		scenePosition++;
+		if( o.numChildren > 0 ) {
+			if( so.jchild == null ) {
+				so.jchild = J("<ul>");
+				so.jchild.addClass("elt");
+				so.jchild.appendTo(so.j);
+			}
+			for( c in o )
+				syncRec(c, so);
+		} else if( so.jchild != null ) {
+			so.jchild.remove();
+			so.jchild = null;
+			for( o in so.childs )
+				o.remove();
+		}
+	}
+
+	function makeProps( props : Array<Property> ) {
+		var t = J("<table>");
+		t.addClass("props");
+		for( p in props ) {
+			var j = J("<tr>");
+			j.addClass("prop");
+			j.addClass(p.getName().toLowerCase());
+			j.appendTo(t);
+
+			var jname = J("<th>");
+			var jprop = J("<td>");
+			jname.appendTo(j);
+			jprop.appendTo(j);
+
+			switch( p ) {
+			case PBool(name, get, set):
+				jname.text(name);
+				jprop.text(get() ? "Yes" : "No");
+				j.dblclick(function(_) {
+					set(!get());
+					jprop.text(get() ? "Yes" : "No");
+				});
+			case PEnum(name, tenum, get, set):
+				jname.text(name);
+				jprop.text(get());
+				j.dblclick(function(_) {
+
+					var input = J("<select>");
+					var cur = (get() : EnumValue).getIndex();
+					var all : Array<EnumValue> = tenum.createAll();
+					for( p in all ) {
+						var name = p.getName();
+						var idx = p.getIndex();
+						J("<option>").attr("value", "" + p.getIndex()).attr(idx == cur ? "selected" : "_sel", "selected").text(name).appendTo(input);
+					}
+					jprop.text("");
+					input.appendTo(jprop);
+					input.trigger("focus");
+					input.blur(function(_) {
+						input.remove();
+						jprop.text(get());
+					});
+					input.change(function(_) {
+						var v = Std.parseInt(input.getValue());
+						if( v != null )
+							set(all[v]);
+						input.remove();
+						jprop.text(get());
+					});
+				});
+			}
+		}
+		return t;
+	}
+
+	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));
+		for( pass in mat.getPasses() ) {
+			var pgrp = J("<div>");
+			pgrp.appendTo(j);
+
+			var p = J("<div>");
+			p.addClass("pass");
+			p.text(pass.name);
+			p.appendTo(pgrp);
+
+			var t = makeProps([
+				PBool("DepthWrite", function() return pass.depthWrite, function(b) pass.depthWrite = b),
+				PEnum("DepthTest", h3d.mat.Data.Compare, function() return pass.depthTest, function(v) pass.depthTest = v),
+			]);
+
+			t.appendTo(pgrp);
+			t.style("display", "none");
+			p.click(function(_) t.toggle());
+		}
 	}
 
 }

+ 37 - 0
hxd/net/Socket.hx

@@ -65,15 +65,43 @@ private class FlashSocketOutput extends SocketOutput {
 		f();
 	}
 
+}
+
+private class FlashSocketInput extends haxe.io.Input {
+
+	var sock : flash.net.Socket;
+
+	public function new(s) {
+		sock = s;
+	}
+
+	override function readBytes( bytes : haxe.io.Bytes, pos : Int, len : Int ) {
+		if( len > (sock.bytesAvailable : Int) ) {
+			len = sock.bytesAvailable;
+			if( len == 0 ) throw new haxe.io.Eof();
+		}
+		if( len > 0 )
+			sock.readBytes(bytes.getData(), pos, len);
+		return len;
+	}
+
+	override function readByte() {
+		if( sock.bytesAvailable == 0 )
+			throw new haxe.io.Eof();
+		return sock.readUnsignedByte();
+	}
+
 }
 #end
 
 class Socket {
 
+	static var openedSocks = [];
 	#if flash
 	var s : flash.net.Socket;
 	#end
 	public var out(default, null) : SocketOutput;
+	public var input(default, null) : haxe.io.Input;
 
 	public function new() {
 		out = new SocketOutput();
@@ -81,10 +109,12 @@ class Socket {
 
 	public function connect( host : String, port : Int, onConnect : Void -> Void ) {
 		close();
+		openedSocks.push(this);
 		#if flash
 		s = new flash.net.Socket();
 		s.addEventListener(flash.events.Event.CONNECT, function(_) {
 			out = new FlashSocketOutput(s);
+			input = new FlashSocketInput(s);
 			onConnect();
 		});
 		s.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e:flash.events.IOErrorEvent) {
@@ -95,6 +125,9 @@ class Socket {
 			close();
 			onError("Closed");
 		});
+		s.addEventListener(flash.events.ProgressEvent.SOCKET_DATA, function(e:flash.events.ProgressEvent) {
+			onData();
+		});
 		s.connect(host, port);
 		#else
 		throw "Not implemented";
@@ -102,6 +135,7 @@ class Socket {
 	}
 
 	public function close() {
+		openedSocks.remove(this);
 		#if flash
 		if( s != null ) {
 			try s.close() catch( e : Dynamic ) { };
@@ -117,4 +151,7 @@ class Socket {
 		throw "Socket Error " + msg;
 	}
 
+	public dynamic function onData() {
+	}
+
 }

+ 41 - 0
hxd/net/inspect.css

@@ -0,0 +1,41 @@
+.jqpage div, .jqpage a, .jqpage li, .jqpage td, .jqpage th {
+	user-select : none;
+	-moz-user-select : none;
+	-webkit-user-select : none;
+}
+.jqpage .panel {
+	overflow : auto;
+}
+.jqpage #log {
+	font-family : Courier;
+}
+.jqpage #log .line {
+	padding : 1px 3px;
+}
+.jqpage #log .line:nth-child(even) {
+	background-color : #eee;
+}
+.jqpage #scene ul.elt {
+	background-color : transparent;
+}
+.jqpage #scene ul.elt li {
+	cursor : pointer;
+}
+.jqpage #scene ul.elt li .content:hover {
+	background-color : #eee;
+}
+.jqpage #scene ul.elt ul {
+	padding-left : 20px;
+}
+.jqpage #material .pass {
+	background-color : #555;
+	color : #bbb;
+	font-weight : bold;
+	padding : 2px 4px;
+	cursor : pointer;
+}
+.jqpage table.props td select {
+	padding-left : 0px;
+	height : 20px;
+	width : 100%;
+}

+ 39 - 0
hxd/net/inspect.hss

@@ -1,5 +1,9 @@
 .jqpage {
 
+	div, a, li, td, th {
+		user-select : none;
+	}
+
 	.panel {
 		overflow : auto;
 	}
@@ -14,4 +18,39 @@
 		}
 	}
 
+	#scene {
+		ul.elt {
+			background-color : transparent;
+			li {
+				cursor : pointer;
+			}
+			li .content:hover {
+				background-color : #eee;
+			}
+			ul {
+				padding-left : 20px;
+			}
+		}
+	}
+
+	#material {
+		.pass {
+			background-color : #555;
+			color : #bbb;
+			font-weight : bold;
+			padding : 2px 4px;
+			cursor : pointer;
+		}
+	}
+
+	table.props {
+		td {
+			select {
+				padding-left : 0px;
+				height : 20px;
+				width : 100%;
+			}
+		}
+	}
+
 }

+ 0 - 5
hxd/net/inspect.min.css

@@ -1,5 +0,0 @@
-.jqpage .panel{overflow:auto;}
-.jqpage #log{font-family:Courier;}
-.jqpage #log .line{padding:1px 3px;}
-.jqpage #log .line:nth-child(even){background-color:#eee;}
-