Nicolas Cannasse 11 years ago
parent
commit
402b48b629
22 changed files with 1323 additions and 276 deletions
  1. 86 36
      h2d/Drawable.hx
  2. 6 0
      h2d/Sprite.hx
  3. 19 0
      h2d/SpriteBatch.hx
  4. 1 1
      h2d/Tile.hx
  5. 3 0
      h3d/Buffer.hx
  6. 28 11
      h3d/Engine.hx
  7. 11 1
      h3d/Vector.hx
  8. 33 3
      h3d/impl/Driver.hx
  9. 837 146
      h3d/impl/GlDriver.hx
  10. 85 18
      h3d/impl/Shader.hx
  11. 5 0
      h3d/mat/Data.hx
  12. 10 1
      h3d/mat/MeshMaterial.hx
  13. 3 0
      h3d/scene/Scene.hx
  14. 21 6
      hxd/BitmapData.hx
  15. 43 0
      hxd/ByteConversions.hx
  16. 18 0
      hxd/BytesBuffer.hx
  17. 30 7
      hxd/Math.hx
  18. 54 9
      hxd/Pixels.hx
  19. 8 26
      hxd/Stage.hx
  20. 14 9
      hxd/System.hx
  21. 1 1
      hxd/res/Embed.hx
  22. 7 1
      hxd/res/FileTree.hx

+ 86 - 36
h2d/Drawable.hx

@@ -83,18 +83,12 @@ private class DrawableShader extends h3d.impl.Shader {
 	
 	#elseif (js || cpp)
 	
+	
 	public var hasColorKey : Bool;
 	
 	// not supported
-	public var skew : Float;
 	public var sinusDeform : h3d.Vector;
-	public var hasAlphaMap : Bool;
-	public var hasMultMap : Bool;
-	public var multMap : h3d.mat.Texture;
-	public var multUV : h3d.Vector;
-	public var multMapFactor : Float;
-	public var alphaMap : h3d.mat.Texture;
-	public var alphaUV : h3d.Vector;
+		
 	// --
 	
 	public var filter : Bool;
@@ -103,11 +97,14 @@ private class DrawableShader extends h3d.impl.Shader {
 	public var hasAlpha : Bool;
 	public var hasVertexAlpha : Bool;
 	public var hasVertexColor : Bool;
+	public var hasAlphaMap : Bool;
+	public var hasMultMap : Bool;
+	public var isAlphaPremul : Bool;
 	
-	override function customSetup(driver:h3d.impl.GlDriver) {
-		driver.setupTexture(tex, None, filter ? Linear : Nearest, tileWrap ? Repeat : Clamp);
-	}
-	
+	/**
+	 * This is the constant set, they are set / compiled for first draw and will enabled on all render thereafter
+	 * 
+	 */
 	override function getConstants( vertex : Bool ) {
 		var cst = [];
 		if( vertex ) {
@@ -124,6 +121,9 @@ private class DrawableShader extends h3d.impl.Shader {
 		}
 		if( hasVertexAlpha ) cst.push("#define hasVertexAlpha");
 		if( hasVertexColor ) cst.push("#define hasVertexColor");
+		if( hasAlphaMap ) cst.push("#define hasAlphaMap");
+		if( hasMultMap ) cst.push("#define hasMultMap");
+		if( isAlphaPremul ) cst.push("#define isAlphaPremul");
 		return cst.join("\n");
 	}
 	
@@ -145,7 +145,7 @@ private class DrawableShader extends h3d.impl.Shader {
 		#end
 		uniform vec3 matA;
 		uniform vec3 matB;
-		uniform lowp float zValue;
+		uniform float zValue;
 		
         #if hasUVPos
 		uniform vec2 uvPos;
@@ -154,10 +154,10 @@ private class DrawableShader extends h3d.impl.Shader {
 		uniform vec2 uvScale;
 		#end
 		
-		varying lowp vec2 tuv;
+		varying vec2 tuv;
 
 		void main(void) {
-			vec3 spos = vec3(pos.xy, 1.0);
+			vec3 spos = vec3(pos.x,pos.y, 1.0);
 			#if hasSize
 				spos = spos * size;
 			#end
@@ -167,7 +167,7 @@ private class DrawableShader extends h3d.impl.Shader {
 			tmp.z = zValue;
 			tmp.w = 1.;
 			gl_Position = tmp;
-			vec2 t = uv;
+			lowp vec2 t = uv;
 			#if hasUVScale
 				t *= uvScale;
 			#end
@@ -187,43 +187,72 @@ private class DrawableShader extends h3d.impl.Shader {
 	
 	static var FRAGMENT = "
 	
-		varying lowp vec2 tuv;
+		varying vec2 tuv;
 		uniform sampler2D tex;
 		
 		#if hasVertexAlpha
-		varying lowp float talpha;
+		varying float talpha;
 		#end
+		
 		#if hasVertexColor
-		varying lowp vec4 tcolor;
+		varying vec4 tcolor;
+		#end
+		
+		#if hasAlphaMap
+			uniform vec4 alphaUV;
+			uniform sampler2D alphaMap;
+		#end
+		
+		#if hasMultMap
+			uniform float multMapFactor;
+			uniform vec4 multUV;
+			uniform sampler2D multMap;
 		#end
 		
-		uniform lowp float alpha;
-		uniform lowp vec3 colorKey/*byte4*/;
+		uniform float alpha;
+		uniform vec3 colorKey/*byte4*/;
 	
-		uniform lowp vec4 colorAdd;
-		uniform lowp vec4 colorMul;
-		uniform mediump mat4 colorMatrix;
+		uniform vec4 colorAdd;
+		uniform vec4 colorMul;
+		uniform mat4 colorMatrix;
 
 		void main(void) {
-			lowp vec4 col = texture2D(tex, tuv);
+			vec4 col = texture2D(tex, tuv).rgba;
+			
 			#if killAlpha
-				if( c.a - 0.001 ) discard;
+				if( col.a - 0.001 <= 0.0 ) discard;
 			#end
+			
 			#if hasColorKey
-				lowp vec3 dc = col.rgb - colorKey;
-				if( dot(dc,dc) < 0.001 ) discard;
-			#end
-			#if hasAlpha
-				col.w *= alpha;
+				vec3 dc = col.rgb - colorKey;
+				if( dot(dc, dc) < 0.00001 ) discard;
 			#end
+			
+			#if isAlphaPremul
+				col.rgb /= col.a;
+			#end 
+			
 			#if hasVertexAlpha
 				col.a *= talpha;
-			#end
+			#end 
+			
 			#if hasVertexColor
 				col *= tcolor;
 			#end
+			
+			#if hasAlphaMap
+				col.a *= texture2D( alphaMap, tuv * alphaUV.zw + alphaUV.xy).r;
+			#end
+			
+			#if hasMultMap
+				col *= multMapFactor * texture2D(multMap,tuv * multUV.zw + multUV.xy);
+			#end
+			
+			#if hasAlpha
+				col.a *= alpha;
+			#end
 			#if hasColorMatrix
-				col = colorMatrix * col;
+				col *= colorMatrix;
 			#end
 			#if hasColorMul
 				col *= colorMul;
@@ -231,6 +260,11 @@ private class DrawableShader extends h3d.impl.Shader {
 			#if hasColorAdd
 				col += colorAdd;
 			#end
+			
+			#if isAlphaPremul
+				col.rgb *= col.a;
+			#end 
+			
 			gl_FragColor = col;
 		}
 			
@@ -248,7 +282,9 @@ class Drawable extends Sprite {
 	var shader : DrawableShader;
 	
 	public var alpha(get, set) : Float;
+	#if !openfl
 	public var skew(get, set) : Null<Float>;
+	#end
 	
 	public var filter(get, set) : Bool;
 	public var color(get, set) : h3d.Vector;
@@ -273,10 +309,11 @@ class Drawable extends Sprite {
 	function new(parent) {
 		super(parent);
 		shader = new DrawableShader();
+		writeAlpha = true;
+		blendMode = Normal;
 		shader.alpha = 1;
 		shader.zValue = 0;
 		writeAlpha = true;
-		blendMode = Normal;
 	}
 	
 	inline function get_alpha() {
@@ -294,6 +331,7 @@ class Drawable extends Sprite {
 		return b;
 	}
 	
+	#if !openfl
 	inline function get_skew() : Null<Float> {
 		return shader.skew;
 	}
@@ -301,6 +339,7 @@ class Drawable extends Sprite {
 	inline function set_skew(v : Null<Float> ) {
 		return shader.skew = skew;
 	}
+	#end
 
 	inline function get_multiplyFactor() {
 		return shader.multMapFactor;
@@ -400,13 +439,18 @@ class Drawable extends Sprite {
 		if( tile == null )
 			tile = core.nullTile;
 
+		var tex : h3d.mat.Texture = tile.getTexture();
+		tex.filter = filter ? Linear : Nearest;
+		
+		var isTexPremul = tex.flags.has(AlphaPremultiplied);
+		
 		switch( blendMode ) {
 		case Normal:
-			mat.blend(SrcAlpha, OneMinusSrcAlpha);
+			mat.blend(isTexPremul ? One : SrcAlpha, OneMinusSrcAlpha);
 		case None:
 			mat.blend(One, Zero);
 		case Add:
-			mat.blend(SrcAlpha, One);
+			mat.blend(isTexPremul ? One : SrcAlpha, One);
 		case SoftAdd:
 			mat.blend(OneMinusDstColor, One);
 		case Multiply:
@@ -458,6 +502,12 @@ class Drawable extends Sprite {
 		tmp.z = absY + tile.dx * matB + tile.dy * matD;
 		shader.matB = tmp;
 		shader.tex = tile.getTexture();
+		/*
+		shader.isAlphaPremul = isTexPremul 
+		&& (shader.hasAlphaMap || shader.hasAlpha || shader.hasMultMap 
+		|| shader.hasVertexAlpha || shader.hasVertexColor 
+		|| shader.colorMatrix != null || shader.colorAdd != null
+		|| shader.colorMul != null );*/
 		mat.shader = shader;
 		engine.selectMaterial(mat);
 	}

+ 6 - 0
h2d/Sprite.hx

@@ -15,6 +15,7 @@ class Sprite {
 	public var scaleY(default,set) : Float;
 	public var rotation(default, set) : Float;
 	public var visible : Bool;
+	public var name : String;
 
 	var matA : Float;
 	var matB : Float;
@@ -438,4 +439,9 @@ class Sprite {
 		return new hxd.impl.ArrayIterator(childs);
 	}
 
+	function toString() {
+		var c = Type.getClassName(Type.getClass(this));
+		return name == null ? c : name + "(" + c + ")";
+	}
+	
 }

+ 19 - 0
h2d/SpriteBatch.hx

@@ -1,5 +1,20 @@
 package h2d;
 
+private class ElementsIterator {
+	var e : BatchElement;
+	public inline function new(e) {
+		this.e = e;
+	}
+	public inline function hasNext() {
+		return e != null;
+	}
+	public inline function next() {
+		var n = e;
+		e = @:privateAccess e.next;
+		return n;
+	}
+}
+
 @:allow(h2d.SpriteBatch)
 class BatchElement {
 	public var x : Float;
@@ -192,5 +207,9 @@ class SpriteBatch extends Drawable {
 	public inline function isEmpty() {
 		return first == null;
 	}
+	
+	public inline function getElements() {
+		return new ElementsIterator(first);
+	}
 
 }

+ 1 - 1
h2d/Tile.hx

@@ -30,7 +30,7 @@ class Tile {
 		if( tex != null ) setTexture(tex);
 	}
 	
-	public function getTexture() {
+	public function getTexture() : h3d.mat.Texture {
 		return innerTex;
 	}
 	

+ 3 - 0
h3d/Buffer.hx

@@ -24,6 +24,8 @@ enum BufferFlag {
 }
 
 class Buffer {
+	public static var GUID = 0;
+	public var id : Int;
 
 	public var buffer(default,null) : h3d.impl.ManagedBuffer;
 	public var position(default,null) : Int;
@@ -32,6 +34,7 @@ class Buffer {
 	public var flags(default, null) : haxe.EnumFlags<BufferFlag>;
 	
 	public function new(vertices, stride, ?flags : Array<BufferFlag>) {
+		id = GUID++;
 		this.vertices = vertices;
 		this.flags = new haxe.EnumFlags();
 		if( flags != null )

+ 28 - 11
h3d/Engine.hx

@@ -3,7 +3,7 @@ import h3d.mat.Data;
 
 class Engine {
 
-	var driver : h3d.impl.Driver;
+	public var driver(default,null) : h3d.impl.Driver;
 	
 	public var mem(default,null) : h3d.impl.MemoryManager;
 
@@ -41,10 +41,11 @@ class Engine {
 		this.hardware = hardware;
 		this.antiAlias = aa;
 		this.autoResize = true;
-		#if openfl
-		hxd.Stage.openFLBoot(start);
+		
+		#if (!flash && openfl)
+			hxd.Stage.openFLBoot(start);
 		#else
-		start();
+			start();
 		#end
 	}
 	
@@ -54,10 +55,10 @@ class Engine {
 		realFps = stage.getFrameRate();
 		lastTime = haxe.Timer.stamp();
 		stage.addResizeEvent(onStageResize);
-		#if flash
-		driver = new h3d.impl.Stage3dDriver();
-		#elseif (js || cpp)
+		#if (js || cpp)
 		driver = new h3d.impl.GlDriver();
+		#elseif flash
+		driver = new h3d.impl.Stage3dDriver();
 		#else
 		throw "No driver";
 		#end
@@ -67,11 +68,18 @@ class Engine {
 	
 	static var CURRENT : Engine = null;
 	
-	public static function getCurrent() {
+	static inline function check() {
+		#if debug
+		if ( CURRENT == null ) throw "no current context, please do this operation after engine init/creation";
+		#end
+	}
+	
+	public static inline function getCurrent() {
+		check();
 		return CURRENT;
 	}
 	
-	public function setCurrent() {
+	public inline function setCurrent() {
 		CURRENT = this;
 	}
 
@@ -265,11 +273,19 @@ class Engine {
 		curProjMatrix = null;
 	}
 
-	public function setTarget( tex : h3d.mat.Texture, clearColor = 0 ) {
+	/**
+	 * Setus a render target to do off screen rendering, might be costly on low end devices
+     * setTarget to null when you're finished rendering to it.
+	 */
+	public function setTarget( tex : h3d.mat.Texture,  clearColor = 0 ) {
 		driver.setRenderTarget(tex, clearColor);
 	}
 
-	public function setRenderZone( x = 0, y = 0, width = -1, height = -1 ) {
+	/**
+	 * Sets up a scissored zone to eliminate pixels outside the given range.
+	 * Call with no parameters to reset to full viewport.
+	 */
+	public function setRenderZone( x = 0, y = 0, ?width = -1, ?height = -1 ) : Void {
 		driver.setRenderZone(x, y, width, height);
 	}
 
@@ -298,6 +314,7 @@ class Engine {
 			debugPoint = new Drawable(new h3d.prim.Plan2D(), new h3d.impl.Shaders.PointShader());
 			debugPoint.material.blend(SrcAlpha, OneMinusSrcAlpha);
 			debugPoint.material.depthWrite = false;
+			debugPoint.material.culling = None;
 		}
 		debugPoint.material.depthTest = depth ? h3d.mat.Data.Compare.LessEqual : h3d.mat.Data.Compare.Always;
 		debugPoint.shader.mproj = curProjMatrix;

+ 11 - 1
h3d/Vector.hx

@@ -1,6 +1,9 @@
 package h3d;
 using hxd.Math;
 
+/**
+	A 4 floats vector. Everytime a Vector is returned, it means a copy is created.
+**/
 class Vector {
 
 	public var x : Float;
@@ -74,12 +77,19 @@ class Vector {
 		return new Vector(x * k, y * k, z * k);
 	}
 
-	public function set(x,y,z,w=1.) {
+	public inline function set(x,y,z,w=1.) {
 		this.x = x;
 		this.y = y;
 		this.z = z;
 		this.w = w;
 	}
+	
+	public inline function load(v : Vector) {
+		this.x = v.x;
+		this.y = v.y;
+		this.z = v.z;
+		this.w = v.w;
+	}
 
 	public inline function scale3( f : Float ) {
 		x *= f;

+ 33 - 3
h3d/impl/Driver.hx

@@ -1,8 +1,34 @@
 package h3d.impl;
 
-typedef IndexBuffer = flash.display3D.IndexBuffer3D;
-typedef VertexBuffer = Stage3dDriver.VertexWrapper;
-typedef Texture = flash.display3D.textures.TextureBase;
+#if (flash&&!cpp&&!js)
+	typedef IndexBuffer = flash.display3D.IndexBuffer3D;
+	typedef VertexBuffer = Stage3dDriver.VertexWrapper;
+	typedef Texture = flash.display3D.textures.TextureBase;
+#elseif js
+	typedef IndexBuffer = js.html.webgl.Buffer;
+	@:publicFields
+	class GLVB {
+		var b : js.html.webgl.Buffer;
+		var stride : Int;
+		public function new(b = null, s = 0) { this.b = b; this.stride = s; };
+	}
+	typedef VertexBuffer = GLVB;
+	typedef Texture = js.html.webgl.Texture;
+#elseif cpp
+	typedef IndexBuffer = openfl.gl.GLBuffer;
+	@:publicFields
+	class GLVB {
+		var b : openfl.gl.GLBuffer;
+		var stride : Int;
+		public function new(b = null, s = 0) { this.b = b; this.stride = s; };
+	}
+	typedef VertexBuffer = GLVB;
+	typedef Texture = openfl.gl.GLTexture;
+#else
+	typedef IndexBuffer = Int;
+	typedef VertexBuffer = Int;
+	typedef Texture = Int;
+#end
 
 class Driver {
 	
@@ -43,6 +69,10 @@ class Driver {
 		return false;
 	}
 	
+	public function deleteShader(shader : Shader) {
+		
+	}
+
 	public function getShaderInputNames() : Array<String> {
 		return null;
 	}

File diff suppressed because it is too large
+ 837 - 146
h3d/impl/GlDriver.hx


+ 85 - 18
h3d/impl/Shader.hx

@@ -1,12 +1,16 @@
 package h3d.impl;
+
+
 #if macro
 import haxe.macro.Context;
+import haxe.macro.Type.Ref;
 #end
 
 #if flash
 typedef Shader = hxsl.Shader;
 #elseif (js || cpp)
 
+typedef ShaderLocation = #if js js.html.webgl.UniformLocation #else openfl.gl.GLUniformLocation #end;
 enum ShaderType {
 	Float;
 	Vec2;
@@ -21,14 +25,53 @@ enum ShaderType {
 	Byte4;
 	Struct( field : String, t : ShaderType );
 	Index( index : Int, t : ShaderType );
+	Elements( field : String, size:Null<Int>, t : ShaderType);//null means size in indefinite and will be context relative
 }
 
-typedef Uniform = { name : String, loc : #if js js.html.webgl.UniformLocation #else openfl.gl.GLUniformLocation #end, type : ShaderType, index : Int }
+@:publicFields
+class Uniform { 
+	var name : String;
+	var loc : Null<ShaderLocation>;
+	var type : ShaderType;
+	var index : Int;
+	
+	inline function new(n:String, l:ShaderLocation, t:ShaderType, i) {
+		if ( l == null) throw "assert";
+		name = n;
+		loc = l;
+		type = t;
+		index = i;
+	}
+}
+
+@:publicFields
+class Attribute {
+	var etype : Int;
+	var offset : Int; 
+	var index : Int;
+	var size : Int;
+	
+	var name : String;
+	var type : ShaderType;
+	
+	function new(n:String,t:ShaderType,e,o,i,s) {
+		name = n;
+		type = t;
+		etype = e;
+		offset = o;
+		index = i;
+		size = s;
+	}
+	
+	public function toString() {
+		return 'etype:$etype offset::$offset index:$index size:$size name:$name type:$type';
+	}
+}
 
 class ShaderInstance {
 
 	public var program : #if js js.html.webgl.Program #else openfl.gl.GLProgram #end;
-	public var attribs : Array<{ name : String, type : ShaderType, etype : Int, offset : Int, index : Int, size : Int }>;
+	public var attribs : Array<Attribute>;
 	public var uniforms : Array<Uniform>;
 	public var stride : Int;
 	public function new() {
@@ -51,6 +94,12 @@ class Shader {
 		return "";
 	}
 
+	public function delete() {
+		#if !macro
+			if( instance!=null)
+				h3d.Engine.getCurrent().driver.deleteShader(this);
+		#end
+	}
 }
 
 #else
@@ -70,6 +119,22 @@ class ShaderMacros {
 		var fields = Context.getBuildFields();
 		var hasVertex = false, hasFragment = false;
 		var r_uni = ~/uniform[ \t]+((lowp|mediump|highp)[ \t]+)?([A-Za-z0-9_]+)[ \t]+([A-Za-z0-9_]+)[ \t]*(\/\*([A-Za-z0-9_]+)\*\/)?/;
+		
+		var cl = Std.string(Context.getLocalClass());
+		//var allFields = Lambda.map( fields, function(t) return t.name).join(' ');
+		
+		function classHasField( c : haxe.macro.Type.Ref< haxe.macro.Type.ClassType> , name)
+		{
+			if ( c == null ) return false;
+			var o = c.get();
+			
+			return
+			if ( o.fields!=null && Lambda.exists( o.fields.get() , function(o) return o.name == name ))
+				true;
+			else if ( o.superClass == null ) false;
+			else classHasField( o.superClass.t , name);
+		}
+		
 		function addUniforms( code : String ) {
 			while( r_uni.match(code) ) {
 				var name = r_uni.matched(4);
@@ -88,32 +153,34 @@ class ShaderMacros {
 						continue;
 					throw "Unsupported type " + type;
 				}
-				if( code.charCodeAt(0) == '['.code )
-					t = macro : Array<$t>;
+								
+				if ( code.charCodeAt(0) == '['.code ) t = macro : Array<$t>;
+				if ( classHasField( Context.getLocalClass(), name ) )  continue;
+				
 				fields.push( {
-					name : name,
-					kind : FVar(t),
-					pos : pos,
-					access : [APublic],
-				});
+						name : name,
+						kind : FVar(t),
+						pos : pos,
+						access : [APublic],
+						meta:[{name:":keep",params:[],pos:pos}]
+					});
 			}
 		}
 		for( f in fields )
 			switch( [f.name, f.kind] ) {
-			case ["VERTEX", FVar(_,{ expr : EConst(CString(code)) }) ]:
-				hasVertex = true;
-				addUniforms(code);
-				f.meta.push( { name : ":keep", params : [], pos : pos } );
-			case ["FRAGMENT", FVar(_,{ expr : EConst(CString(code)) })]:
-				hasFragment = true;
-				addUniforms(code);
-				f.meta.push( { name : ":keep", params : [], pos : pos } );
-			default:
+				case ["VERTEX", FVar(_,{ expr : EConst(CString(code)) }) ]:
+					hasVertex = true;
+					addUniforms(code);
+				case ["FRAGMENT", FVar(_,{ expr : EConst(CString(code)) })]:
+					hasFragment = true;
+					addUniforms(code);
+				default:
 			}
 		if( !hasVertex )
 			haxe.macro.Context.error("Missing VERTEX shader", pos);
 		if( !hasFragment )
 			haxe.macro.Context.error("Missing FRAGMENT shader", pos);
+			
 		return fields;
 	}
 	

+ 5 - 0
h3d/mat/Data.hx

@@ -97,4 +97,9 @@ enum TextureFlags {
 		Inform that we will often perform upload operations on this texture
 	**/
 	Dynamic;
+	/**
+		Assumes that the color value of the texture is premultiplied by the alpha component.
+	**/
+	AlphaPremultiplied;
 }
+

+ 10 - 1
h3d/mat/MeshMaterial.hx

@@ -509,9 +509,12 @@ class MeshMaterial extends Material {
 	var mshader : MeshShader;
 	
 	public var texture : Texture;
-	public var glowTexture(get,set) : Texture;
+	
+	#if  flash
+	public var glowTexture(get, set) : Texture;
 	public var glowAmount(get, set) : Float;
 	public var glowColor(get, set) : h3d.Vector;
+	#end
 
 	public var useMatrixPos : Bool;
 	public var uvScale(get,set) : Null<h3d.Vector>;
@@ -543,7 +546,9 @@ class MeshMaterial extends Material {
 	
 	public var shadowMap(null, set) : ShadowMap;
 	
+	#if !openfl
 	public var volumeDecal(default, set) : DecalInfos;
+	#end
 	
 	public function new(texture) {
 		mshader = new MeshShader();
@@ -720,6 +725,7 @@ class MeshMaterial extends Material {
 		return mshader.glowTexture;
 	}
 
+	#if flash
 	inline function set_glowTexture(t) {
 		mshader.hasGlow = t != null;
 		if( t != null && mshader.glowAmount == null ) mshader.glowAmount = new h3d.Vector(1, 1, 1);
@@ -745,6 +751,7 @@ class MeshMaterial extends Material {
 	inline function set_glowColor(v) {
 		return mshader.glowAmount = v;
 	}
+	#end
 
 	inline function get_fog() {
 		return mshader.fog;
@@ -783,6 +790,7 @@ class MeshMaterial extends Material {
 		return v;
 	}
 	
+	#if !openfl
 	inline function set_volumeDecal( d : DecalInfos ) {
 		if( d != null ) {
 			mshader.isDecal = true;
@@ -793,6 +801,7 @@ class MeshMaterial extends Material {
 			mshader.isDecal = false;
 		return volumeDecal = d;
 	}
+	#end
 	
 	#if flash
 

+ 3 - 0
h3d/scene/Scene.hx

@@ -22,6 +22,9 @@ class Scene extends Object implements h3d.IDrawable {
 		return s;
 	}
 	
+	/**
+	 allow to customize render passes (for example, branch sub scene or 2d context)
+	 */
 	public function addPass(p,before=false) {
 		if( before )
 			prePasses.push(p);

+ 21 - 6
hxd/BitmapData.hx

@@ -1,6 +1,13 @@
 package hxd;
 
-private typedef InnerData = #if flash flash.display.BitmapData #elseif js js.html.ImageData #elseif cpp flash.display.BitmapData #else Int #end;
+private typedef InnerData = 
+#if (flash||openfl)
+	flash.display.BitmapData 
+#elseif js
+	js.html.ImageData 
+#else 
+	Int 
+#end;
 
 abstract BitmapData(InnerData) {
 
@@ -14,7 +21,7 @@ abstract BitmapData(InnerData) {
 	public var height(get, never) : Int;
 	
 	public inline function new(width:Int, height:Int) {
-		#if flash
+		#if (flash||openfl)
 		this = new flash.display.BitmapData(width, height, true, 0);
 		#else
 		throw "TODO";
@@ -22,7 +29,7 @@ abstract BitmapData(InnerData) {
 	}
 	
 	public inline function clear( color : Int ) {
-		#if flash
+		#if (flash||openfl)
 		this.fillRect(this.rect, color);
 		#else
 		throw "TODO";
@@ -115,7 +122,7 @@ abstract BitmapData(InnerData) {
 	}
 	
 	public inline function dispose() {
-		#if flash
+		#if (flash||openfl)
 		this.dispose();
 		#end
 	}
@@ -132,7 +139,7 @@ abstract BitmapData(InnerData) {
 	}
 	
 	public inline function getPixel( x : Int, y : Int ) : Int {
-		#if flash
+		#if ( flash || openfl )
 		return this.getPixel32(x, y);
 		#else
 		throw "TODO";
@@ -141,7 +148,7 @@ abstract BitmapData(InnerData) {
 	}
 
 	public inline function setPixel( x : Int, y : Int, c : Int ) {
-		#if flash
+		#if (flash||openfl)
 		this.setPixel32(x, y, c);
 		#else
 		throw "TODO";
@@ -175,6 +182,12 @@ abstract BitmapData(InnerData) {
 	static function nativeGetPixels( b : InnerData ) {
 		#if flash
 		return new Pixels(b.width, b.height, haxe.io.Bytes.ofData(b.getPixels(b.rect)), ARGB);
+		#elseif openfl
+		var bRect = b.rect;
+		var bPixels : haxe.io.Bytes = hxd.ByteConversions.byteArrayToBytes(b.getPixels(b.rect));
+		var p = new Pixels(b.width, b.height, bPixels, ARGB);
+		p.flags.set(AlphaPremultiplied);
+		return p;
 		#else
 		throw "TODO";
 		return null;
@@ -195,6 +208,8 @@ abstract BitmapData(InnerData) {
 			bytes.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		}
 		b.setPixels(b.rect, bytes);
+		#elseif (js || cpp)
+			b.setPixels(b.rect, flash.utils.ByteArray.fromBytes(pixels.bytes));
 		#else
 		throw "TODO";
 		return null;

+ 43 - 0
hxd/ByteConversions.hx

@@ -0,0 +1,43 @@
+package hxd;
+
+import haxe.io.Bytes;
+
+/**
+ * Tries to provide consistent access to haxe.io.bytes from any primitive
+ */
+class ByteConversions{
+
+	public static function byteArrayToBytes( v: flash.utils.ByteArray ) : haxe.io.Bytes {
+		return
+		#if flash
+		Bytes.ofData( v );
+		#elseif (js&&openfl)
+		{
+			var b :Bytes = Bytes.alloc(v.length);
+			for ( i in 0...v.length )
+				b.set(i,v[i]);
+			b;
+		};
+		#elseif (openfl)
+		v; 
+		#else
+		throw "unsupported on this platform";
+		#end
+	}
+	
+	#if js
+	public static function arrayBufferToBytes( v : js.html.ArrayBuffer ) : haxe.io.Bytes{
+		return byteArrayToBytes(flash.utils.ByteArray.nmeOfBuffer(v));
+	}
+	#end
+		
+	public static function bytesToByteArray( v: haxe.io.Bytes ) :  flash.utils.ByteArray {
+		#if flash
+		return v.getData();
+		#elseif openfl
+		return flash.utils.ByteArray.fromBytes(v);
+		#else
+		throw "unsupported on this platform";
+		#end
+	}
+}

+ 18 - 0
hxd/BytesBuffer.hx

@@ -15,6 +15,24 @@ abstract BytesBuffer(InnerData) {
 		#end
 	}
 	
+	public static inline function fromU8Array(arr:Array<Int>) {
+		var v = new BytesBuffer();
+		for ( i in 0...arr.length)
+			v.writeByte( arr[i] );
+		return v;
+	}
+	
+	public static inline function fromIntArray(arr:Array<Int>) {
+		var v = new BytesBuffer();
+		for ( i in 0...arr.length)
+			v.writeInt32(arr[i]);
+		return v;
+	}
+	
+	public inline function writeByte( v : Int ) {
+		this.writeByte(v&255);
+	}
+	
 	public inline function writeFloat( v : Float ) {
 		this.writeFloat(v);
 	}

+ 30 - 7
hxd/Math.hx

@@ -134,14 +134,11 @@ class Math {
 	public inline static function lerp(a:Float, b:Float, k:Float) {
 		return a + k * (b - a);
 	}
-	
+		
 	public inline static function bitCount(v:Int) {
-		var k = 0;
-		while( v != 0 ) {
-			k += v & 1;
-			v >>>= 1;
-		}
-		return k;
+		v = v - ((v >> 1) & 0x55555555);
+		v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+		return (((v + (v >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
 	}
 	
 	public static inline function distanceSq( dx : Float, dy : Float, dz = 0. ) {
@@ -205,4 +202,30 @@ class Math {
 	}
 	
 	
+	/**
+	 * takes an int , masks it and devide so that it safely maps 0...255 to 0...1.0
+	 * @paramv an int between 0 and 255 will be masked
+	 * @return a float between( 0 and 1)
+	 */
+	public static inline function b2f( v:Int ) :Float {
+		return (v&0xFF) * 0.0039215686274509803921568627451;
+	}
+	
+	/**
+	 * takes a float , clamps it and multipy so that it safely maps 0...1 to 0...255.0
+	 * @param	f a float
+	 * @return an int [0...255]
+	 */
+	public static inline function f2b( v:Float ) : Int {
+		return Std.int(clamp(v) * 255.0);
+	}
+	
+	/**
+	 * returns the modulo but always positive
+	 */
+	public static inline function umod( value : Int, modulo : Int ) {
+		var r = value % modulo;
+		return r >= 0 ? r : r + modulo;
+	}
+
 }

+ 54 - 9
hxd/Pixels.hx

@@ -1,16 +1,24 @@
 package hxd;
 
+enum Flags {
+	ReadOnly;
+	AlphaPremultiplied;
+}
+
 class Pixels {
 	public var bytes : haxe.io.Bytes;
 	public var format : PixelFormat;
 	public var width : Int;
 	public var height : Int;
+	public var offset : Int;
+	public var flags: haxe.EnumFlags<Flags>;
 	
-	public function new(width, height, bytes, format) {
+	public function new(width : Int, height : Int, bytes : haxe.io.Bytes, format : hxd.PixelFormat, offset = 0) {
 		this.width = width;
 		this.height = height;
 		this.bytes = bytes;
 		this.format = format;
+		this.offset = offset;
 	}
 		
 	public function makeSquare( ?copy : Bool ) {
@@ -20,7 +28,7 @@ class Pixels {
 		while( th < h ) th <<= 1;
 		if( w == tw && h == th ) return this;
 		var out = hxd.impl.Tmp.getBytes(tw * th * 4);
-		var p = 0, b = 0;
+		var p = 0, b = offset;
 		for( y in 0...h ) {
 			out.blit(p, bytes, b, w * 4);
 			p += w * 4;
@@ -32,22 +40,32 @@ class Pixels {
 			out.set(p++, 0);
 		if( copy )
 			return new Pixels(tw, th, out, format);
-		hxd.impl.Tmp.saveBytes(bytes);
+		if( !flags.has(ReadOnly) ) hxd.impl.Tmp.saveBytes(bytes);
 		bytes = out;
 		width = tw;
 		height = th;
 		return this;
 	}
-	
+
+	function copyInner() {
+		var old = bytes;
+		bytes = hxd.impl.Tmp.getBytes(width * height * 4);
+		bytes.blit(0, old, offset, width * height * 4);
+		offset = 0;
+		flags.unset(ReadOnly);
+	}
+
 	public function convert( target : PixelFormat ) {
 		if( format == target )
 			return;
+		if( flags.has(ReadOnly) )
+			copyInner();
 		switch( [format, target] ) {
 		case [BGRA, ARGB], [ARGB, BGRA]:
 			// reverse bytes
 			var mem = hxd.impl.Memory.select(bytes);
 			for( i in 0...width*height ) {
-				var p = i << 2;
+				var p = (i << 2) + offset;
 				var a = mem.b(p);
 				var r = mem.b(p+1);
 				var g = mem.b(p+2);
@@ -61,7 +79,7 @@ class Pixels {
 		case [BGRA, RGBA]:
 			var mem = hxd.impl.Memory.select(bytes);
 			for( i in 0...width*height ) {
-				var p = i << 2;
+				var p = (i << 2) + offset;
 				var b = mem.b(p);
 				var r = mem.b(p+2);
 				mem.wb(p, r);
@@ -72,13 +90,13 @@ class Pixels {
 		case [ARGB, RGBA]: {
 			var mem = hxd.impl.Memory.select(bytes);
 			for ( i in 0...width * height ) {
-				var p = i << 2;
+				var p = (i << 2) + offset;
 				var a = (mem.b(p));
 				
 				mem.wb(p, mem.b(p + 1));
 				mem.wb(p + 1, mem.b(p + 2));
 				mem.wb(p + 2, mem.b(p + 3));
-				mem.wb(p+3, a);				
+				mem.wb(p + 3, a);				
 			}
 			mem.end();
 		}
@@ -89,9 +107,36 @@ class Pixels {
 		format = target;
 	}
 	
+	public function getPixel(x, y) : Int {
+		var p = 4 * (y * width + x) + offset;
+		switch(format) {
+		case BGRA:
+			var u = 0;
+			u |= bytes.get( p	);
+			u |= bytes.get( p+1 )<<8;
+			u |= bytes.get( p+2 )<<16;
+			u |= bytes.get( p+3 )<<24;
+			return u;
+		case RGBA:
+			var u = 0;
+			u |= bytes.get( p	)<<16;
+			u |= bytes.get( p+1 )<<8;
+			u |= bytes.get( p+2 );
+			u |= bytes.get( p+3 )<<24;
+			return u;
+		case ARGB:
+			var u = 0;
+			u |= bytes.get( p	)<<24;
+			u |= bytes.get( p+1 )<<16;
+			u |= bytes.get( p+2 )<<8;
+			u |= bytes.get( p+3 );
+			return u;
+		}		
+	}
+	
 	public function dispose() {
 		if( bytes != null ) {
-			hxd.impl.Tmp.saveBytes(bytes);
+			if( !flags.has(ReadOnly) ) hxd.impl.Tmp.saveBytes(bytes);
 			bytes = null;
 		}
 	}

+ 8 - 26
hxd/Stage.hx

@@ -139,11 +139,19 @@ class Stage {
 	}
 	
 	inline function get_mouseLock() {
+		#if openfl
+		return false;
+		#else
 		return stage.mouseLock;
+		#end
 	}
 
 	inline function set_mouseLock(v) {
+		#if openfl
+		return false;
+		#else
 		return stage.mouseLock = v;
+		#end
 	}
 	
 	function onResize(_) {
@@ -349,32 +357,6 @@ class Stage {
 			callb();
 			return;
 		}
-		// init done by hand
-		var width = 750, height = 450, fps = 60, bgColor = 0x808080;
-		flash.Lib.create(
-			function() {
-				flash.Lib.current.stage.align = flash.display.StageAlign.TOP_LEFT;
-				flash.Lib.current.stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
-				flash.Lib.current.loaderInfo = flash.display.LoaderInfo.create (null);
-				callb();
-			},
-			width, height, fps, bgColor,
-			(true ? flash.Lib.HARDWARE : 0) |
-			(true ? flash.Lib.ALLOW_SHADERS : 0) |
-			(true ? flash.Lib.REQUIRE_SHADERS : 0) |
-			(false ? flash.Lib.DEPTH_BUFFER : 0) |
-			(false ? flash.Lib.STENCIL_BUFFER : 0) |
-			(true ? flash.Lib.RESIZABLE : 0) |
-			(false ? flash.Lib.BORDERLESS : 0) |
-			(false ? flash.Lib.VSYNC : 0) |
-			(false ? flash.Lib.FULLSCREEN : 0) |
-			(0 == 4 ? flash.Lib.HW_AA_HIRES : 0) |
-			(0 == 2 ? flash.Lib.HW_AA : 0),
-			"h3d", null
-			#if mobile
-			, null /* ScaledStage : TODO? */
-			#end
-		);
 	}
 
 #end

+ 14 - 9
hxd/System.hx

@@ -84,14 +84,18 @@ class System {
 		case TextInput: "ibeam";
 		case Hide: "auto";
 		case Custom(frames, speed, offsetX, offsetY):
-			var customCursor = new flash.ui.MouseCursorData();
-			var v = new flash.Vector();
-			for( f in frames ) v.push(f.toNative());
-			customCursor.data = v;
-			customCursor.frameRate = speed;
-			customCursor.hotSpot = new flash.geom.Point(offsetX, offsetY);
-			flash.ui.Mouse.registerCursor("custom", customCursor);
-			"custom";
+			#if openfl
+				throw "not supported on openFL for now";
+			#else 
+				var customCursor = new flash.ui.MouseCursorData();
+				var v = new flash.Vector();
+				for( f in frames ) v.push(f.toNative());
+				customCursor.data = v;
+				customCursor.frameRate = speed;
+				customCursor.hotSpot = new flash.geom.Point(offsetX, offsetY);
+				flash.ui.Mouse.registerCursor("custom", customCursor);
+				"custom";
+			#end
 		}
 		if( c == Hide ) flash.ui.Mouse.hide() else flash.ui.Mouse.show();
 	}
@@ -201,7 +205,8 @@ class System {
 	public static function setLoop( f : Void -> Void ) {
 		if( VIEW == null ) {
 			VIEW = new openfl.display.OpenGLView();
-			flash.Lib.current.addChild(VIEW);
+			VIEW.name = "glView";
+			flash.Lib.current.addChildAt(VIEW,0);
 		}
 		VIEW.render = function(_) if( f != null ) f();
 	}

+ 1 - 1
hxd/res/Embed.hx

@@ -18,7 +18,7 @@ class Embed {
 	}
 	
 	public static function doEmbedFont( name : String, file : String, chars : String ) {
-		if( Context.defined("flash") ) {
+		if( Context.defined("flash") || Context.defined("openfl") ) {
 			if( chars == null ) // convert char list to char range
 				chars = Charset.DEFAULT_CHARS.split("-").join("\\-");
 			var pos = Context.currentPos();

+ 7 - 1
hxd/res/FileTree.hx

@@ -16,6 +16,7 @@ class FileTree {
 	var options : EmbedOptions;
 	var isFlash : Bool;
 	var isJS : Bool;
+	var isCPP : Bool;
 	var embedTypes : Array<String>;
 	
 	public function new(dir) {
@@ -33,6 +34,7 @@ class FileTree {
 		pairedExt.set("xtra", ["fbx"]);
 		isFlash = Context.defined("flash");
 		isJS = Context.defined("js");
+		isCPP = Context.defined("cpp");
 	}
 	
 	public static function resolvePath( ?dir:String ) {
@@ -155,7 +157,7 @@ class FileTree {
 				kind : TDClass({ pack : ["flash","utils"], name : "ByteArray", params : [] }),
 			});
 			embedTypes.push("hxd._res." + name);
-		} else if( isJS ) {
+		} else if( isJS || isCPP ) {
 			Context.addResource(name, sys.io.File.getBytes(fullPath));
 			return true;
 		} else {
@@ -267,7 +269,11 @@ class FileTree {
 						ret : field.t,
 						expr : { expr : EMeta({ name : ":privateAccess", params : [], pos : pos }, { expr : EReturn(field.e), pos : pos }), pos : pos },
 					}),
+					#if openfl
+					meta : [ { name:":keep", pos:pos, params:[] } ],
+					#else
 					meta : [ { name:":extern", pos:pos, params:[] } ],
+					#end
 					access : [AStatic, AInline, APrivate],
 				};
 				var field : Field = {

Some files were not shown because too many files changed in this diff