Jelajahi Sumber

added find/findAll to Object and Sprite, and a few renames

Nicolas Cannasse 8 tahun lalu
induk
melakukan
00ed880ad9

+ 21 - 21
h2d/Flow.hx

@@ -571,7 +571,7 @@ class Flow extends Sprite {
 				for( i in lastIndex...maxIndex ) {
 					var p = properties[i];
 					if( p.isAbsolute ) continue;
-					var c = childs[i];
+					var c = children[i];
 					if( !c.visible ) continue;
 					var a = p.verticalAlign != null ? p.verticalAlign : valign;
 					c.y = y + p.offsetY + p.paddingTop;
@@ -586,10 +586,10 @@ class Flow extends Sprite {
 				lastIndex = maxIndex;
 			}
 
-			for( i in 0...childs.length ) {
+			for( i in 0...children.length ) {
 				var p = properties[i];
 				if( p.isAbsolute ) continue;
-				var c = childs[i];
+				var c = children[i];
 				if( !c.visible ) continue;
 
 				c.constraintSize(
@@ -616,7 +616,7 @@ class Flow extends Sprite {
 				x += horizontalSpacing;
 				if( p.calculatedHeight > maxLineHeight ) maxLineHeight = p.calculatedHeight;
 			}
-			alignLine(childs.length);
+			alignLine(children.length);
 			cw += paddingRight + borderWidth;
 			ch = y + maxLineHeight + paddingBottom + borderHeight;
 
@@ -625,9 +625,9 @@ class Flow extends Sprite {
 			var endX = cw - (paddingRight + borderWidth);
 			var xmin : Float = startX, xmax : Float = endX;
 			var midSpace = 0;
-			for( i in 0...childs.length ) {
+			for( i in 0...children.length ) {
 				var p = properties[i];
-				if( p.isAbsolute || !childs[i].visible ) continue;
+				if( p.isAbsolute || !children[i].visible ) continue;
 				if( p.isBreak ) {
 					xmin = startX;
 					xmax = endX;
@@ -647,9 +647,9 @@ class Flow extends Sprite {
 				case Middle:
 					if( midSpace == 0 ) {
 						var remSize = p.calculatedWidth;
-						for( j in i + 1...childs.length ) {
+						for( j in i + 1...children.length ) {
 							var p = properties[j];
-							if( p.isAbsolute || !childs[j].visible ) continue;
+							if( p.isAbsolute || !children[j].visible ) continue;
 							if( p.isBreak ) break;
 							remSize += horizontalSpacing + p.calculatedWidth;
 						}
@@ -666,7 +666,7 @@ class Flow extends Sprite {
 					px = xmin;
 					xmin += p.calculatedWidth + horizontalSpacing;
 				}
-				childs[i].x = px + p.offsetX + p.paddingLeft;
+				children[i].x = px + p.offsetX + p.paddingLeft;
 			}
 
 		} else {
@@ -691,7 +691,7 @@ class Flow extends Sprite {
 				for( i in lastIndex...maxIndex ) {
 					var p = properties[i];
 					if( p.isAbsolute ) continue;
-					var c = childs[i];
+					var c = children[i];
 					if( !c.visible ) continue;
 					var a = p.horizontalAlign != null ? p.horizontalAlign : halign;
 					c.x = x + p.offsetX + p.paddingLeft;
@@ -706,11 +706,11 @@ class Flow extends Sprite {
 				lastIndex = maxIndex;
 			}
 
-			for( i in 0...childs.length ) {
+			for( i in 0...children.length ) {
 				var p = properties[i];
 				if( p.isAbsolute ) continue;
 
-				var c = childs[i];
+				var c = children[i];
 				if( !c.visible ) continue;
 
 				c.constraintSize(
@@ -740,7 +740,7 @@ class Flow extends Sprite {
 				y += verticalSpacing;
 				if( p.calculatedWidth > maxColWidth ) maxColWidth = p.calculatedWidth;
 			}
-			alignLine(childs.length);
+			alignLine(children.length);
 			ch += paddingBottom + borderHeight;
 			cw = x + maxColWidth + paddingRight + borderWidth;
 
@@ -750,9 +750,9 @@ class Flow extends Sprite {
 			var endY = ch - (paddingBottom + borderHeight);
 			var ymin : Float = startY, ymax : Float = endY;
 			var midSpace = 0;
-			for( i in 0...childs.length ) {
+			for( i in 0...children.length ) {
 				var p = properties[i];
-				if( p.isAbsolute || !childs[i].visible ) continue;
+				if( p.isAbsolute || !children[i].visible ) continue;
 				if( p.isBreak ) {
 					ymin = startY;
 					ymax = endY;
@@ -772,9 +772,9 @@ class Flow extends Sprite {
 				case Middle:
 					if( midSpace == 0 ) {
 						var remSize = p.calculatedHeight;
-						for( j in i + 1...childs.length ) {
+						for( j in i + 1...children.length ) {
 							var p = properties[j];
-							if( p.isAbsolute || !childs[j].visible ) continue;
+							if( p.isAbsolute || !children[j].visible ) continue;
 							if( p.isBreak ) break;
 							remSize += verticalSpacing + p.calculatedHeight;
 						}
@@ -791,7 +791,7 @@ class Flow extends Sprite {
 					py = ymin;
 					ymin += p.calculatedHeight + verticalSpacing;
 				}
-				childs[i].y = py + p.offsetY + p.paddingTop;
+				children[i].y = py + p.offsetY + p.paddingTop;
 			}
 		}
 
@@ -818,7 +818,7 @@ class Flow extends Sprite {
 
 		if( debug ) {
 			debugGraphics.clear();
-			if( debugGraphics != childs[childs.length - 1] ) {
+			if( debugGraphics != children[children.length - 1] ) {
 				addChild(debugGraphics); // always on-top
 				needReflow = false;
 			}
@@ -827,9 +827,9 @@ class Flow extends Sprite {
 				debugGraphics.drawRect(paddingLeft + borderWidth, paddingTop + borderHeight, innerWidth, innerHeight);
 			}
 			debugGraphics.lineStyle(1, 0x0080FF);
-			for( i in 0...childs.length ) {
+			for( i in 0...children.length ) {
 				var p = properties[i];
-				var c = childs[i];
+				var c = children[i];
 				if( p.isAbsolute || !c.visible ) continue;
 				debugGraphics.drawRect(c.x, c.y, p.calculatedWidth, p.calculatedHeight);
 			}

+ 18 - 18
h2d/Layers.hx

@@ -29,16 +29,16 @@ class Layers extends Sprite {
 		}
 		// new layer
 		while( layer >= layerCount )
-			layersIndexes[layerCount++] = childs.length;
+			layersIndexes[layerCount++] = children.length;
 		super.addChildAt(s,layersIndexes[layer]);
 		for( i in layer...layerCount )
 			layersIndexes[i]++;
 	}
 
 	override function removeChild( s : Sprite ) {
-		for( i in 0...childs.length ) {
-			if( childs[i] == s ) {
-				childs.splice(i, 1);
+		for( i in 0...children.length ) {
+			if( children[i] == s ) {
+				children.splice(i, 1);
 				if( s.allocated ) s.onRemove();
 				s.parent = null;
 				var k = layerCount - 1;
@@ -52,8 +52,8 @@ class Layers extends Sprite {
 	}
 
 	public function under( s : Sprite ) {
-		for( i in 0...childs.length )
-			if( childs[i] == s ) {
+		for( i in 0...children.length )
+			if( children[i] == s ) {
 				var pos = 0;
 				for( l in layersIndexes )
 					if( l > i )
@@ -62,22 +62,22 @@ class Layers extends Sprite {
 						pos = l;
 				var p = i;
 				while( p > pos ) {
-					childs[p] = childs[p - 1];
+					children[p] = children[p - 1];
 					p--;
 				}
-				childs[pos] = s;
+				children[pos] = s;
 				break;
 			}
 	}
 
 	public function over( s : Sprite ) {
-		for( i in 0...childs.length )
-			if( childs[i] == s ) {
+		for( i in 0...children.length )
+			if( children[i] == s ) {
 				for( l in layersIndexes )
 					if( l > i ) {
 						for( p in i...l-1 )
-							childs[p] = childs[p + 1];
-						childs[l - 1] = s;
+							children[p] = children[p + 1];
+						children[l - 1] = s;
 						break;
 					}
 				break;
@@ -91,7 +91,7 @@ class Layers extends Sprite {
 		else {
 			var start = layer == 0 ? 0 : layersIndexes[layer - 1];
 			var max = layersIndexes[layer];
-			a = childs.slice(start, max);
+			a = children.slice(start, max);
 		}
 		return new hxd.impl.ArrayIterator(a);
 	}
@@ -103,18 +103,18 @@ class Layers extends Sprite {
 		if( start == max )
 			return;
 		var pos = start;
-		var ymax = childs[pos++].y;
+		var ymax = children[pos++].y;
 		while( pos < max ) {
-			var c = childs[pos];
+			var c = children[pos];
 			if( c.y < ymax ) {
 				var p = pos - 1;
 				while( p >= start ) {
-					var c2 = childs[p];
+					var c2 = children[p];
 					if( c.y >= c2.y ) break;
-					childs[p + 1] = c2;
+					children[p + 1] = c2;
 					p--;
 				}
-				childs[p + 1] = c;
+				children[p + 1] = c;
 			} else
 				ymax = c.y;
 			pos++;

+ 3 - 3
h2d/Scene.hx

@@ -302,8 +302,8 @@ class Scene extends Layers implements h3d.IDrawable implements hxd.SceneEvents.I
 		}
 		inline function indexOf(p:Sprite, i:Sprite) {
 			var id = -1;
-			for( k in 0...p.childs.length )
-				if( p.childs[k] == i ) {
+			for( k in 0...p.children.length )
+				if( p.children[k] == i ) {
 					id = k;
 					break;
 				}
@@ -378,7 +378,7 @@ class Scene extends Layers implements h3d.IDrawable implements hxd.SceneEvents.I
 		ctx.time += ctx.elapsedTime;
 		ctx.globalAlpha = alpha;
 		sync(ctx);
-		if( childs.length == 0 ) return;
+		if( children.length == 0 ) return;
 		ctx.begin();
 		ctx.drawScene();
 		ctx.end();

+ 52 - 31
h2d/Sprite.hx

@@ -6,7 +6,7 @@ class Sprite {
 
 	static var nullDrawable : h2d.Drawable;
 
-	var childs : Array<Sprite>;
+	var children : Array<Sprite>;
 	var parentContainer : Sprite;
 	public var parent(default, null) : Sprite;
 	public var numChildren(get, never) : Int;
@@ -38,7 +38,7 @@ class Sprite {
 		x = 0; y = 0; scaleX = 1; scaleY = 1; rotation = 0;
 		posChanged = parent != null;
 		visible = true;
-		childs = [];
+		children = [];
 		if( parent != null )
 			parent.addChild(this);
 	}
@@ -82,6 +82,27 @@ class Sprite {
 		return out;
 	}
 
+	public function find<T>( f : Sprite -> Null<T> ) : Null<T> {
+		var v = f(this);
+		if( v != null )
+			return v;
+		for( o in children ) {
+			var v = o.find(f);
+			if( v != null ) return v;
+		}
+		return null;
+	}
+
+	public function findAll<T>( f : Sprite -> Null<T>, ?arr : Array<T> ) : Array<T> {
+		if( arr == null ) arr = [];
+		var v = f(this);
+		if( v != null )
+			arr.push(v);
+		for( o in children )
+			o.findAll(f,arr);
+		return arr;
+	}
+
 	function set_filter(f) {
 		if( filter != null && allocated ) filter.unbind(this);
 		filter = f;
@@ -92,23 +113,23 @@ class Sprite {
 	function getBoundsRec( relativeTo : Sprite, out : h2d.col.Bounds, forSize : Bool ) {
 		if( posChanged ) {
 			calcAbsPos();
-			for( c in childs )
+			for( c in children )
 				c.posChanged = true;
 			posChanged = false;
 		}
-		var n = childs.length;
+		var n = children.length;
 		if( n == 0 ) {
 			out.empty();
 			return;
 		}
 		if( n == 1 ) {
-			var c = childs[0];
+			var c = children[0];
 			if( c.visible ) c.getBoundsRec(relativeTo, out,forSize) else out.empty();
 			return;
 		}
 		var xmin = hxd.Math.POSITIVE_INFINITY, ymin = hxd.Math.POSITIVE_INFINITY;
 		var xmax = hxd.Math.NEGATIVE_INFINITY, ymax = hxd.Math.NEGATIVE_INFINITY;
-		for( c in childs ) {
+		for( c in children ) {
 			if( !c.visible ) continue;
 			c.getBoundsRec(relativeTo, out, forSize);
 			if( out.xMin < xmin ) xmin = out.xMin;
@@ -176,7 +197,7 @@ class Sprite {
 
 	public function getSpritesCount() {
 		var k = 0;
-		for( c in childs )
+		for( c in children )
 			k += c.getSpritesCount() + 1;
 		return k;
 	}
@@ -218,12 +239,12 @@ class Sprite {
 	}
 
 	public function addChild( s : Sprite ) {
-		addChildAt(s, childs.length);
+		addChildAt(s, children.length);
 	}
 
 	public function addChildAt( s : Sprite, pos : Int ) {
 		if( pos < 0 ) pos = 0;
-		if( pos > childs.length ) pos = childs.length;
+		if( pos > children.length ) pos = children.length;
 		var p = this;
 		while( p != null ) {
 			if( p == s ) throw "Recursive addChild";
@@ -236,7 +257,7 @@ class Sprite {
 			s.parent.removeChild(s);
 			s.allocated = old;
 		}
-		childs.insert(pos, s);
+		children.insert(pos, s);
 		if( !allocated && s.allocated )
 			s.onRemove();
 		s.parent = this;
@@ -258,7 +279,7 @@ class Sprite {
 
 	// called when we're allocated already but moved in hierarchy
 	function onParentChanged() {
-		for( c in childs )
+		for( c in children )
 			c.onParentChanged();
 	}
 
@@ -267,7 +288,7 @@ class Sprite {
 		allocated = true;
 		if( filter != null )
 			filter.bind(this);
-		for( c in childs )
+		for( c in children )
 			c.onAdd();
 	}
 
@@ -276,7 +297,7 @@ class Sprite {
 		allocated = false;
 		if( filter != null )
 			filter.unbind(this);
-		for( c in childs )
+		for( c in children )
 			c.onRemove();
 	}
 
@@ -290,7 +311,7 @@ class Sprite {
 	}
 
 	public function removeChild( s : Sprite ) {
-		if( childs.remove(s) ) {
+		if( children.remove(s) ) {
 			if( s.allocated ) s.onRemove();
 			s.parent = null;
 			if( s.parentContainer != null ) s.setParentContainer(null);
@@ -301,7 +322,7 @@ class Sprite {
 
 	function setParentContainer( c : Sprite ) {
 		parentContainer = c;
-		for( s in childs )
+		for( s in children )
 			s.setParentContainer(c);
 	}
 
@@ -337,9 +358,9 @@ class Sprite {
 		}
 
 		lastFrame = ctx.frame;
-		var p = 0, len = childs.length;
+		var p = 0, len = children.length;
 		while( p < len ) {
-			var c = childs[p];
+			var c = children[p];
 			if( c == null )
 				break;
 			if( c.lastFrame != ctx.frame ) {
@@ -348,9 +369,9 @@ class Sprite {
 			}
 			// if the object was removed, let's restart again.
 			// our lastFrame ensure that no object will get synched twice
-			if( childs[p] != c ) {
+			if( children[p] != c ) {
 				p = 0;
-				len = childs.length;
+				len = children.length;
 			} else
 				p++;
 		}
@@ -360,7 +381,7 @@ class Sprite {
 		if( parent != null ) parent.syncPos();
 		if( posChanged ) {
 			calcAbsPos();
-			for( c in childs )
+			for( c in children )
 				c.posChanged = true;
 			posChanged = false;
 		}
@@ -580,7 +601,7 @@ class Sprite {
 		ctx.pushTarget(t, xMin, yMin, width, height);
 		ctx.engine.clear(0);
 
-		// reset transform and update childs
+		// reset transform and update children
 		var oldAlpha = ctx.globalAlpha;
 		var shader = @:privateAccess ctx.baseShader;
 		var oldA = shader.filterMatrixA.clone();
@@ -600,7 +621,7 @@ class Sprite {
 		shader.filterMatrixB.set(invB, invD, invY);
 		ctx.globalAlpha = 1;
 		draw(ctx);
-		for( c in childs )
+		for( c in children )
 			c.drawRec(ctx);
 		ctx.flush();
 
@@ -637,7 +658,7 @@ class Sprite {
 			// only sync anim, don't update() (prevent any event from occuring during draw())
 			// if( currentAnimation != null ) currentAnimation.sync();
 			calcAbsPos();
-			for( c in childs )
+			for( c in children )
 				c.posChanged = true;
 			posChanged = false;
 		}
@@ -647,12 +668,12 @@ class Sprite {
 			var old = ctx.globalAlpha;
 			ctx.globalAlpha *= alpha;
 			if( ctx.front2back ) {
-				var nchilds = childs.length;
-				for (i in 0...nchilds) childs[nchilds - 1 - i].drawRec(ctx);
+				var nchilds = children.length;
+				for (i in 0...nchilds) children[nchilds - 1 - i].drawRec(ctx);
 				draw(ctx);
 			} else {
 				draw(ctx);
-				for( c in childs ) c.drawRec(ctx);
+				for( c in children ) c.drawRec(ctx);
 			}
 			ctx.globalAlpha = old;
 		}
@@ -708,22 +729,22 @@ class Sprite {
 	}
 
 	public inline function getChildAt( n ) {
-		return childs[n];
+		return children[n];
 	}
 
 	public function getChildIndex( s ) {
-		for( i in 0...childs.length )
-			if( childs[i] == s )
+		for( i in 0...children.length )
+			if( children[i] == s )
 				return i;
 		return -1;
 	}
 
 	inline function get_numChildren() {
-		return childs.length;
+		return children.length;
 	}
 
 	public inline function iterator() {
-		return new hxd.impl.ArrayIterator(childs);
+		return new hxd.impl.ArrayIterator(children);
 	}
 
 	function toString() {

+ 1 - 1
h3d/mat/BaseMaterial.hx

@@ -78,7 +78,7 @@ class BaseMaterial implements h3d.impl.Serializable {
 
 	public function clone( ?m : BaseMaterial ) : BaseMaterial {
 		if( m == null ) m = new BaseMaterial();
-		m.mainPass.loadProps(mainPass);
+		m.mainPass.load(mainPass);
 		// DO NOT clone passes (it's up to the superclass to recreate the passes + shaders)
 		m.name = name;
 		return m;

+ 1 - 1
h3d/mat/MaterialDatabase.hx

@@ -18,7 +18,7 @@ class MaterialDatabase {
 	}
 
 	function load() {
-		db = try haxe.Json.parse(hxd.res.Loader.currentInstance.load(file).toText()) catch( e : hxd.res.NotFound ) {};
+		db = try haxe.Json.parse(hxd.res.Loader.currentInstance.load(file).toText()) catch( e : hxd.res.NotFound ) { type : "materialDB" };
 	}
 
 	function save() {

+ 25 - 9
h3d/mat/MaterialScript.hx

@@ -19,33 +19,48 @@ class MaterialScript extends MaterialSetup {
 		return v;
 	}
 
-
 	function initVars() {
-		#if js
-		variables.set("Element", js.jquery.JQuery);
-		#end
 		variables.set("BlendMode", h3d.mat.BlendMode);
 		variables.set("Blend", h3d.mat.Data.Blend);
 		variables.set("Face", h3d.mat.Data.Face);
 		variables.set("Compare", h3d.mat.Data.Compare);
 		variables.set("Operation", h3d.mat.Data.Operation);
+		variables.set("this", this);
+		#if js
+		variables.set("Element", js.jquery.JQuery);
+		#end
+	}
+
+	function call( name : String, args : Array<Dynamic> ) : Dynamic {
+		#if hscript
+		try {
+			return Reflect.callMethod(this, getVar(name), args);
+		} catch( e : hscript.Expr.Error ) {
+			onError(Std.string(e));
+			return null;
+		}
+		#else
+		throw "Can't call " + name;
+		#end
 	}
 
-	#if hscript
 	override function getDefaults(?type:String):Any {
-		return try getVar("getDefaults")(type) catch( e : hscript.Expr.Error ) { onError(Std.string(e)); {}; }
+		return call("getDefaults", [type]);
 	}
 
 	override function applyProps(m:Material) {
-		try getVar("applyProps")(m) catch( e : hscript.Expr.Error ) onError(Std.string(e));
+		return call("applyProps", [m]);
+	}
+
+	override function initModelMaterial(material:Material) {
+		return call("initModelMaterial", [material]);
 	}
 
 	#if js
 	override function editMaterial( props : Any ) {
-		return try getVar("editMaterial")(props) catch( e : hscript.Expr.Error) { onError(Std.string(e)); new js.jquery.JQuery(); }
+		return call("editMaterial", [props]);
 	}
 	#end
-	#end
 
 	public function load( script : String, ?fileName : String ) {
 		#if !hscript
@@ -54,6 +69,7 @@ class MaterialScript extends MaterialSetup {
 		if( fileName == null ) fileName = "Renderer.hx";
 		this.fileName = fileName;
 		var parser = new hscript.Parser();
+		parser.allowTypes = true;
 		var expr = try parser.parseString(script, fileName) catch( e : hscript.Expr.Error ) { onError(Std.string(e)); return; }
 		var interp = new hscript.Interp();
 		variables = interp.variables;

+ 22 - 22
h3d/mat/MaterialSetup.hx

@@ -65,28 +65,6 @@ class MaterialSetup {
 		return props;
 	}
 
-	#if js
-	public function editMaterial( props : Any ) {
-		return new js.jquery.JQuery('
-			<dl>
-				<dt>Kind</dt>
-				<dd>
-					<select field="kind">
-						<option value="Opaque">Opaque</option>
-						<option value="Alpha">Alpha</option>
-						<option value="AlphaKill">AlphaKill</option>
-						<option value="Add">Add</option>
-						<option value="SoftAdd">SoftAdd</option>
-					</select>
-				</dd>
-				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
-				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
-				<dt>Lighted</dt><dd><input type="checkbox" field="lighted"/></dd>
-			</dl>
-		');
-	}
-	#end
-
 	public function applyProps( m : Material ) {
 		var props : DefaultProps = m.props;
 		var mainPass = m.mainPass;
@@ -119,6 +97,28 @@ class MaterialSetup {
 		if( m.shadows ) m.getPass("shadow").culling = mainPass.culling;
 	}
 
+	#if js
+	public function editMaterial( props : Any ) {
+		return new js.jquery.JQuery('
+			<dl>
+				<dt>Kind</dt>
+				<dd>
+					<select field="kind">
+						<option value="Opaque">Opaque</option>
+						<option value="Alpha">Alpha</option>
+						<option value="AlphaKill">AlphaKill</option>
+						<option value="Add">Add</option>
+						<option value="SoftAdd">SoftAdd</option>
+					</select>
+				</dd>
+				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
+				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
+				<dt>Lighted</dt><dd><input type="checkbox" field="lighted"/></dd>
+			</dl>
+		');
+	}
+	#end
+
 	public static var current = new MaterialSetup("Default");
 
 }

+ 2 - 2
h3d/mat/Pass.hx

@@ -44,7 +44,7 @@ class Pass implements h3d.impl.Serializable {
 		colorMask = 15;
 	}
 
-	public function loadProps( p : Pass ) {
+	public function load( p : Pass ) {
 		name = p.name;
 		passId = p.passId;
 		bits = p.bits;
@@ -62,7 +62,7 @@ class Pass implements h3d.impl.Serializable {
 		colorMask = p.colorMask;
 		if (p.stencil != null) {
 			if (stencil == null) stencil = new Stencil();
-			stencil.loadProps(p.stencil);
+			stencil.load(p.stencil);
 		}
 	}
 

+ 1 - 1
h3d/mat/Stencil.hx

@@ -92,7 +92,7 @@ class Stencil implements h3d.impl.Serializable {
 		return s;
 	}
 
-	public function loadProps(s : Stencil) {
+	public function load(s : Stencil) {
 		frontRefBits = s.frontRefBits;
 		backRefBits = s.backRefBits;
 		opBits = s.opBits;

+ 1 - 1
h3d/parts/GpuParticles.hx

@@ -112,7 +112,7 @@ class GpuPartGroup {
 
 	public var name : String;
 	public var enable = true;
-	public var material : {};
+	public var material = {};
 	public var sortMode(default, set) : GpuSortMode = None;
 
 	public var nparts(default, set) : Int 		= 100;

+ 21 - 0
h3d/scene/Object.hx

@@ -166,6 +166,27 @@ class Object implements h3d.impl.Serializable {
 		return null;
 	}
 
+	public function find<T>( f : Object -> Null<T> ) : Null<T> {
+		var v = f(this);
+		if( v != null )
+			return v;
+		for( o in children ) {
+			var v = o.find(f);
+			if( v != null ) return v;
+		}
+		return null;
+	}
+
+	public function findAll<T>( f : Object -> Null<T>, ?arr : Array<T> ) : Array<T> {
+		if( arr == null ) arr = [];
+		var v = f(this);
+		if( v != null )
+			arr.push(v);
+		for( o in children )
+			o.findAll(f,arr);
+		return arr;
+	}
+
 	public function getMaterials( ?a : Array<h3d.mat.Material> ) {
 		if( a == null ) a = [];
 		for( o in children )

+ 3 - 1
hxd/fs/LocalFileSystem.hx

@@ -1,6 +1,6 @@
 package hxd.fs;
 
-#if (air3 || sys)
+#if (air3 || sys || nodejs)
 
 @:allow(hxd.fs.LocalFileSystem)
 @:access(hxd.fs.LocalFileSystem)
@@ -226,6 +226,8 @@ private class LocalEntry extends FileEntry {
 		var ctx = new flash.system.LoaderContext();
 		ctx.imageDecodingPolicy = ON_LOAD;
 		loader.load(new flash.net.URLRequest(file.url), ctx);
+		#elseif nodejs
+		throw "Not implemented";
 		#else
 		var bmp = new hxd.res.Image(this).toBitmap();
 		onLoaded(new hxd.fs.LoadedBitmap(bmp));