浏览代码

particles 2d editor

Nicolas Cannasse 8 年之前
父节点
当前提交
54eb4018b3
共有 2 个文件被更改,包括 199 次插入3 次删除
  1. 10 3
      hide/comp/Scene.hx
  2. 189 0
      hide/view/Particles2D.hx

+ 10 - 3
hide/comp/Scene.hx

@@ -147,6 +147,7 @@ class Scene extends Component implements h3d.IDrawable {
 		stage = @:privateAccess new hxd.Stage(canvas);
 		stage = @:privateAccess new hxd.Stage(canvas);
 		stage.setCurrent();
 		stage.setCurrent();
 		engine = new h3d.Engine();
 		engine = new h3d.Engine();
+		engine.onResized = function() onResize();
 		engine.backgroundColor = 0xFF111111;
 		engine.backgroundColor = 0xFF111111;
 		canvas.id = null;
 		canvas.id = null;
 		engine.onReady = function() {
 		engine.onReady = function() {
@@ -277,13 +278,16 @@ class Scene extends Component implements h3d.IDrawable {
 		return null;
 		return null;
 	}
 	}
 
 
-	public function loadTextureFile( modelPath : String, texturePath : String ) {
+	public function loadTextureFile( modelPath : String, texturePath : String, ?onReady ) {
 		var path = resolvePath(modelPath, texturePath);
 		var path = resolvePath(modelPath, texturePath);
 		if( path != null ) {
 		if( path != null ) {
-			var t = new h3d.mat.Texture(1,1);
+			var bytes = sys.io.File.getBytes(path);
+			var size = hxd.res.Any.fromBytes(path, bytes).toImage().getSize();
+			var t = new h3d.mat.Texture(size.width,size.height);
 			t.clear(0x102030);
 			t.clear(0x102030);
 			t.name = ide.makeRelative(path);
 			t.name = ide.makeRelative(path);
-			loadTexture(path, function(_) {}, t);
+			if( onReady == null ) onReady = function(_) {};
+			loadTexture(path, onReady, t);
 			return t;
 			return t;
 		}
 		}
 		trace("Could not load texture " + { modelPath : modelPath, texturePath : texturePath });
 		trace("Could not load texture " + { modelPath : modelPath, texturePath : texturePath });
@@ -343,6 +347,9 @@ class Scene extends Component implements h3d.IDrawable {
 	public dynamic function onReady() {
 	public dynamic function onReady() {
 	}
 	}
 
 
+	public dynamic function onResize() {
+	}
+
 	public static function getNearest( e : Element ) : Scene {
 	public static function getNearest( e : Element ) : Scene {
 		while( e.length > 0 ) {
 		while( e.length > 0 ) {
 			var c : Dynamic = e.find("canvas")[0];
 			var c : Dynamic = e.find("canvas")[0];

+ 189 - 0
hide/view/Particles2D.hx

@@ -0,0 +1,189 @@
+package hide.view;
+
+@:access(hide.view.Particles2D)
+private class Particles extends h2d.Particles {
+
+	var parts : Particles2D;
+
+	public function new(parts, parent) {
+		this.parts = parts;
+		super(parent);
+	}
+
+	override function loadTexture( path : String ) {
+		return parts.scene.loadTextureFile(parts.state.path, path);
+	}
+
+}
+
+class Particles2D extends FileView {
+
+	var scene : hide.comp.Scene;
+	var parts : Particles;
+	var properties : hide.comp.PropsEditor;
+
+	override function getDefaultContent() {
+		var p = new Particles(this,null);
+		p.addGroup().name = "Default";
+		return haxe.io.Bytes.ofString(ide.toJSON(p.save()));
+	}
+
+	override function onDisplay() {
+		root.html('
+			<div class="flex">
+				<div class="scene"></div>
+				<div class="props"></div>
+			</div>
+		');
+		properties = new hide.comp.PropsEditor(root.find(".props"), undo);
+		properties.saveDisplayKey = "particles2D";
+		scene = new hide.comp.Scene(root.find(".scene"));
+		scene.onReady = init;
+	}
+
+	override function save() {
+		sys.io.File.saveContent(getPath(), ide.toJSON(parts.save()));
+	}
+
+	function addGroup( g : h2d.Particles.ParticleGroup ) {
+		var e = new Element('
+			<div class="section">
+				<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>Blend Mode</dt><dd><select field="blendMode"/></dd></dd>
+							<dt>Texture</dt><dd><input type="texture" field="texture"/></dd>
+							<dt>Color Gradient</dt><dd><input type="texture" field="colorGradient"/></dd>
+							<dt>Sort Mode</dt><dd><select field="sortMode"/></dd></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="300" step="1"/></dd>
+							<dt>Distance</dt><dd><input type="range" field="emitDist" min="0" max="1000"/></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="1000"/></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="-250" max="250"/></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" style="width:30px" field="frameDivisionX" min="1" max="16"/>
+								Y <input type="number" style="width:30px" field="frameDivisionY" min="1" max="16"/>
+								# <input type="number" style="width:30px" field="frameCount" min="0" max="32"/>
+							</dd>
+						</dl>
+					</div>
+
+				</div>
+			</div>
+		');
+
+		e.find("h1").contextmenu(function(ev) {
+			var groups = @:privateAccess parts.groups;
+			var index = groups.indexOf(g);
+			function moveIndex(d:Int,history=true) {
+				var index = groups.indexOf(g);
+				parts.removeGroup(g);
+				parts.addGroup(g, index + d);
+				if( history ) undo.change(Custom(function(undo) moveIndex(undo ? -d : d,false)));
+				initProperties();
+			}
+			new hide.comp.ContextMenu([
+				{ label : "Enable", checked : g.enable, click : function() { g.enable = !g.enable; e.find("[field=enable]").prop("checked", g.enable); } },
+				{ label : "MoveUp", enabled : index > 0, click : function() moveIndex(-1) },
+				{ label : "MoveDown", enabled : index < groups.length - 1, click : function() moveIndex(1) },
+				{ label : "Delete", click : function() { parts.removeGroup(g); e.remove(); } },
+			]);
+			ev.preventDefault();
+		});
+		properties.add(e, g);
+	}
+
+	function init() {
+		parts = new Particles(this,scene.s2d);
+		parts.load(haxe.Json.parse(sys.io.File.getContent(getPath())));
+		initProperties();
+		scene.init(props);
+		scene.onResize = onResize;
+	}
+
+	override function onResize() {
+		if( parts == null ) return;
+		parts.x = scene.s2d.width >> 1;
+		parts.y = scene.s2d.height >> 1;
+	}
+
+	function initProperties() {
+
+		properties.clear();
+
+		for( g in parts.getGroups() )
+			addGroup(g);
+
+		var extra = new Element('
+			<div class="section">
+				<h1>Manage</h1>
+				<div class="content">
+					<dl>
+					<dt></dt><dd><input type="button" class="new" value="New Group"/></dd>
+					</dl>
+				</div>
+			</div>
+		');
+		extra = properties.add(extra);
+		extra.find(".new").click(function(_) {
+			var g = parts.addGroup();
+			g.name = "Group#" + Lambda.count({ iterator : parts.getGroups });
+			addGroup(g);
+			extra.appendTo(properties.root);
+		}, null);
+	}
+
+	static var _ = FileTree.registerExtension(Particles2D, ["json.particles2D"], { icon : "snowflake-o", createNew: "Particle 2D" });
+
+}