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

Add layer toolbars buttons

trethaller 7 жил өмнө
parent
commit
8652fa34ce

+ 32 - 21
bin/style.css

@@ -172,7 +172,7 @@ input[type=checkbox]:checked:after {
   padding-right: 5px;
 }
 .hide-scene-tree {
-  min-height: 500px;
+  min-height: 400px;
 }
 .hide-range {
   display: inline-block;
@@ -218,8 +218,9 @@ input[type=checkbox]:checked:after {
 .hide-toolbar .toggle {
   margin-right: 5px;
   display: inline-block;
+  user-select: none;
   border: 1px solid #5a5a5a;
-  width: 20px;
+  min-width: 20px;
   height: 20px;
   padding: 2px;
   text-align: center;
@@ -240,6 +241,13 @@ input[type=checkbox]:checked:after {
   border-color: white;
   background-color: #666;
 }
+.hide-toolbar .button label,
+.hide-toolbar .toggle label {
+  font-size: 12px;
+  margin-left: 6px;
+  margin-right: 6px;
+  text-shadow: none;
+}
 .hide-toolbar .toggle.toggled {
   color: #ddd;
   background: #777;
@@ -447,38 +455,41 @@ div.lm_close_tab:hover {
   width: 18px !important;
   top: -1px;
 }
-.jstree-icon {
-  color: #aaa !important;
+.jstree-icon i {
+  color: #aaa;
+}
+.jstree.small a {
+  font-size: 12px;
 }
 .jstree.small .jstree-node {
-  min-height: 20px;
-  line-height: 20px;
-  margin-left: 10px;
-  min-width: 20px;
+  min-height: 18px;
+  line-height: 18px;
+  margin-left: 12px;
+  min-width: 18px;
 }
 .jstree.small .jstree-anchor {
-  line-height: 20px;
-  height: 20px;
+  line-height: 18px;
+  height: 18px;
 }
 .jstree.small .jstree-icon {
-  width: 20px;
-  height: 20px;
-  line-height: 20px;
+  width: 18px;
+  height: 18px;
+  line-height: 18px;
 }
 .jstree.small .jstree-icon:empty {
-  width: 20px;
-  height: 20px;
-  line-height: 20px;
+  width: 18px;
+  height: 18px;
+  line-height: 18px;
 }
 .jstree.small .jstree-wholerow {
-  height: 20px;
+  height: 18px;
 }
-.jstree-invisible a,
-.jstree-invisible i {
+.jstree-invisible a {
   color: #555 !important;
+  display: inline;
 }
-.jstree-invisible a {
-  display: inline !important;
+.jstree-invisible i {
+  color: #555;
 }
 /* Spectrum Color picker */
 div.sp-replacer {

+ 22 - 8
bin/style.less

@@ -183,7 +183,7 @@ input[type=checkbox] {
 }
 
 .hide-scene-tree {
-	min-height: 500px;
+	min-height: 400px;
 }
 
 .hide-range {
@@ -236,8 +236,9 @@ input[type=checkbox] {
 	.button, .toggle {
 		margin-right : 5px;
 		display: inline-block;
+		user-select:none;
 		border: 1px solid rgb(90,90,90);
-		width : 20px;
+		min-width : 20px;
 		height : 20px;
 		padding : 2px;
 		text-align: center;
@@ -255,6 +256,12 @@ input[type=checkbox] {
 			border-color : white;
 			background-color : #666;
 		}
+		label {
+			font-size: 12px;
+			margin-left: 6px;
+			margin-right: 6px;
+			text-shadow: none;	
+		}
 	}
 
 	.toggle.toggled {
@@ -488,16 +495,22 @@ div.lm_close_tab:hover { background-color : #555 !important; }
 }
 
 .jstree-icon {
-	color : #aaa !important;
+	i {
+		color : #aaa;
+	}
 }
 
 .jstree.small {
-	@size: 20px;
+	@size: 18px;
+
+	a {
+		font-size: 12px;
+	}
 
 	.jstree-node {
 		min-height: @size;
 		line-height: @size;
-		margin-left: 10px;
+		margin-left: 12px;
 		min-width: @size;
 	}
 	.jstree-anchor {
@@ -520,11 +533,12 @@ div.lm_close_tab:hover { background-color : #555 !important; }
 }
 
 .jstree-invisible {
-	a, i {
+	a {
 		color: #555 !important;
+		display: inline;
 	}
-	a {
-		display: inline !important;
+	i {
+		color: #555;
 	}
 }
 

+ 13 - 4
hide/comp/Toolbar.hx

@@ -3,6 +3,7 @@ package hide.comp;
 typedef ToolToggle = {
 	var element : Element;
 	function toggle( v : Bool ) : Void;
+	function isDown(): Bool;
 }
 
 typedef ToolSelect<T> = {
@@ -25,19 +26,27 @@ class Toolbar extends Component {
 		return e;
 	}
 
-	public function addToggle( icon : String, ?label : String, ?onToggle : Bool -> Void, ?defValue = false ) : ToolToggle {
-		var e = new Element('<div class="toggle" title="${label==null ? "" : label}"><div class="icon fa fa-$icon"/></div>');
+	public function addToggle( icon : String, ?title : String, ?label : String, ?onToggle : Bool -> Void, ?defValue = false ) : ToolToggle {
+		var e = new Element('<div class="toggle" title="${title==null ? "" : title}"><div class="icon fa fa-$icon"/></div>');
+		if(label != null) {
+			new Element('<label>$label</label>').appendTo(e);
+		}
+		var callback = null;
 		e.click(function(_) {
 			e.toggleClass("toggled");
 			this.saveDisplayState("toggle:" + icon, e.hasClass("toggled"));
-			if( onToggle != null ) onToggle(e.hasClass("toggled"));
+			if( callback != null ) callback(e.hasClass("toggled"));
 		});
 		e.appendTo(root);
 		if( defValue ) e.addClass("toggled");
 		var def = getDisplayState("toggle:" + icon);
 		if( def == null ) def = false;
 		if( def != defValue ) e.click();
-		return { element : e, toggle : function(b) e.toggleClass("toggled",b) };
+		callback = onToggle;
+		return {
+			element : e,
+			toggle : function(b) e.toggleClass("toggled",b),
+			isDown: function() return e.hasClass("toggled") };
 	}
 
 	public function addColor( label : String, onChange : Int -> Void, ?alpha : Bool, ?defValue = 0 ) {

+ 1 - 1
hide/prefab/Object3D.hx

@@ -103,7 +103,7 @@ class Object3D extends Prefab {
 
 
 	override function getHideProps() {
-		return { icon : "genderless", name : "Empty", fileSource : null };
+		return { icon : "folder-open", name : "Empty", fileSource : null };
 	}
 
 	static var _ = Library.register("object", Object3D);

+ 12 - 1
hide/prefab/Prefab.hx

@@ -151,8 +151,19 @@ class Prefab {
 		return v;
 	}
 
+	public function getAll<T:Prefab>( cl : Class<T>, ?arr: Array<T> ) : Array<T> {
+		if(arr == null)
+			arr = [];
+		var i = Std.instance(this, cl);
+		if(i != null)
+			arr.push(i);
+		for(c in children) {
+			c.getAll(cl, arr);
+		}
+		return arr;
+	}
+
 	public function to<T:Prefab>( c : Class<T> ) : Null<T> {
 		return Std.instance(this, c);
 	}
-
 }

+ 114 - 60
hide/view/Level3D.hx

@@ -3,6 +3,7 @@ import hxd.Math;
 import hxd.Key as K;
 
 import hide.prefab.Prefab as PrefabElement;
+import hide.prefab.Object3D;
 import h3d.scene.Object;
 
 class LevelEditContext extends hide.prefab.EditContext {
@@ -248,6 +249,7 @@ class Level3D extends FileView {
 	var light : h3d.scene.DirLight;
 	var lightDirection = new h3d.Vector( 1, 2, -4 );
 	var tree : hide.comp.IconTree<PrefabElement>;
+	var layerButtons : Map<PrefabElement, hide.comp.Toolbar.ToolToggle>;
 
 	var searchBox : Element;
 	var curEdit : LevelEditContext;
@@ -346,45 +348,15 @@ class Level3D extends FileView {
 		data.makeInstance(context);
 		scene.s3d.addChild(sh.root3d);
 		scene.init(props);
-		tree.refresh(callb);
-
-		var all = sh.contexts.keys();
-		for(elt in all) {
-			var ctx = sh.contexts[elt];
-			if(ctx.local3d != null) {
-				var o = ctx.local3d;
-				var meshes = o.getMeshes();
-				var collider : h3d.col.Collider;
-				var bounds = new h3d.col.Bounds();
-				if(meshes.length == 1) {
-					collider = meshes[0].primitive.getCollider();
-					bounds = meshes[0].primitive.getBounds();
-				}
-				else if(meshes.length > 1) {
-					for(m in meshes)
-						bounds.add(m.primitive.getBounds());
-					collider = new h3d.col.Collider.GroupCollider([for(m in meshes) m.primitive.getCollider()]);
-				}
-				else continue;
-				var int = new h3d.scene.Interactive(bounds, o);
-				int.preciseShape = collider;
-				int.propagateEvents = true;
-				int.onClick = function(e) {
-					if(K.isDown(K.CTRL) && curEdit != null) {
-						var list = curEdit.elements.copy();
-						if(list.indexOf(elt) < 0) {
-								list.push(elt);
-							tree.setSelection(list);
-							selectObjects(list);
-						}
-					}
-					else {
-						tree.setSelection([elt]);
-						selectObjects([elt]);
-					}
-				}
+		tree.refresh(function() {
+			for(elt in sh.contexts.keys()) {
+				onPrefabChange(elt);
 			}
-		}
+			if(callb != null) callb();
+		});
+
+		refreshInteractives();
+		refreshLayerIcons();
 	}
 
 	function autoName(p : PrefabElement) {
@@ -392,7 +364,7 @@ class Level3D extends FileView {
 		var prefix = p.type;
 		if(prefix == "object")
 			prefix = "group";
-			
+
 		var model = Std.instance(p, hide.prefab.Model);
 		if(model != null && model.source != null) {
 			var path = new haxe.io.Path(model.source);
@@ -452,7 +424,7 @@ class Level3D extends FileView {
 				m;
 			}];
 
-			var objects3d = [for(e in curEdit.elements) Std.instance(e, hide.prefab.Object3D)];
+			var objects3d = [for(e in curEdit.elements) Std.instance(e, Object3D)];
 			var prevState = [for(o in objects3d) o.save()];			
 			
 			gizmo.onMove = function(translate: h3d.Vector, rot: h3d.Quat) {
@@ -618,9 +590,6 @@ class Level3D extends FileView {
 				children : o.children.length > 0,
 				state : { opened : true },
 			};
-			if(Reflect.field(o, "visible") == false) {
-				r.li_attr = { "class": "jstree-invisible" };
-			}
 			return r;
 		}
 		tree.get = function(o:PrefabElement) {
@@ -638,9 +607,8 @@ class Level3D extends FileView {
 
 			var registered = new Array<hide.comp.ContextMenu.ContextMenuItem>();
 			var allRegs = @:privateAccess hide.prefab.Library.registeredElements;
-			var allowed = ["model", "object"];
-			for( ptype in allRegs.keys() ) {
-				if( allowed.indexOf(ptype) < 0 ) continue;
+			var allowed = ["model", "object", "layer"];
+			for( ptype in allowed ) {
 				var pcl = allRegs.get(ptype);
 				var props = Type.createEmptyInstance(pcl).getHideProps();
 				registered.push({
@@ -675,10 +643,11 @@ class Level3D extends FileView {
 			];
 
 			if(current != null && curEdit != null) {
-				var obj3d = Std.instance(current, hide.prefab.Object3D);
+				var obj3d = Std.instance(current, Object3D);
 				if(obj3d != null) {
 					menuItems.push({label : obj3d.visible ? "Hide" : "Show", click: function() {
-						setVisible(obj3d, !obj3d.visible);
+						var children = current.getAll(Object3D);
+						setVisible(cast children, !obj3d.visible);
 					}});
 				}
 			}
@@ -850,7 +819,7 @@ class Level3D extends FileView {
 		to.children.remove(e);
 		to.children.insert(index, e);
 
-		var obj3d = Std.instance(e, hide.prefab.Object3D);
+		var obj3d = Std.instance(e, Object3D);
 		var obj = getObject(e);
 		var toObj = getObject(to);
 		var mat = worldMat(obj);
@@ -888,13 +857,27 @@ class Level3D extends FileView {
 		return context.shared.root3d;
 	}
 
-	function setVisible(obj3d : hide.prefab.Object3D, visible: Bool) {
-		obj3d.visible = visible;
-		var o = curEdit.getContext(obj3d).local3d;
-		if(o != null) {
-			obj3d.applyPos(o);
+	function setVisible(elements : Array<PrefabElement>, visible: Bool) {
+		// var objects3d = [for(e in elements) Std.instance(e, Object3D)];
+		function apply(b) {
+			for(e in elements) {
+				var obj3d = Std.instance(e, Object3D);
+				if(obj3d == null) continue;
+				obj3d.visible = b;
+				var o = curEdit.getContext(obj3d).local3d;
+				if(o != null) {
+					obj3d.applyPos(o);
+				}
+				curEdit.onChange(obj3d);
+			}
 		}
-		curEdit.onChange(obj3d);
+		apply(visible);
+		undo.change(Custom(function(undo) {
+			if(undo)
+				apply(!visible);
+			else
+				apply(visible);
+		}));
 	}
 
 	function showSearch() {
@@ -902,14 +885,85 @@ class Level3D extends FileView {
 		searchBox.find("input").focus().select();
 	}
 
+	function refreshLayerIcons() {
+		if(layerButtons != null) {
+			for(b in layerButtons)
+				b.element.remove();
+		}
+		layerButtons = new Map<PrefabElement, hide.comp.Toolbar.ToolToggle>();
+		var all = context.shared.contexts.keys();
+		for(elt in all) {
+			var layer = Std.instance(elt, hide.prefab.Layer3D);
+			if(layer == null) continue;
+			layerButtons[elt] = tools.addToggle("file", layer.name, layer.name, function(on) {
+				setVisible([layer], on);
+			}, layer.visible);
+		}
+	}
+
+	function refreshInteractives() {
+		var contexts = context.shared.contexts;
+		var all = contexts.keys();
+		for(elt in all) {
+			var ctx = contexts[elt];
+			if(ctx.local3d != null) {
+				var o = ctx.local3d;
+				var meshes = o.getMeshes();
+				var collider : h3d.col.Collider;
+				var bounds = new h3d.col.Bounds();
+				if(meshes.length == 1) {
+					collider = meshes[0].primitive.getCollider();
+					bounds = meshes[0].primitive.getBounds();
+				}
+				else if(meshes.length > 1) {
+					for(m in meshes)
+						bounds.add(m.primitive.getBounds());
+					collider = new h3d.col.Collider.GroupCollider([for(m in meshes) m.primitive.getCollider()]);
+				}
+				else continue;
+				var int = new h3d.scene.Interactive(bounds, o);
+				int.preciseShape = collider;
+				int.propagateEvents = true;
+				int.onClick = function(e) {
+					if(K.isDown(K.CTRL) && curEdit != null) {
+						var list = curEdit.elements.copy();
+						if(list.indexOf(elt) < 0) {
+								list.push(elt);
+							tree.setSelection(list);
+							selectObjects(list);
+						}
+					}
+					else {
+						tree.setSelection([elt]);
+						selectObjects([elt]);
+					}
+				}
+			}
+		}
+	}
+
 	public function onPrefabChange(p: PrefabElement) {
 		var el = tree.getElement(p);
-		var obj3d : hide.prefab.Object3D = cast p;
-		if(obj3d.visible) {
-			el.removeClass("jstree-invisible");
+		var obj3d  = Std.instance(p, Object3D);
+		if(obj3d != null) {
+			if(obj3d.visible) {
+				el.removeClass("jstree-invisible");
+			}
+			else {
+				el.addClass("jstree-invisible");
+			}
 		}
-		else {
-			el.addClass("jstree-invisible");
+
+		var layer = Std.instance(p, hide.prefab.Layer3D);
+		if(layer != null) {
+			var color = "#" + StringTools.hex(layer.color);
+			el.find("i.jstree-themeicon").first().css("color", color);
+			var lb = layerButtons[p];
+			if(lb != null) {
+				if(layer.visible != lb.isDown())
+					lb.toggle(layer.visible);
+				lb.element.find(".icon").css("color", color);
+			}
 		}
 	}