Nicolas Cannasse 8 лет назад
Родитель
Сommit
a9f950b066
6 измененных файлов с 245 добавлено и 41 удалено
  1. 4 2
      bin/app.html
  2. 61 7
      bin/style.css
  3. 67 7
      bin/style.less
  4. 1 1
      hide/comp/ContextMenu.hx
  5. 17 4
      hide/comp/Properties.hx
  6. 95 20
      hide/view/Particles3D.hx

+ 4 - 2
bin/app.html

@@ -63,8 +63,10 @@
   var fs = require('fs');
 
   var reloadWatcher=fs.watch(path, function() {
-    location.reload();
-    reloadWatcher.close();
+	setTimeout(function() {
+		location.reload();
+		reloadWatcher.close();
+	},1000);
   });
 </script>
 

+ 61 - 7
bin/style.css

@@ -24,6 +24,43 @@ select {
 input {
   padding-left: 4px;
 }
+input[type=button] {
+  background-color: #444;
+  cursor: pointer;
+}
+input[type=button]:hover {
+  color: white;
+  background-color: #666;
+}
+input[type=range] {
+  -webkit-appearance: none;
+  /* Hides the slider so that custom slider can be made */
+  background: transparent;
+  /* Otherwise white in Chrome */
+  border: none;
+  padding: 0;
+}
+input[type=range]::-webkit-slider-thumb {
+  -webkit-appearance: none;
+  outline: 1px solid #aaa;
+  height: 6px;
+  width: 6px;
+  background: #ccc;
+  cursor: pointer;
+  margin-top: 0px;
+  /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
+}
+input[type=range]::-webkit-slider-runnable-track {
+  width: 100%;
+  height: 8px;
+  cursor: pointer;
+  background: #141414;
+  border: 1px solid #444;
+}
+input[type=range]:focus {
+  outline: none;
+  /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
+}
 .checkbox-wrapper {
   display: inline-block;
 }
@@ -68,7 +105,7 @@ a {
 select,
 input {
   background-color: #222222;
-  border: 1px solid #aaa;
+  border: 1px solid #444;
 }
 select:focus,
 input:focus {
@@ -79,14 +116,14 @@ input:focus {
   height: 100%;
   overflow: auto;
 }
-.hide-scrollzone::-webkit-scrollbar {
+::-webkit-scrollbar {
   width: 5px;
   height: 5px;
 }
-.hide-scrollzone::-webkit-scrollbar-track {
+::-webkit-scrollbar-track {
   background: #666;
 }
-.hide-scrollzone::-webkit-scrollbar-thumb {
+::-webkit-scrollbar-thumb {
   background: #ddd;
 }
 .hide-loading {
@@ -189,8 +226,9 @@ input:focus {
   display: flex;
 }
 .hide-properties > .panel {
-  width: 250px;
+  width: 260px;
   padding: 10px;
+  overflow: auto;
 }
 .hide-properties > .content {
   flex-grow: 100;
@@ -231,18 +269,34 @@ input:focus {
 .hide-properties dt {
   width: 80px;
   text-align: right;
-  color: #d8d8d8;
+  font-size: 11px;
+  color: #aaa;
+  user-select: none;
+  cursor: default;
 }
 .hide-properties dd {
   width: 160px;
   margin-left: 10px;
 }
-.hide-properties dd input:not([type=checkbox]) {
+.hide-properties dd input:not([type=checkbox]):not([type=number]) {
   width: 150px;
 }
 .hide-properties dd select {
   width: 156px;
 }
+.hide-properties .group {
+  margin-bottom: 5px;
+}
+.hide-properties .group > .title {
+  text-align: center;
+  background-color: #1e1e1e;
+  cursor: pointer;
+  user-select: none;
+  padding: 1px;
+}
+.hide-properties .group > .content {
+  margin-bottom: 5px;
+}
 /* Golden Layout Fixes */
 .lm_header .lm_tabs {
   z-index: 1;

+ 67 - 7
bin/style.less

@@ -20,6 +20,45 @@ input {
 	padding-left : 4px;
 }
 
+input[type=button] {
+	background-color : #444;
+	cursor : pointer;
+}
+
+input[type=button]:hover {
+	color : white;
+	background-color : #666;
+}
+
+input[type=range] {
+	-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
+	background: transparent; /* Otherwise white in Chrome */
+	border:none;
+	padding:0;
+}
+
+input[type=range]::-webkit-slider-thumb {
+	-webkit-appearance: none;
+	outline: 1px solid #aaa;
+	height: 6px;
+	width: 6px;
+	background: #ccc;
+	cursor: pointer;
+	margin-top: 0px; /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
+}
+
+input[type=range]::-webkit-slider-runnable-track {
+	width: 100%;
+	height: 8px;
+	cursor: pointer;
+	background: rgb(20,20,20);
+	border: 1px solid #444;
+}
+
+input[type=range]:focus {
+	outline: none; /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
+}
+
 .checkbox-wrapper {
 	display:inline-block;
 }
@@ -37,6 +76,7 @@ input[type='checkbox'] {
     cursor:pointer;
 	top:1px;
 }
+
 input[type='checkbox']:after {
     content:"";
     vertical-align: middle;
@@ -53,6 +93,7 @@ input[type='checkbox']:after {
     background: #202020;
     color: #fff;
 }
+
 input[type='checkbox']:checked:after {
     content:'\2714';
 }
@@ -65,7 +106,7 @@ a {
 
 select, input {
 	background-color: rgb(34,34,34);
-	border : 1px solid #aaa;
+	border : 1px solid #444;
 	&:focus {
 		background-color: rgb(20,20,20);
 	}
@@ -77,16 +118,16 @@ select, input {
 	overflow : auto;
 }
 
-.hide-scrollzone::-webkit-scrollbar {
+::-webkit-scrollbar {
 	width: 5px;
 	height: 5px;
 }
 
-.hide-scrollzone::-webkit-scrollbar-track {
+::-webkit-scrollbar-track {
 	background: #666;
 }
 
-.hide-scrollzone::-webkit-scrollbar-thumb {
+::-webkit-scrollbar-thumb {
 	background: #ddd;
 }
 
@@ -201,8 +242,9 @@ select, input {
 	display: flex;
 
 	>.panel {
-		width : 250px;
+		width : 260px;
 		padding:10px;
+		overflow:auto;
 	}
 
 	>.content {
@@ -248,13 +290,16 @@ select, input {
 	dt {
 		width:80px;
 		text-align:right;
-		color:#d8d8d8;
+		font-size:11px;
+		color:#aaa;
+		user-select:none;
+		cursor:default;
 	}
 
 	dd {
 		width:160px;
 		margin-left:10px;
-		input:not([type=checkbox]) {
+		input:not([type=checkbox]):not([type=number]) {
 			width:150px;
 		}
 		select {
@@ -262,6 +307,21 @@ select, input {
 		}
 	}
 
+	.group {
+		>.title {
+			text-align : center;
+			background-color : rgb(30,30,30);
+			cursor:pointer;
+			user-select:none;
+			padding : 1px;
+		}
+		>.content {
+			margin-bottom : 5px;
+		}
+		margin-bottom : 5px;
+	}
+
+
 }
 
 /* Golden Layout Fixes */

+ 1 - 1
hide/comp/ContextMenu.hx

@@ -25,7 +25,7 @@ class ContextMenu {
 	}
 
 	function makeMenuItem(i:ContextMenuItem) {
-		var mconf : nw.MenuItem.MenuItemOptions = { label : i.label, type : i.checked ? Checkbox : i.isSeparator ? Separator : Normal };
+		var mconf : nw.MenuItem.MenuItemOptions = { label : i.label, type : i.checked != null ? Checkbox : i.isSeparator ? Separator : Normal };
 		if( i.menu != null ) mconf.submenu = makeMenu(i.menu);
 		var m = new nw.MenuItem(mconf);
 		if( i.checked != null ) m.checked = i.checked;

+ 17 - 4
hide/comp/Properties.hx

@@ -24,12 +24,23 @@ class Properties extends Component {
 
 		e.find("input[type=range]").not("[step]").attr("step", "any");
 
-		e.find(".section").not(".open").find(".content").hide();
+		e.find(".section").not(".open").children(".content").hide();
 		e.find(".section > h1").mousedown(function(e) {
 			if( e.button != 0 ) return;
 			var section = js.jquery.Helper.JTHIS.parent();
 			section.toggleClass("open");
-			section.children(".content").toggle(100);
+			section.children(".content").slideToggle(100);
+		}).find("input").mousedown(function(e) e.stopPropagation());
+
+		for( g in e.find(".group").elements() ) {
+			g.wrapInner("<div class='content'></div>'");
+			if( g.attr("name") != null ) new Element("<div class='title'>" + g.attr("name") + '</div>').prependTo(g);
+		}
+
+		e.find(".group > .title").mousedown(function(e) {
+			if( e.button != 0 ) return;
+			var group = js.jquery.Helper.JTHIS.parent();
+			group.children(".content").slideToggle(100);
 		}).find("input").mousedown(function(e) e.stopPropagation());
 
 		for( f in e.find("[field]").elements() ) {
@@ -72,18 +83,20 @@ class Properties extends Component {
 
 				var newVal : Dynamic = f.val();
 
-				if( f.is("[type=range]") )
+				if( f.is("[type=range]") || f.is("[type=number]") )
 					newVal = Std.parseFloat(newVal);
 
 				if( enumValue != null )
 					newVal = Type.createEnum(enumValue, newVal);
 
+				if( f.is("select") ) f.blur();
+
 				if( current == newVal ) return;
 
 				beforeChange();
-				trace(fname, newVal, Type.typeof(newVal));
 				current = newVal;
 				Reflect.setProperty(context, fname, newVal);
+
 			});
 		}
 

+ 95 - 20
hide/view/Particles3D.hx

@@ -34,31 +34,106 @@ class Particles3D extends FileView {
 		scene.onReady = init;
 	}
 
+	function addGroup( g : h3d.parts.GpuParticles.GpuPartGroup ) {
+		var e = new Element('
+			<div class="section open">
+				<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
+				<div class="content">
+
+					<div class="group" name="Display">
+						<dl>
+							<dt>Name</dt><dd><input field="name" onchange="$(this).closest(\'.section\').find(\'>h1 span\').text($(this).val())"/></dd>
+							<dt>Texture</dt><dd><input type="file" accept="image/*"/></dd>
+							<dt>Color Gradient</dt><dd><input type="file" accept="image/*"/></dd>
+							<dt>Sort</dt><dd><select field="sortMode"></select></dd>
+							<dt>3D&nbsp;Transform</dt><dd><input type="checkbox" field="transform3D"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Emit">
+						<dl>
+							<dt>Mode</dt><dd><select field="emitMode"/></dd>
+							<dt>Count</dt><dd><input type="range" field="nparts" min="0" max="1000" step="1"/></dd>
+							<dt>Distance</dt><dd><input type="range" field="emitDist" min="0" max="10"/></dd>
+							<dt>Angle</dt><dd><input type="range" field="emitAngle" min="${-Math.PI/2}" max="${Math.PI}"/></dd>
+							<dt>Sync</dt><dd><input type="range" field="emitSync" min="0" max="1"/></dd>
+							<dt>Delay</dt><dd><input type="range" field="emitDelay" min="0" max="10"/></dd>
+							<dt>Loop</dt><dd><input type="checkbox" field="emitLoop"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Life">
+						<dl>
+							<dt>Initial</dt><dd><input type="range" field="life" min="0" max="10"/></dd>
+							<dt>Randomness</dt><dd><input type="range" field="lifeRand" min="0" max="1"/></dd>
+							<dt>Fade In</dt><dd><input type="range" field="fadeIn" min="0" max="1"/></dd>
+							<dt>Fade Out</dt><dd><input type="range" field="fadeOut" min="0" max="1"/></dd>
+							<dt>Fade Power</dt><dd><input type="range" field="fadePower" min="0" max="3"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Speed">
+						<dl>
+							<dt>Initial</dt><dd><input type="range" field="speed" min="0" max="10"/></dd>
+							<dt>Randomness</dt><dd><input type="range" field="speedRand" min="0" max="1"/></dd>
+							<dt>Acceleration</dt><dd><input type="range" field="speedIncr" min="-1" max="1"/></dd>
+							<dt>Gravity</dt><dd><input type="range" field="gravity" min="-5" max="5"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Size">
+						<dl>
+							<dt>Initial</dt><dd><input type="range" field="size" min="0.01" max="2"/></dd>
+							<dt>Randomness</dt><dd><input type="range" field="sizeRand" min="0" max="1"/></dd>
+							<dt>Growth</dt><dd><input type="range" field="sizeIncr" min="-1" max="1"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Rotation">
+						<dl>
+							<dt>Initial</dt><dd><input type="range" field="rotInit" min="0" max="1"/></dd>
+							<dt>Speed</dt><dd><input type="range" field="rotSpeed" min="0" max="5"/></dd>
+							<dt>Randomness</dt><dd><input type="range" field="rotSpeedRand" min="0" max="1"/></dd>
+						</dl>
+					</div>
+
+					<div class="group" name="Animation">
+						<dl>
+							<dt>Animation Repeat</dt><dd><input type="range" field="animationRepeat" min="0" max="10"/></dd>
+							<dt>Frame Division</dt><dd>X <input type="number" field="frameDivisionX" min="1" max="16"/> Y <input type="number" field="frameDivisionY" min="1" max="16"/></dd>
+							<dt>Frame Count</dt><dd><input type="number" field="frameCount" min="0" max="32"/></dd>
+						</dl>
+					</div>
+
+				</div>
+			</div>
+		');
+		e.find("h1").contextmenu(function(ev) {
+			new hide.comp.ContextMenu([
+				{ label : "Enable", checked : g.enable, click : function() { g.enable = !g.enable; e.find("[field=enable]").prop("checked", g.enable); } },
+				{ label : "Delete", click : function() { parts.removeGroup(g); e.remove(); } },
+			]);
+			ev.preventDefault();
+		});
+		e.find("[field=emitLoop]").change(function(_) parts.currentTime = 0);
+		properties.add(e,g);
+	}
+
 	function init() {
 		new h3d.scene.CameraController(scene.s3d).loadFromCamera();
 		parts = new GpuParticles(this,scene.s3d);
 		parts.load(haxe.Json.parse(sys.io.File.getContent(getPath())));
 
-		for( g in parts.getGroups() ) {
-			var e = new Element('
-				<div class="section open">
-					<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
-					<dl class="content">
-						<dt>Name</dt><dd><input field="name" onchange="$(this).closest(\'.section\').find(\'>h1 span\').text($(this).val())"/></dd>
-						<dt>Mode</dt><dd><select field="emitMode"/></dd>
-						<dt>Count</dt><dd><input type="range" field="nparts" min="0" max="1000" step="1"/></dd>
-						<dt>Distance</dt><dd><input type="range" field="emitDist" min="0" max="10"/></dd>
-						<dt>Angle</dt><dd><input type="range" field="emitAngle" min="${-Math.PI/2}" max="${Math.PI}"/></dd>
-						<dt>Loop</dt><dd><input type="checkbox" field="emitLoop"/></dd>
-						<dt>Sync</dt><dd><input type="range" field="emitSync" min="0" max="1"/></dd>
-						<dt>Delay</dt><dd><input type="range" field="emitDelay" min="0" max="10"/></dd>
-						<dt>Transform3D</dt><dd><input type="checkbox" field="transform3D"/></dd>
-					</dl>
-				</div>
-			');
-			e.find("[field=emitLoop]").change(function(_) parts.currentTime = 0);
-			properties.add(e,g);
-		}
+		for( g in parts.getGroups() )
+			addGroup(g);
+		var but = new Element('<input type="button" value="New Group"/>');
+		but.appendTo(properties.panel);
+		but.click(function(_) {
+			var g = parts.addGroup();
+			g.name = "Group#" + Lambda.count({ iterator : parts.getGroups });
+			addGroup(g);
+			but.appendTo(properties.panel);
+		},null);
 	}
 
 	static var _ = FileTree.registerExtension(Particles3D, ["json.particles3D"], { icon : "snowflake-o", createNew: "Particle 3D" });