Bladeren bron

started crossplatform, isolated Driver calls, added hxd package

ncannasse 12 jaren geleden
bovenliggende
commit
3311ea3d9f
58 gewijzigde bestanden met toevoegingen van 1492 en 863 verwijderingen
  1. 1 1
      h2d/Bitmap.hx
  2. 3 2
      h2d/Drawable.hx
  3. 9 2
      h2d/Font.hx
  4. 4 1
      h2d/Graphics.hx
  5. 19 19
      h2d/Interactive.hx
  6. 29 104
      h2d/Scene.hx
  7. 2 2
      h2d/SpriteBatch.hx
  8. 16 10
      h2d/Tile.hx
  9. 74 76
      h2d/TileColorGroup.hx
  10. 18 20
      h2d/TileGroup.hx
  11. 1 1
      h2d/Tools.hx
  12. 26 25
      h2d/comp/ColorPicker.hx
  13. 2 2
      h2d/comp/Component.hx
  14. 1 1
      h2d/comp/Context.hx
  15. 10 8
      h2d/comp/GradientEditor.hx
  16. 1 1
      h2d/comp/Input.hx
  17. 1 1
      h2d/comp/Slider.hx
  18. 1 1
      h3d/Drawable.hx
  19. 52 290
      h3d/Engine.hx
  20. 1 1
      h3d/anim/Animation.hx
  21. 2 2
      h3d/anim/FrameAnimation.hx
  22. 2 2
      h3d/anim/LinearAnimation.hx
  23. 4 4
      h3d/fbx/Library.hx
  24. 4 4
      h3d/impl/Buffer.hx
  25. 114 0
      h3d/impl/Driver.hx
  26. 6 1
      h3d/impl/Indexes.hx
  27. 39 77
      h3d/impl/MemoryManager.hx
  28. 10 0
      h3d/impl/Shader.hx
  29. 7 3
      h3d/impl/Shaders.hx
  30. 422 0
      h3d/impl/Stage3dDriver.hx
  31. 1 1
      h3d/mat/Material.hx
  32. 3 1
      h3d/mat/MeshMaterial.hx
  33. 5 2
      h3d/mat/PartMaterial.hx
  34. 0 18
      h3d/mat/PngBytes.hx
  35. 12 32
      h3d/mat/Texture.hx
  36. 13 14
      h3d/prim/Cube.hx
  37. 18 21
      h3d/prim/FBXModel.hx
  38. 22 23
      h3d/prim/GeoSphere.hx
  39. 2 2
      h3d/prim/MeshPrimitive.hx
  40. 1 1
      h3d/prim/Plan2D.hx
  41. 1 1
      h3d/prim/Plan3D.hx
  42. 23 26
      h3d/prim/Polygon.hx
  43. 9 10
      h3d/prim/Quads.hx
  44. 1 1
      h3d/prim/RawPrimitive.hx
  45. 1 1
      h3d/prim/Sphere.hx
  46. 20 19
      h3d/scene/Image.hx
  47. 10 10
      h3d/scene/Particles.hx
  48. 1 1
      h3d/scene/RenderContext.hx
  49. 65 0
      hxd/BitmapData.hx
  50. 47 0
      hxd/BytesBuffer.hx
  51. 1 1
      hxd/Event.hx
  52. 70 0
      hxd/FloatBuffer.hx
  53. 58 0
      hxd/IndexBuffer.hx
  54. 176 0
      hxd/Stage.hx
  55. 31 1
      hxd/System.hx
  56. 12 8
      samples/basic/Test.hx
  57. 2 2
      tools/fbx/Viewer.hx
  58. 6 6
      tools/parts/Main.hx

+ 1 - 1
h2d/Bitmap.hx

@@ -13,7 +13,7 @@ class Bitmap extends Drawable {
 		drawTile(ctx.engine,tile);
 	}
 			
-	public static function create( bmp : flash.display.BitmapData, ?allocPos : h3d.impl.AllocPos ) {
+	public static function create( bmp : hxd.BitmapData, ?allocPos : h3d.impl.AllocPos ) {
 		return new Bitmap(Tile.fromBitmap(bmp,allocPos));
 	}
 	

+ 3 - 2
h2d/Drawable.hx

@@ -1,6 +1,7 @@
 package h2d;
 
-private class DrawableShader extends hxsl.Shader {
+private class DrawableShader extends h3d.impl.Shader {
+	#if flash
 	static var SRC = {
 		var input : {
 			pos : Float2,
@@ -73,7 +74,7 @@ private class DrawableShader extends hxsl.Shader {
 
 
 	}
-	
+	#end
 }
 
 class Drawable extends Sprite {

+ 9 - 2
h2d/Font.hx

@@ -69,6 +69,7 @@ class Font #if !macro extends Tile #end {
 	}
 		
 	function init() {
+		#if flash
 		lineHeight = 0;
 		var tf = new flash.text.TextField();
 		var fmt = tf.defaultTextFormat;
@@ -158,9 +159,10 @@ class Font #if !macro extends Tile #end {
 			}
 		}
 		var bytes = haxe.io.Bytes.ofData(bytes);
+		var width = bmp.width, height = bmp.height;
 		
 		if( innerTex == null ) {
-			var t = h3d.Engine.getCurrent().mem.allocTexture(bmp.width, bmp.height);
+			var t = h3d.Engine.getCurrent().mem.allocTexture(width, height);
 			t.uploadBytes(bytes);
 			setTexture(t);
 			for( t in all )
@@ -170,6 +172,11 @@ class Font #if !macro extends Tile #end {
 			innerTex.uploadBytes(bytes);
 		
 		bmp.dispose();
+		#else
+		
+		throw "TODO";
+		
+		#end
 		
 		inline function map(code, to) {
 			if( glyphs[code] == null ) glyphs[code] = glyphs[to] else if( glyphs[to] == null ) glyphs[to] = glyphs[code];
@@ -222,7 +229,7 @@ class Font #if !macro extends Tile #end {
 			if( !skipErrors ) throw "Font file not found " + file;
 			return macro false;
 		}
-		if( chars == null ) chars = DEFAULT_CHARS;
+		if( chars == null ) chars = DEFAULT_CHARSET;
 		var pos = haxe.macro.Context.currentPos();
 		var safeName = "F_"+~/[^A-Za-z_]+/g.replace(name, "_");
 		haxe.macro.Context.defineType({

+ 4 - 1
h2d/Graphics.hx

@@ -1,5 +1,6 @@
 package h2d;
 
+#if flash
 @:allow(h2d.Graphics)
 class GraphicsContext {
 	
@@ -71,4 +72,6 @@ class Graphics extends Drawable {
 		drawTile(ctx.engine, tile);
 	}
 
-}
+}
+
+#end

+ 19 - 19
h2d/Interactive.hx

@@ -4,7 +4,7 @@ class Interactive extends Drawable {
 
 	public var width : Float;
 	public var height : Float;
-	public var cursor(default,set) : h3d.System.Cursor;
+	public var cursor(default,set) : hxd.System.Cursor;
 	public var isEllipse : Bool;
 	public var blockEvents : Bool = true;
 	public var propagateEvents : Bool = false;
@@ -45,13 +45,13 @@ class Interactive extends Drawable {
 			scene.removeEventTarget(this);
 			if( scene.currentOver == this ) {
 				scene.currentOver = null;
-				h3d.System.setCursor(Default);
+				hxd.System.setCursor(Default);
 			}
 		}
 		super.onDelete();
 	}
 
-	function checkBounds( e : Event ) {
+	function checkBounds( e : hxd.Event ) {
 		return switch( e.kind ) {
 		case EOut, ERelease, EFocus, EFocusLost: false;
 		default: true;
@@ -59,7 +59,7 @@ class Interactive extends Drawable {
 	}
 	
 	@:allow(h2d.Scene)
-	function handleEvent( e : Event ) {
+	function handleEvent( e : hxd.Event ) {
 		if( isEllipse && checkBounds(e) ) {
 			var cx = width * 0.5, cy = height * 0.5;
 			var dx = (e.relX - cx) / cx;
@@ -79,10 +79,10 @@ class Interactive extends Drawable {
 		case ERelease:
 			onRelease(e);
 		case EOver:
-			h3d.System.setCursor(cursor);
+			hxd.System.setCursor(cursor);
 			onOver(e);
 		case EOut:
-			h3d.System.setCursor(Default);
+			hxd.System.setCursor(Default);
 			onOut(e);
 		case EWheel:
 			onWheel(e);
@@ -102,11 +102,11 @@ class Interactive extends Drawable {
 	function set_cursor(c) {
 		this.cursor = c;
 		if( scene != null && scene.currentOver == this )
-			h3d.System.setCursor(cursor);
+			hxd.System.setCursor(cursor);
 		return c;
 	}
 	
-	function globalToLocal( e : Event ) {
+	function globalToLocal( e : hxd.Event ) {
 		// convert global event to our local space
 		var x = e.relX, y = e.relY;
 		var rx = x * scene.matA + y * scene.matB + scene.absX;
@@ -149,7 +149,7 @@ class Interactive extends Drawable {
 	public function focus() {
 		if( scene == null )
 			return;
-		var ev = new h2d.Event(null);
+		var ev = new hxd.Event(null);
 		if( scene.currentFocus != null ) {
 			if( scene.currentFocus == this )
 				return;
@@ -165,34 +165,34 @@ class Interactive extends Drawable {
 		return scene != null && scene.currentFocus == this;
 	}
 	
-	public dynamic function onOver( e : Event ) {
+	public dynamic function onOver( e : hxd.Event ) {
 	}
 
-	public dynamic function onOut( e : Event ) {
+	public dynamic function onOut( e : hxd.Event ) {
 	}
 	
-	public dynamic function onPush( e : Event ) {
+	public dynamic function onPush( e : hxd.Event ) {
 	}
 
-	public dynamic function onRelease( e : Event ) {
+	public dynamic function onRelease( e : hxd.Event ) {
 	}
 	
-	public dynamic function onMove( e : Event ) {
+	public dynamic function onMove( e : hxd.Event ) {
 	}
 
-	public dynamic function onWheel( e : Event ) {
+	public dynamic function onWheel( e : hxd.Event ) {
 	}
 
-	public dynamic function onFocus( e : Event ) {
+	public dynamic function onFocus( e : hxd.Event ) {
 	}
 	
-	public dynamic function onFocusLost( e : Event ) {
+	public dynamic function onFocusLost( e : hxd.Event ) {
 	}
 
-	public dynamic function onKeyUp( e : Event ) {
+	public dynamic function onKeyUp( e : hxd.Event ) {
 	}
 
-	public dynamic function onKeyDown( e : Event ) {
+	public dynamic function onKeyDown( e : hxd.Event ) {
 	}
 	
 }

+ 29 - 104
h2d/Scene.hx

@@ -10,9 +10,9 @@ class Scene extends Layers implements h3d.IDrawable {
 	
 	var fixedSize : Bool;
 	var interactive : Array<Interactive>;
-	var pendingEvents : flash.Vector<Event>;
-	var stage : flash.display.Stage;
+	var pendingEvents : Array<hxd.Event>;
 	var ctx : RenderContext;
+	var stage : hxd.Stage;
 	
 	@:allow(h2d.Interactive)
 	var currentOver : Interactive;
@@ -20,7 +20,7 @@ class Scene extends Layers implements h3d.IDrawable {
 	var currentFocus : Interactive;
 		
 	var pushList : Array<Interactive>;
-	var currentDrag : { f : Event -> Void, ref : Null<Int> };
+	var currentDrag : { f : hxd.Event -> Void, ref : Null<Int> };
 	
 	public function new() {
 		super(null);
@@ -30,7 +30,7 @@ class Scene extends Layers implements h3d.IDrawable {
 		height = e.height;
 		interactive = new Array();
 		pushList = new Array();
-		stage = flash.Lib.current.stage;
+		stage = hxd.Stage.getInstance();
 		posChanged = true;
 	}
 	
@@ -41,47 +41,26 @@ class Scene extends Layers implements h3d.IDrawable {
 		posChanged = true;
 	}
 
+	override function onAlloc() {
+		stage.addEventTarget(onEvent);
+		super.onAlloc();
+	}
+	
 	override function onDelete() {
-		if( h3d.System.isTouch ) {
-			stage.removeEventListener(flash.events.TouchEvent.TOUCH_BEGIN, onTouchDown);
-			stage.removeEventListener(flash.events.TouchEvent.TOUCH_MOVE, onTouchMove);
-			stage.removeEventListener(flash.events.TouchEvent.TOUCH_END, onTouchUp);
-		} else {
-			stage.removeEventListener(flash.events.MouseEvent.MOUSE_DOWN, onMouseDown);
-			stage.removeEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
-			stage.removeEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
-			stage.removeEventListener(flash.events.MouseEvent.MOUSE_WHEEL, onMouseWheel);
-			stage.removeEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
-			stage.removeEventListener(flash.events.KeyboardEvent.KEY_DOWN, onKeyDown);
-			stage.removeEventListener(flash.events.KeyboardEvent.KEY_UP, onKeyUp);
-			h3d.System.setCursor(Default);
-		}
+		stage.removeEventTarget(onEvent);
 		super.onDelete();
 	}
 	
-	override function onAlloc() {
-		if( h3d.System.isTouch ) {
-			flash.ui.Multitouch.inputMode = flash.ui.MultitouchInputMode.TOUCH_POINT;
-			stage.addEventListener(flash.events.TouchEvent.TOUCH_BEGIN, onTouchDown);
-			stage.addEventListener(flash.events.TouchEvent.TOUCH_MOVE, onTouchMove);
-			stage.addEventListener(flash.events.TouchEvent.TOUCH_END, onTouchUp);
-		} else {
-			stage.addEventListener(flash.events.MouseEvent.MOUSE_DOWN, onMouseDown);
-			stage.addEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
-			stage.addEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
-			stage.addEventListener(flash.events.MouseEvent.MOUSE_WHEEL, onMouseWheel);
-			stage.addEventListener(flash.events.KeyboardEvent.KEY_DOWN, onKeyDown);
-			stage.addEventListener(flash.events.KeyboardEvent.KEY_UP, onKeyUp);
-		}
-		super.onAlloc();
+	function onEvent( e : hxd.Event ) {
+		if( pendingEvents != null ) pendingEvents.push(e);
 	}
 	
 	function screenXToLocal(mx:Float) {
-		return (mx - x) * width / (stage.stageWidth * scaleX);
+		return (mx - x) * width / (stage.width * scaleX);
 	}
 
 	function screenYToLocal(my:Float) {
-		return (my - y) * height / (stage.stageHeight * scaleY);
+		return (my - y) * height / (stage.height * scaleY);
 	}
 	
 	function get_mouseX() {
@@ -91,73 +70,8 @@ class Scene extends Layers implements h3d.IDrawable {
 	function get_mouseY() {
 		return screenYToLocal(stage.mouseY);
 	}
-			
-	function onMouseDown(e:Dynamic) {
-		if( pendingEvents != null )
-			pendingEvents.push(new Event(EPush, mouseX, mouseY));
-	}
-
-	function onMouseUp(e:Dynamic) {
-		if( pendingEvents != null )
-			pendingEvents.push(new Event(ERelease, mouseX, mouseY));
-	}
-	
-	function onMouseMove(e:Dynamic) {
-		if( pendingEvents != null )
-			pendingEvents.push(new Event(EMove, mouseX, mouseY));
-	}
-	
-	function onMouseWheel(e:flash.events.MouseEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(EWheel, mouseX, mouseY);
-			ev.wheelDelta = -e.delta / 3.0;
-			pendingEvents.push(ev);
-		}
-	}
-	
-	function onKeyUp(e:flash.events.KeyboardEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(EKeyUp);
-			ev.keyCode = e.keyCode;
-			ev.charCode = e.charCode;
-			pendingEvents.push(ev);
-		}
-	}
 
-	function onKeyDown(e:flash.events.KeyboardEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(EKeyDown);
-			ev.keyCode = e.keyCode;
-			ev.charCode = e.charCode;
-			pendingEvents.push(ev);
-		}
-	}
-	
-	function onTouchDown(e:flash.events.TouchEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(EPush, screenXToLocal(e.localX), screenYToLocal(e.localY));
-			ev.touchId = e.touchPointID;
-			pendingEvents.push(ev);
-		}
-	}
-
-	function onTouchUp(e:flash.events.TouchEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(ERelease, screenXToLocal(e.localX), screenYToLocal(e.localY));
-			ev.touchId = e.touchPointID;
-			pendingEvents.push(ev);
-		}
-	}
-	
-	function onTouchMove(e:flash.events.TouchEvent) {
-		if( pendingEvents != null ) {
-			var ev = new Event(EMove, screenXToLocal(e.localX), screenYToLocal(e.localY));
-			ev.touchId = e.touchPointID;
-			pendingEvents.push(ev);
-		}
-	}
-	
-	function emitEvent( event : Event ) {
+	function emitEvent( event : hxd.Event ) {
 		var x = event.relX, y = event.relY;
 		var rx = x * matA + y * matB + absX;
 		var ry = x * matC + y * matD + absY;
@@ -279,13 +193,24 @@ class Scene extends Layers implements h3d.IDrawable {
 		if( pendingEvents == null ) {
 			if( interactive.length == 0 )
 				return;
-			pendingEvents = new flash.Vector();
+			pendingEvents = new Array();
 		}
 		var old = pendingEvents;
 		if( old.length == 0 )
 			return;
 		pendingEvents = null;
+		var ox = 0., oy = 0.;
 		for( e in old ) {
+			var hasPos = switch( e.kind ) {
+			case EKeyUp, EKeyDown: false;
+			default: true;
+			}
+			
+			if( hasPos ) {
+				ox = e.relX;
+				oy = e.relY;
+			}
+			
 			if( currentDrag != null && (currentDrag.ref == null || currentDrag.ref == e.touchId) ) {
 				currentDrag.f(e);
 				if( e.cancel )
@@ -301,10 +226,10 @@ class Scene extends Layers implements h3d.IDrawable {
 			}
 		}
 		if( interactive.length > 0 )
-			pendingEvents = new flash.Vector();
+			pendingEvents = new Array();
 	}
 	
-	public function startDrag( f : Event -> Void, ?refEvent : Event ) {
+	public function startDrag( f : hxd.Event -> Void, ?refEvent : hxd.Event ) {
 		currentDrag = { f : f, ref : refEvent == null ? null : refEvent.touchId };
 	}
 	

+ 2 - 2
h2d/SpriteBatch.hx

@@ -28,7 +28,7 @@ class SpriteBatch extends Drawable {
 	public var tile : Tile;
 	var first : BatchElement;
 	var last : BatchElement;
-	var tmpBuf : flash.Vector<Float>;
+	var tmpBuf : hxd.FloatBuffer;
 		
 	public function new(t,?parent) {
 		super(parent);
@@ -65,7 +65,7 @@ class SpriteBatch extends Drawable {
 	override function draw( ctx : RenderContext ) {
 		if( first == null )
 			return;
-		if( tmpBuf == null ) tmpBuf = new flash.Vector();
+		if( tmpBuf == null ) tmpBuf = new hxd.FloatBuffer();
 		var pos = 0;
 		var e = first;
 		var tmp = tmpBuf;

+ 16 - 10
h2d/Tile.hx

@@ -121,17 +121,20 @@ class Tile {
 		return "Tile(" + x + "," + y + "," + width + "x" + height + (dx != 0 || dy != 0 ? "," + dx + ":" + dy:"") + ")";
 	}
 
-	function upload(bmp:flash.display.BitmapData) {
+	function upload( bmp:hxd.BitmapData ) {
 		var w = innerTex.width;
 		var h = innerTex.height;
+		#if flash
 		if( w != bmp.width || h != bmp.height ) {
 			var bmp2 = new flash.display.BitmapData(w, h, true, 0);
 			var p0 = new flash.geom.Point(0, 0);
+			var bmp = bmp.toNative();
 			bmp2.copyPixels(bmp, bmp.rect, p0, bmp, p0, true);
-			innerTex.upload(bmp2);
+			innerTex.uploadBitmap(hxd.BitmapData.fromNative(bmp2));
 			bmp2.dispose();
 		} else
-			innerTex.upload(bmp);
+		#end
+			innerTex.uploadBitmap(bmp);
 	}
 	
 
@@ -158,7 +161,7 @@ class Tile {
 		return t;
 	}
 	
-	public static function fromBitmap( bmp : flash.display.BitmapData, ?allocPos : h3d.impl.AllocPos ) {
+	public static function fromBitmap( bmp : hxd.BitmapData, ?allocPos : h3d.impl.AllocPos ) {
 		var w = 1, h = 1;
 		while( w < bmp.width )
 			w <<= 1;
@@ -170,9 +173,9 @@ class Tile {
 		return t;
 	}
 
-	public static function autoCut( bmp : flash.display.BitmapData, width : Int, ?height : Int, ?allocPos : h3d.impl.AllocPos ) {
+	public static function autoCut( bmp : hxd.BitmapData, width : Int, ?height : Int, ?allocPos : h3d.impl.AllocPos ) {
 		if( height == null ) height = width;
-		var colorBG = bmp.getPixel32(bmp.width - 1, bmp.height - 1);
+		var colorBG = bmp.getPixel(bmp.width - 1, bmp.height - 1);
 		var tl = new Array();
 		var w = 1, h = 1;
 		while( w < bmp.width )
@@ -199,6 +202,7 @@ class Tile {
 		return new Tile(t, 0, 0, t.width, t.height);
 	}
 	
+	#if flash
 	public static function fromSprites( sprites : Array<flash.display.Sprite>, ?allocPos : h3d.impl.AllocPos ) {
 		var tmp = [];
 		var width = 0;
@@ -225,19 +229,21 @@ class Tile {
 			m.ty = -t.dy;
 			bmp.draw(t.s, m);
 		}
-		var main = fromBitmap(bmp,allocPos);
+		var main = fromBitmap(hxd.BitmapData.fromNative(bmp), allocPos);
+		bmp.dispose();
 		var tiles = [];
 		for( t in tmp )
 			tiles.push(main.sub(t.x, 0, t.w, t.h, t.dx, t.dy));
 		return tiles;
 	}
+	#end
 	
-	static function isEmpty( b : flash.display.BitmapData, px, py, width, height, bg : UInt ) {
+	static function isEmpty( b : hxd.BitmapData, px, py, width, height, bg : Int ) {
 		var empty = true;
 		var xmin = width, ymin = height, xmax = 0, ymax = 0;
 		for( x in 0...width )
 			for( y in 0...height ) {
-				var color = b.getPixel32(x+px, y+py);
+				var color : Int = b.getPixel(x+px, y+py);
 				if( color != bg ) {
 					empty = false;
 					if( x < xmin ) xmin = x;
@@ -246,7 +252,7 @@ class Tile {
 					if( y > ymax ) ymax = y;
 				}
 				if( color == bg )
-					b.setPixel32(x+px, y+py, 0);
+					b.setPixel(x+px, y+py, 0);
 			}
 		return empty ? null : { dx : xmin, dy : ymin, w : xmax - xmin + 1, h : ymax - ymin + 1 };
 	}

+ 74 - 76
h2d/TileColorGroup.hx

@@ -2,16 +2,14 @@ package h2d;
 
 private class TileLayerContent extends h3d.prim.Primitive {
 
-	var tmp : flash.Vector<Float>;
-	var pos : Int;
+	var tmp : hxd.FloatBuffer;
 
 	public function new() {
 		reset();
 	}
 
 	public function reset() {
-		tmp = new flash.Vector();
-		pos = 0;
+		tmp = new hxd.FloatBuffer();
 		if( buffer != null ) buffer.dispose();
 		buffer = null;
 	}
@@ -31,98 +29,98 @@ private class TileLayerContent extends h3d.prim.Primitive {
 	public function add( x : Int, y : Int, r : Float, g : Float, b : Float, a : Float, t : Tile ) {
 		var sx = x + t.dx;
 		var sy = y + t.dy;
-		tmp[pos++] = sx;
-		tmp[pos++] = sy;
-		tmp[pos++] = t.u;
-		tmp[pos++] = t.v;
-		tmp[pos++] = r;
-		tmp[pos++] = g;
-		tmp[pos++] = b;
-		tmp[pos++] = a;
-		tmp[pos++] = sx + t.width;
-		tmp[pos++] = sy;
-		tmp[pos++] = t.u2;
-		tmp[pos++] = t.v;
-		tmp[pos++] = r;
-		tmp[pos++] = g;
-		tmp[pos++] = b;
-		tmp[pos++] = a;
-		tmp[pos++] = sx;
-		tmp[pos++] = sy + t.height;
-		tmp[pos++] = t.u;
-		tmp[pos++] = t.v2;
-		tmp[pos++] = r;
-		tmp[pos++] = g;
-		tmp[pos++] = b;
-		tmp[pos++] = a;
-		tmp[pos++] = sx + t.width;
-		tmp[pos++] = sy + t.height;
-		tmp[pos++] = t.u2;
-		tmp[pos++] = t.v2;
-		tmp[pos++] = r;
-		tmp[pos++] = g;
-		tmp[pos++] = b;
-		tmp[pos++] = a;
+		tmp.push(sx);
+		tmp.push(sy);
+		tmp.push(t.u);
+		tmp.push(t.v);
+		tmp.push(r);
+		tmp.push(g);
+		tmp.push(b);
+		tmp.push(a);
+		tmp.push(sx + t.width);
+		tmp.push(sy);
+		tmp.push(t.u2);
+		tmp.push(t.v);
+		tmp.push(r);
+		tmp.push(g);
+		tmp.push(b);
+		tmp.push(a);
+		tmp.push(sx);
+		tmp.push(sy + t.height);
+		tmp.push(t.u);
+		tmp.push(t.v2);
+		tmp.push(r);
+		tmp.push(g);
+		tmp.push(b);
+		tmp.push(a);
+		tmp.push(sx + t.width);
+		tmp.push(sy + t.height);
+		tmp.push(t.u2);
+		tmp.push(t.v2);
+		tmp.push(r);
+		tmp.push(g);
+		tmp.push(b);
+		tmp.push(a);
 	}
 	
 	public function addPoint( x : Float, y : Float, color : Int ) {
-		tmp[pos++] = x;
-		tmp[pos++] = y;
-		tmp[pos++] = 0;
-		tmp[pos++] = 0;
+		tmp.push(x);
+		tmp.push(y);
+		tmp.push(0);
+		tmp.push(0);
 		insertColor(color);
 	}
 
 	inline function insertColor( c : Int ) {
-		tmp[pos++] = ((c >> 16) & 0xFF) / 255.;
-		tmp[pos++] = ((c >> 8) & 0xFF) / 255.;
-		tmp[pos++] = (c & 0xFF) / 255.;
-		tmp[pos++] = (c >>> 24) / 255.;
+		tmp.push(((c >> 16) & 0xFF) / 255.);
+		tmp.push(((c >> 8) & 0xFF) / 255.);
+		tmp.push((c & 0xFF) / 255.);
+		tmp.push((c >>> 24) / 255.);
 	}
 
 	public inline function rectColor( x : Float, y : Float, w : Float, h : Float, color : Int ) {
-		tmp[pos++] = x;
-		tmp[pos++] = y;
-		tmp[pos++] = 0;
-		tmp[pos++] = 0;
+		tmp.push(x);
+		tmp.push(y);
+		tmp.push(0);
+		tmp.push(0);
 		insertColor(color);
-		tmp[pos++] = x + w;
-		tmp[pos++] = y;
-		tmp[pos++] = 1;
-		tmp[pos++] = 0;
+		tmp.push(x + w);
+		tmp.push(y);
+		tmp.push(1);
+		tmp.push(0);
 		insertColor(color);
-		tmp[pos++] = x;
-		tmp[pos++] = y + h;
-		tmp[pos++] = 0;
-		tmp[pos++] = 1;
+		tmp.push(x);
+		tmp.push(y + h);
+		tmp.push(0);
+		tmp.push(1);
 		insertColor(color);
-		tmp[pos++] = x + w;
-		tmp[pos++] = y + h;
-		tmp[pos++] = 1;
-		tmp[pos++] = 1;
+		tmp.push(x + w);
+		tmp.push(y + h);
+		tmp.push(1);
+		tmp.push(1);
 		insertColor(color);
 	}
 
 	public inline function rectGradient( x : Float, y : Float, w : Float, h : Float, ctl : Int, ctr : Int, cbl : Int, cbr : Int ) {
-		tmp[pos++] = x;
-		tmp[pos++] = y;
-		tmp[pos++] = 0;
-		tmp[pos++] = 0;
+		tmp.push(x);
+		tmp.push(y);
+		tmp.push(0);
+		tmp.push(0);
 		insertColor(ctl);
-		tmp[pos++] = x + w;
-		tmp[pos++] = y;
-		tmp[pos++] = 1;
-		tmp[pos++] = 0;
+		tmp.push(x + w);
+		tmp.push(y);
+		tmp.push(1);
+		tmp.push(0);
 		insertColor(ctr);
-		tmp[pos++] = x;
-		tmp[pos++] = y + h;
-		tmp[pos++] = 0;
-		tmp[pos++] = 1;
+		tmp.push(x);
+		tmp.push(y + h);
+		tmp.push(0);
+		tmp.push(1);
 		insertColor(cbl);
-		tmp[pos++] = x + w;
-		tmp[pos++] = y + h;
-		tmp[pos++] = 1;
-		tmp[pos++] = 0;
+		tmp.push(x + w);
+		tmp.push(y + h);
+		tmp.push(1);
+		tmp.push(0);
 		insertColor(cbr);
 	}
 

+ 18 - 20
h2d/TileGroup.hx

@@ -2,8 +2,7 @@ package h2d;
 
 private class TileLayerContent extends h3d.prim.Primitive {
 
-	var tmp : flash.Vector<Float>;
-	var pos : Int;
+	var tmp : hxd.FloatBuffer;
 	
 	public function new() {
 		reset();
@@ -14,8 +13,7 @@ private class TileLayerContent extends h3d.prim.Primitive {
 	}
 	
 	public function reset() {
-		tmp = new flash.Vector();
-		pos = 0;
+		tmp = new hxd.FloatBuffer();
 		if( buffer != null ) buffer.dispose();
 		buffer = null;
 	}
@@ -25,22 +23,22 @@ private class TileLayerContent extends h3d.prim.Primitive {
 		var sy = y + t.dy;
 		var sx2 = sx + t.width;
 		var sy2 = sy + t.height;
-		tmp[pos++] = sx;
-		tmp[pos++] = sy;
-		tmp[pos++] = t.u;
-		tmp[pos++] = t.v;
-		tmp[pos++] = sx2;
-		tmp[pos++] = sy;
-		tmp[pos++] = t.u2;
-		tmp[pos++] = t.v;
-		tmp[pos++] = sx;
-		tmp[pos++] = sy2;
-		tmp[pos++] = t.u;
-		tmp[pos++] = t.v2;
-		tmp[pos++] = sx2;
-		tmp[pos++] = sy2;
-		tmp[pos++] = t.u2;
-		tmp[pos++] = t.v2;
+		tmp.push(sx);
+		tmp.push(sy);
+		tmp.push(t.u);
+		tmp.push(t.v);
+		tmp.push(sx2);
+		tmp.push(sy);
+		tmp.push(t.u2);
+		tmp.push(t.v);
+		tmp.push(sx);
+		tmp.push(sy2);
+		tmp.push(t.u);
+		tmp.push(t.v2);
+		tmp.push(sx2);
+		tmp.push(sy2);
+		tmp.push(t.u2);
+		tmp.push(t.v2);
 	}
 	
 	override public function triCount() {

+ 1 - 1
h2d/Tools.hx

@@ -26,7 +26,7 @@ private class CoreObjects  {
 		tmpMaterial.culling = None;
 		tmpMaterial.depth(false, Always);
 		
-		var vector = new flash.Vector<Float>();
+		var vector = new hxd.FloatBuffer();
 		for( pt in [[0, 0], [1, 0], [0, 1], [1, 1]] ) {
 			vector.push(pt[0]);
 			vector.push(pt[1]);

+ 26 - 25
h2d/comp/ColorPicker.hx

@@ -69,7 +69,7 @@ private class Cross extends h2d.css.Fill {
 		lineRect(FillStyle.Color(color), 0, 0, size, size, 1);
 	}
 	
-	public function setColor(color:UInt) {
+	public function setColor(color:Int) {
 		reset();
 		lineRect(FillStyle.Color(color), 0, 0, size, size, 1);
 	}
@@ -78,8 +78,8 @@ private class Cross extends h2d.css.Fill {
 private class Color extends h2d.Sprite{
 	public var width :Float;
 	public var height :Float;
-	public var color(default, set):UInt = 0xFFFFFFFF;
-	public var preview(default, set):UInt = 0xFFFFFFFF;
+	public var color(default, set):Int = 0xFFFFFFFF;
+	public var preview(default, set):Int = 0xFFFFFFFF;
 	public var alpha(default, set):Float = 1.;
 	
 	var canvas:h2d.css.Fill;
@@ -96,7 +96,7 @@ private class Color extends h2d.Sprite{
 		init();
 	}
 	
-	function set_color(v:UInt) {
+	function set_color(v:Int) {
 		if(v != color) {
 			color = v;
 			drawAll();
@@ -104,7 +104,7 @@ private class Color extends h2d.Sprite{
 		return color;
 	}
 	
-	function set_preview(v:UInt) {
+	function set_preview(v:Int) {
 		if(v != preview) {
 			preview = v;
 			drawAll();
@@ -118,7 +118,7 @@ private class Color extends h2d.Sprite{
 		return color;
 	}
 	
-	public function updateColor(v:UInt) {
+	public function updateColor(v:Int) {
 		color = v;
 		input.value = StringTools.hex(preview, 6).substr(2);
 	}
@@ -161,7 +161,7 @@ private class Color extends h2d.Sprite{
 private class Palette extends h2d.Sprite {
 	public var width :Float;
 	public var height :Float;
-	public var color(default, set):UInt;
+	public var color(default, set):Int;
 	
 	var canvas:h2d.css.Fill;
 	var interact:h2d.Interactive;
@@ -199,7 +199,7 @@ private class Palette extends h2d.Sprite {
 		drawAll();
 	}
 	
-	function set_color(v:UInt) {
+	function set_color(v:Int) {
 		color = v;
 		if(!ColorPicker.change.equals(SPalette))
 			updateCursor();
@@ -237,7 +237,7 @@ private class Palette extends h2d.Sprite {
 		return(ColorPicker.HSLtoINT(h, s, l));
 	}
 	
-	public function setColorFrom(newColor:UInt) {
+	public function setColorFrom(newColor:Int) {
 		var rgb = ColorPicker.INTtoRGB(newColor);
 		var hsl = ColorPicker.RGBtoHLS(rgb[0], rgb[1], rgb[2]);
 		hsl[1] = 1; hsl[2] = 0.5;
@@ -249,8 +249,8 @@ private class Palette extends h2d.Sprite {
 private class Chart extends h2d.Sprite{
 	public var width :Int;
 	public var height :Int;
-	public var refColor(default, set):UInt = 0xffffffff;
-	public var color:UInt = 0xffffffff;
+	public var refColor(default, set):Int = 0xffffffff;
+	public var color:Int = 0xffffffff;
 	
 	var ray :Float;
 	var canvas:h2d.css.Fill;
@@ -299,7 +299,7 @@ private class Chart extends h2d.Sprite{
 		cross.setColor(ColorPicker.complementaryColor(color));
 	}
 	
-	function set_refColor(v:UInt) {
+	function set_refColor(v:Int) {
 		refColor = v;
 		color = getColor(lastPos.x, lastPos.y);
 		cross.setColor(ColorPicker.complementaryColor(color));
@@ -348,7 +348,7 @@ private class Chart extends h2d.Sprite{
 		return ColorPicker.RGBtoINT(r, g, b);
 	}
 	
-	public function setColorFrom(newColor:UInt) {
+	public function setColorFrom(newColor:Int) {
 		var rgb = ColorPicker.INTtoRGB(newColor);
 		var hsl = ColorPicker.RGBtoHLS(rgb[0], rgb[1], rgb[2]);
 		hsl[1] = 1; hsl[2] = 0.5;
@@ -367,7 +367,7 @@ private class Chart extends h2d.Sprite{
 private class ColorGauge extends h2d.Sprite{
 	public var width :Int;
 	public var height :Int;
-	public var color(default, set):UInt = 0xffffffff;
+	public var color(default, set):Int = 0xffffffff;
 	public var ratio(get, null):Float;
 	
 	var canvas:h2d.css.Fill;
@@ -422,7 +422,7 @@ private class ColorGauge extends h2d.Sprite{
 		drawAll();
 	}
 	
-	function set_color(v:UInt) {
+	function set_color(v:Int) {
 		color = v;
 		if(!bindTo.equals(RGBA.A))
 			updateCursor();
@@ -475,8 +475,8 @@ private class ColorGauge extends h2d.Sprite{
 		var r = (color >> 16) & 0xFF;
 		var g =	(color >> 8) & 0xFF;
 		var b = color & 0xFF;
-		var left:UInt;
-		var right:UInt;
+		var left:Int;
+		var right:Int;
 		switch(bindTo) {
 			case RGBA.R: left = ColorPicker.RGBtoINT(0, g, b);	right = ColorPicker.RGBtoINT(255, g, b);
 			case RGBA.G: left = ColorPicker.RGBtoINT(r, 0, b);	right = ColorPicker.RGBtoINT(r, 255, b);
@@ -522,10 +522,12 @@ class ColorPicker extends h2d.comp.Component {
 		chart.refColor = palette.color;
 		change = SNone;
 		
+		#if flash
 		flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, doUpdate);
+		#end
 	}
-	
-	function doUpdate(e:flash.events.Event) {
+
+	function doUpdate(_) {
 		finalColor.preview = chart.color;
 		if(change.equals(SNone)) {
 			if(finalColor.color != chart.color) {
@@ -535,7 +537,6 @@ class ColorPicker extends h2d.comp.Component {
 			return;
 		}
 			
-		var p = new flash.geom.Point(flash.Lib.current.mouseX, flash.Lib.current.mouseY);
 		switch(change) {
 			case SColor:	palette.setColorFrom(finalColor.color);
 							chart.setColorFrom(finalColor.color);
@@ -555,7 +556,7 @@ class ColorPicker extends h2d.comp.Component {
 		gaugeBlue.color = chart.color;
 	}
 	
-	public function show (color:UInt) {
+	public function show(color:Int) {
 		finalColor.color = color;
 		palette.setColorFrom(finalColor.color);
 		chart.setColorFrom(finalColor.color);
@@ -565,15 +566,15 @@ class ColorPicker extends h2d.comp.Component {
 		visible = false;
 	}
 	
-	public dynamic function onChange( value : UInt ) {
+	public dynamic function onChange( value : Int ) {
 	}
 	
 //////////////////
-	inline public static function INTtoRGB(color:UInt) {
+	inline public static function INTtoRGB(color:Int) {
 		return [(color >> 16) & 0xFF, (color >> 8) & 0xFF,  color & 0xFF];
 	}
 	
-	inline public static function INTtoHSL(color:UInt) {
+	inline public static function INTtoHSL(color:Int) {
 		var rgb = INTtoRGB(color);
 		return RGBtoHLS(rgb[0], rgb[1], rgb[2]);
 	}
@@ -632,7 +633,7 @@ class ColorPicker extends h2d.comp.Component {
 		return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
 	}
 	
-	inline public static function complementaryColor (color:UInt) {
+	inline public static function complementaryColor (color:Int) {
 		var rgb = INTtoRGB(color);
 		var r = rgb[0] ^ 0xFF;
 		var g = rgb[1] ^ 0xFF;

+ 2 - 2
h2d/comp/Component.hx

@@ -43,7 +43,7 @@ class Component extends Sprite {
 	}
 	
 	function getElementByIdRec( s : h2d.Sprite, id : String ) : Component {
-		var c = flash.Lib.as(s, Component);
+		var c = Std.instance(s, Component);
 		if( c != null && c.id == id )
 			return c;
 		for( s in s.childs ) {
@@ -65,7 +65,7 @@ class Component extends Sprite {
 		var old = parentComponent;
 		var p = parent;
 		while( p != null ) {
-			var c = flash.Lib.as(p, Component);
+			var c = Std.instance(p, Component);
 			if( c != null ) {
 				parentComponent = c;
 				if( old != c ) {

+ 1 - 1
h2d/comp/Context.hx

@@ -36,7 +36,7 @@ class Context {
 
 	static var FONTS = new Map<String,h2d.Font>();
 	
-	public static var DEFAULT_CSS = h3d.System.getFileContent("h2d/css/default.css");
+	public static var DEFAULT_CSS = hxd.System.getFileContent("h2d/css/default.css");
 	
 	static var DEF = null;
 	public static function getDefaultCss() {

+ 10 - 8
h2d/comp/GradientEditor.hx

@@ -2,7 +2,7 @@ package h2d.comp;
 import h2d.css.Defs;
 import h2d.css.Fill;
 
-private typedef Key = { x:Float, value:UInt };
+private typedef Key = { x:Float, value:Int };
 
 private enum KCursor {
 	KAlpha;
@@ -71,10 +71,10 @@ private class CFlag extends h2d.css.Fill {
 }
 
 private class Cursor extends h2d.Sprite {
-	public var value(default, set):UInt;
+	public var value(default, set):Int;
 	public var coeff(get, null):Float;
-	public var color:UInt = 0xFFFFFFFF;
-	public var bgcolor:UInt = 0xFFFF00FF;
+	public var color:Int = 0xFFFFFFFF;
+	public var bgcolor:Int = 0xFFFF00FF;
 	public var cursor:h2d.Sprite;
 	public var kind:KCursor;
 	var ang:Float;
@@ -251,7 +251,7 @@ private class ColorSelector extends h2d.Sprite {
 	var locInput:h2d.comp.Input;
 	var colorInput:h2d.comp.Input;
 	var canvas:h2d.css.Fill;
-	var color:UInt = 0xFFFFFFFF;
+	var color:Int = 0xFFFFFFFF;
 	var interact : h2d.Interactive;
 	
 	public function new (ix, iy, parent) {
@@ -418,11 +418,13 @@ class GradientEditor extends h2d.comp.Component {
 		updateTarget = colorsKeys[0];
 		updateKeys();
 		drawGradient();
-		
+	
+		#if flash
 		flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, doUpdate);
+		#end
 	}
 	
-	function doUpdate(e:flash.events.Event) {
+	function doUpdate(_) {
 		if(dragTarget != null) {
 			if(dragOut) {
 				switch(dragTarget.kind) {
@@ -612,7 +614,7 @@ class GradientEditor extends h2d.comp.Component {
 	}
 	
 	
-	inline public static function INTtoRGB(color:UInt) {
+	inline public static function INTtoRGB(color:Int) {
 		return [(color >> 16) & 0xFF, (color >> 8) & 0xFF,  color & 0xFF, color >>> 24];
 	}
 	

+ 1 - 1
h2d/comp/Input.hx

@@ -36,7 +36,7 @@ class Input extends Component {
 			removeClass(":focus");
 			cursor.visible = false;
 		};
-		input.onKeyDown = function(e:Event) {
+		input.onKeyDown = function(e:hxd.Event) {
 			if( input.hasFocus() ) {
 				// BACK
 				switch( e.keyCode ) {

+ 1 - 1
h2d/comp/Slider.hx

@@ -28,7 +28,7 @@ class Slider extends Component {
 		value = 0.;
 	}
 	
-	function pixelToVal( e : h2d.Event ) {
+	function pixelToVal( e : hxd.Event ) {
 		return Std.int(e.relX - (style.borderSize + cursor.width * 0.5) ) / (input.width - (style.borderSize * 2 + cursor.width));
 	}
 	

+ 1 - 1
h3d/Drawable.hx

@@ -4,7 +4,7 @@ package h3d;
 	A core object is a rendering context but completely outside of the 3d scene.
 	It is meant to be able to share a rendering context between several similar physical objects.
  **/
-class Drawable<S:hxsl.Shader> implements IDrawable {
+class Drawable<S:h3d.impl.Shader> implements IDrawable {
 
 	public var shader : S;
 	public var primitive : h3d.prim.Primitive;

+ 52 - 290
h3d/Engine.hx

@@ -3,9 +3,8 @@ import h3d.mat.Data;
 
 class Engine {
 
-	var s3d : flash.display.Stage3D;
-	var ctx : flash.display3D.Context3D;
-
+	var driver : h3d.impl.Driver;
+	
 	public var mem(default,null) : h3d.impl.MemoryManager;
 
 	public var hardware(default, null) : Bool;
@@ -28,18 +27,9 @@ class Engine {
 	public var forcedMatMask : Int = 0xFFFFFF;
 	
 	var realFps : Float;
-	var lastTime : Int;
-	
-	var curMatBits : Int;
-	var curShader : hxsl.Shader.ShaderInstance;
-	var curBuffer : h3d.impl.MemoryManager.BigBuffer;
-	var curMultiBuffer : Array<h3d.impl.Buffer.BufferOffset>;
-	var curAttributes : Int;
-	var curTextures : Array<h3d.mat.Texture>;
-	var curSamplerBits : Array<Int>;
+	var lastTime : Float;
 	var antiAlias : Int;
-	var inTarget : Bool;
-
+	
 	var debugPoint : h3d.Drawable<h3d.impl.Shaders.PointShader>;
 	var debugLine : h3d.Drawable<h3d.impl.Shaders.LineShader>;
 	
@@ -50,13 +40,16 @@ class Engine {
 		this.hardware = hardware;
 		this.antiAlias = aa;
 		this.autoResize = true;
-		fullScreen = !System.isWindowed;
-		var stage = flash.Lib.current.stage;
-		realFps = stage.frameRate;
-		lastTime = flash.Lib.getTimer();
-		stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
-		stage.addEventListener(flash.events.Event.RESIZE, onStageResize);
-		s3d = stage.stage3Ds[0];
+		fullScreen = !hxd.System.isWindowed;
+		var stage = hxd.Stage.getInstance();
+		realFps = stage.getFrameRate();
+		lastTime = haxe.Timer.stamp();
+		stage.addResizeEvent(onStageResize);
+		#if flash
+		driver = new h3d.impl.Stage3dDriver();
+		#else
+		throw "No driver";
+		#end
 		if( CURRENT == null )
 			CURRENT = this;
 	}
@@ -71,120 +64,30 @@ class Engine {
 		CURRENT = this;
 	}
 
-	public function show( b ) {
-		s3d.visible = b;
-	}
-
 	public function init() {
-		s3d.addEventListener(flash.events.Event.CONTEXT3D_CREATE, onCreate);
-		s3d.requestContext3D( hardware ? "auto" : "software" );
-	}
-
-	public function saveTo( bmp : flash.display.BitmapData ) {
-		ctx.drawToBitmapData(bmp);
+		driver.init(onCreate);
 	}
 
 	public function driverName(details=false) {
-		return ctx == null ? "None" : (details ? ctx.driverInfo : ctx.driverInfo.split(" ")[0]);
-	}
-
-	public function isReady() {
-		return ctx != null;
+		return driver.getDriverName(details);
 	}
 
-	public function selectShader( shader : hxsl.Shader ) {
-		var s = shader.getInstance();
-		if( s.program == null ) {
-			s.program = ctx.createProgram();
-			var vdata = s.vertexBytes.getData();
-			var fdata = s.fragmentBytes.getData();
-			vdata.endian = flash.utils.Endian.LITTLE_ENDIAN;
-			fdata.endian = flash.utils.Endian.LITTLE_ENDIAN;
-			s.program.upload(vdata, fdata);
-			curShader = null; // in case we had the same shader and it was disposed
-		}
-		if( s != curShader ) {
-			ctx.setProgram(s.program);
+	public function selectShader( shader : h3d.impl.Shader ) {
+		if( driver.selectShader(shader) )
 			shaderSwitches++;
-			s.varsChanged = true;
-			// unbind extra textures
-			var tcount : Int = s.textures.length;
-			while( curTextures.length > tcount ) {
-				curTextures.pop();
-				ctx.setTextureAt(curTextures.length, null);
-			}
-			// force remapping of vertex buffer
-			curBuffer = null;
-			curMultiBuffer = null;
-			curShader = s;
-		}
-		if( s.varsChanged ) {
-			s.varsChanged = false;
-			ctx.setProgramConstantsFromVector(flash.display3D.Context3DProgramType.VERTEX, 0, s.vertexVars.toData());
-			ctx.setProgramConstantsFromVector(flash.display3D.Context3DProgramType.FRAGMENT, 0, s.fragmentVars.toData());
-			for( i in 0...s.textures.length ) {
-				var t = s.textures[i];
-				if( t == null || t.isDisposed() )
-					t = h2d.Tile.fromColor(0xFFFF00FF).getTexture();
-				var cur = curTextures[i];
-				if( t != cur ) {
-					ctx.setTextureAt(i, t.t);
-					curTextures[i] = t;
-				}
-				// if we have set one of the texture flag manually or if the shader does not configure the texture flags
-				if( !t.hasDefaultFlags() || !s.texHasConfig[s.textureMap[i]] ) {
-					if( cur == null || t.bits != curSamplerBits[i] ) {
-						ctx.setSamplerStateAt(i, WRAP[t.wrap.getIndex()], FILTER[t.filter.getIndex()], MIP[t.mipMap.getIndex()]);
-						curSamplerBits[i] = t.bits;
-					}
-				} else {
-					// the texture flags has been set by the shader, so we are in an unkown state
-					curSamplerBits[i] = -1;
-				}
-			}
-		}
 	}
 
 	@:access(h3d.mat.Material.bits)
 	public function selectMaterial( m : h3d.mat.Material ) {
 		var mbits = (m.bits & forcedMatMask) | forcedMatBits;
-		var diff = curMatBits ^ mbits;
-		if( diff != 0 ) {
-			if( curMatBits < 0 || diff&3 != 0 )
-				ctx.setCulling(FACE[mbits&3]);
-			if( curMatBits < 0 || diff & (0xFF << 6) != 0 )
-				ctx.setBlendFactors(BLEND[(mbits>>6)&15], BLEND[(mbits>>10)&15]);
-			if( curMatBits < 0 || diff & (15 << 2) != 0 )
-				ctx.setDepthTest((mbits >> 2) & 1 == 1, COMPARE[(mbits>>3)&7]);
-			if( curMatBits < 0 || diff & (15 << 14) != 0 )
-				ctx.setColorMask((mbits >> 14) & 1 != 0, (mbits >> 14) & 2 != 0, (mbits >> 14) & 4 != 0, (mbits >> 14) & 8 != 0);
-			curMatBits = mbits;
-		}
+		driver.selectMaterial(mbits);
 		selectShader(m.shader);
 	}
 
 	function selectBuffer( buf : h3d.impl.MemoryManager.BigBuffer ) {
 		if( buf.isDisposed() )
 			return false;
-		if( buf == curBuffer )
-			return true;
-		curBuffer = buf;
-		curMultiBuffer = null;
-		if( buf.stride < curShader.stride )
-			throw "Buffer stride (" + buf.stride + ") and shader stride (" + curShader.stride + ") mismatch";
-		if( !buf.written )
-			mem.finalize(buf);
-		var pos = 0, offset = 0;
-		var bits = curShader.bufferFormat;
-		while( offset < curShader.stride ) {
-			var size = bits & 7;
-			ctx.setVertexBufferAt(pos++, buf.vbuf, offset, FORMAT[size]);
-			offset += size == 0 ? 1 : size;
-			bits >>= 3;
-		}
-		for( i in pos...curAttributes )
-			ctx.setVertexBufferAt(i, null);
-		curAttributes = pos;
+		driver.selectBuffer(buf.vbuf);
 		return true;
 	}
 
@@ -223,7 +126,7 @@ class Engine {
 			}
 			if( ntri > 0 && selectBuffer(b.b) ) {
 				// *3 because it's the position in indexes which are always by 3
-				ctx.drawTriangles(indexes.ibuf, pos * 3, ntri);
+				driver.draw(indexes.ibuf, pos * 3, ntri);
 				drawTriangles += ntri;
 				drawCalls++;
 			}
@@ -241,7 +144,7 @@ class Engine {
 		if( drawTri < 0 ) drawTri = maxTri - startTri;
 		if( drawTri > 0 && selectBuffer(b.b) ) {
 			// *3 because it's the position in indexes which are always by 3
-			ctx.drawTriangles(indexes.ibuf, startTri * 3, drawTri);
+			driver.draw(indexes.ibuf, startTri * 3, drawTri);
 			drawTriangles += drawTri;
 			drawCalls++;
 		}
@@ -250,44 +153,13 @@ class Engine {
 	public function renderMultiBuffers( buffers : Array<h3d.impl.Buffer.BufferOffset>, indexes : h3d.impl.Indexes, startTri = 0, drawTri = -1 ) {
 		var maxTri = Std.int(indexes.count / 3);
 		if( maxTri <= 0 ) return;
-		
-		// select the multiple buffers elements
-		var changed = curMultiBuffer == null || curMultiBuffer.length != buffers.length;
-		if( !changed )
-			for( i in 0...curMultiBuffer.length )
-				if( buffers[i] != curMultiBuffer[i] ) {
-					changed = true;
-					break;
-				}
-		if( changed ) {
-			var pos = 0, offset = 0;
-			var bits = curShader.bufferFormat;
-			while( offset < curShader.stride ) {
-				var size = bits & 7;
-				var b = buffers[pos];
-				if( b.b.next != null )
-					throw "Buffer is split";
-				if( !b.b.b.written )
-					mem.finalize(b.b.b);
-				ctx.setVertexBufferAt(pos, b.b.b.vbuf, b.offset, FORMAT[size]);
-				offset += size == 0 ? 1 : size;
-				bits >>= 3;
-				pos++;
-			}
-			for( i in pos...curAttributes )
-				ctx.setVertexBufferAt(i, null);
-			curAttributes = pos;
-			curBuffer = null;
-			curMultiBuffer = buffers;
-		}
-		
+		driver.selectMultiBuffers(buffers);
 		if( indexes.isDisposed() )
 			return;
-		
 		if( drawTri < 0 ) drawTri = maxTri - startTri;
 		if( drawTri > 0 ) {
 			// render
-			ctx.drawTriangles(indexes.ibuf, startTri * 3, drawTri);
+			driver.draw(indexes.ibuf, startTri * 3, drawTri);
 			drawTriangles += drawTri;
 			drawCalls++;
 		}
@@ -295,31 +167,24 @@ class Engine {
 
 	function set_debug(d) {
 		debug = d;
-		if( ctx != null ) ctx.enableErrorChecking = d && hardware;
+		driver.setDebug(debug);
 		return d;
 	}
 
-	function onCreate(_) {
-		var old = ctx;
+	function onCreate( disposed ) {
 		if( autoResize ) {
-			width = System.width;
-			height = System.height;
+			width = hxd.System.width;
+			height = hxd.System.height;
 		}
-		if( old != null ) {
-			if( old.driverInfo != "Disposed" ) throw "Duplicate onCreate()";
-			old.dispose();
-			hxsl.Shader.ShaderGlobals.disposeAll();
-			ctx = s3d.context3D;
-			mem.onContextLost(ctx);
-		} else {
-			ctx = s3d.context3D;
-			mem = new h3d.impl.MemoryManager(ctx, 65400);
-		}
-		hardware = ctx.driverInfo.toLowerCase().indexOf("software") == -1;
+		if( disposed )
+			mem.onContextLost();
+		else
+			mem = new h3d.impl.MemoryManager(driver, 65400);
+		hardware = driver.isHardware();
 		set_debug(debug);
 		set_fullScreen(fullScreen);
 		resize(width, height, antiAlias);
-		if( old != null )
+		if( disposed )
 			onContextLost();
 		else
 			onReady();
@@ -331,33 +196,19 @@ class Engine {
 	public dynamic function onReady() {
 	}
 	
-	function onStageResize(_) {
-		if( ctx != null && autoResize && ctx.driverInfo != "Disposed" ) {
-			var w = System.width, h = System.height;
+	function onStageResize() {
+		if( autoResize && !driver.isDisposed() ) {
+			var w = hxd.System.width, h = hxd.System.height;
 			if( w != width || h != height )
 				resize(w, h, antiAlias);
 			onResized();
 		}
 	}
 	
-	var fsDelayed : Bool;
 	function set_fullScreen(v) {
 		fullScreen = v;
-		if( ctx != null && System.isWindowed ) {
-			var stage = flash.Lib.current.stage;
-			var isAir = flash.system.Capabilities.playerType == "Desktop";
-			var state = v ? (isAir ? flash.display.StageDisplayState.FULL_SCREEN_INTERACTIVE : flash.display.StageDisplayState.FULL_SCREEN) : flash.display.StageDisplayState.NORMAL;
-			if( stage.displayState != state ) {
-				var t = flash.Lib.getTimer();
-				// delay first fullsrceen toggle on OSX/Air to prevent the command window to spawn over
-				if( v && isAir && t < 5000 && !fsDelayed && flash.system.Capabilities.os.indexOf("Mac") != -1 ) {
-					fsDelayed = true;
-					haxe.Timer.delay(function() this.fullScreen = fullScreen, 1000);
-					return v;
-				}
-				stage.displayState = state;
-			}
-		}
+		if( mem != null && hxd.System.isWindowed )
+			hxd.Stage.getInstance().setFullScreen(v);
 		return v;
 	}
 	
@@ -371,72 +222,39 @@ class Engine {
 		this.width = width;
 		this.height = height;
 		this.antiAlias = aa;
-		if( ctx.driverInfo != "Disposed" ) {
-			try {
-				ctx.configureBackBuffer(width, height, aa);
-			} catch( e : Dynamic ) {
-				throw Std.string(e) + " " + width + "x" + height;
-			}
-		}
+		if( !driver.isDisposed() ) driver.resize(width, height, aa);
 	}
 
 	public function begin() {
-		if( ctx == null || ctx.driverInfo == "Disposed" )
+		if( driver.isDisposed() )
 			return false;
-		ctx.clear( ((backgroundColor>>16)&0xFF)/255 , ((backgroundColor>>8)&0xFF)/255, (backgroundColor&0xFF)/255, ((backgroundColor>>>24)&0xFF)/255);
+		driver.clear( ((backgroundColor>>16)&0xFF)/255 , ((backgroundColor>>8)&0xFF)/255, (backgroundColor&0xFF)/255, ((backgroundColor>>>24)&0xFF)/255);
 		// init
 		frameCount++;
 		drawTriangles = 0;
 		shaderSwitches = 0;
 		drawCalls = 0;
-		curMatBits = -1;
-		curShader = null;
-		curBuffer = null;
-		curMultiBuffer = null;
 		curProjMatrix = null;
-		curTextures = [];
-		curSamplerBits = [];
+		driver.reset();
 		return true;
 	}
 
 	function reset() {
-		curMatBits = -1;
-		curShader = null;
-		curBuffer = null;
-		curMultiBuffer = null;
-		for( i in 0...curAttributes )
-			ctx.setVertexBufferAt(i, null);
-		curAttributes = 0;
-		for( i in 0...curTextures.length )
-			ctx.setTextureAt(i, null);
-		curTextures = [];
+		driver.reset();
 	}
 
 	public function end() {
-		ctx.present();
+		driver.present();
 		reset();
 		curProjMatrix = null;
 	}
 
 	public function setTarget( tex : h3d.mat.Texture, useDepth = false, clearColor = 0 ) {
-		if( tex == null ) {
-			ctx.setRenderToBackBuffer();
-			inTarget = false;
-		} else {
-			if( inTarget )
-				throw "Calling setTarget() while already set";
-			ctx.setRenderToTexture(tex.t, useDepth);
-			inTarget = true;
-			reset();
-			ctx.clear( ((clearColor>>16)&0xFF)/255 , ((clearColor>>8)&0xFF)/255, (clearColor&0xFF)/255, ((clearColor>>>24)&0xFF)/255);
-		}
+		driver.setRenderTarget(tex == null ? null : tex.t, useDepth, clearColor);
 	}
 
 	public function setRenderZone( x = 0, y = 0, width = -1, height = -1 ) {
-		if( x == 0 && y == 0 && width < 0 && height < 0 )
-			ctx.setScissorRectangle(null);
-		else
-			ctx.setScissorRectangle(new flash.geom.Rectangle(x, y, width < 0 ? this.width : width, height < 0 ? this.height : height));
+		driver.setRenderZone(x, y, width, height);
 	}
 
 	public function render( obj : { function render( engine : Engine ) : Void; } ) {
@@ -444,12 +262,12 @@ class Engine {
 		obj.render(this);
 		end();
 				
-		var delta = flash.Lib.getTimer() - lastTime;
+		var delta = haxe.Timer.stamp() - lastTime;
 		lastTime += delta;
 		if( delta > 0 ) {
-			var curFps = 1000 / delta;
+			var curFps = 1. / delta;
 			if( curFps > realFps * 2 ) curFps = realFps * 2 else if( curFps < realFps * 0.5 ) curFps = realFps * 0.5;
-			var f = delta / 500;
+			var f = delta / .5;
 			if( f > 0.3 ) f = 0.3;
 			realFps = realFps * (1 - f) + curFps * f; // smooth a bit the fps
 		}
@@ -496,68 +314,12 @@ class Engine {
 	}
 
 	public function dispose() {
-		s3d.removeEventListener(flash.events.Event.CONTEXT3D_CREATE, onCreate);
-		ctx.dispose();
-		ctx = null;
+		driver.dispose();
+		hxd.Stage.getInstance().removeResizeEvent(onStageResize);
 	}
 	
 	function get_fps() {
 		return Math.ceil(realFps * 100) / 100;
 	}
-
-	static var BLEND = [
-		flash.display3D.Context3DBlendFactor.ONE,
-		flash.display3D.Context3DBlendFactor.ZERO,
-		flash.display3D.Context3DBlendFactor.SOURCE_ALPHA,
-		flash.display3D.Context3DBlendFactor.SOURCE_COLOR,
-		flash.display3D.Context3DBlendFactor.DESTINATION_ALPHA,
-		flash.display3D.Context3DBlendFactor.DESTINATION_COLOR,
-		flash.display3D.Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA,
-		flash.display3D.Context3DBlendFactor.ONE_MINUS_SOURCE_COLOR,
-		flash.display3D.Context3DBlendFactor.ONE_MINUS_DESTINATION_ALPHA,
-		flash.display3D.Context3DBlendFactor.ONE_MINUS_DESTINATION_COLOR
-	];
-
-	static var FACE = [
-		flash.display3D.Context3DTriangleFace.NONE,
-		flash.display3D.Context3DTriangleFace.BACK,
-		flash.display3D.Context3DTriangleFace.FRONT,
-		flash.display3D.Context3DTriangleFace.FRONT_AND_BACK,
-	];
-
-	static var COMPARE = [
-		flash.display3D.Context3DCompareMode.ALWAYS,
-		flash.display3D.Context3DCompareMode.NEVER,
-		flash.display3D.Context3DCompareMode.EQUAL,
-		flash.display3D.Context3DCompareMode.NOT_EQUAL,
-		flash.display3D.Context3DCompareMode.GREATER,
-		flash.display3D.Context3DCompareMode.GREATER_EQUAL,
-		flash.display3D.Context3DCompareMode.LESS,
-		flash.display3D.Context3DCompareMode.LESS_EQUAL,
-	];
-
-	static var FORMAT = [
-		flash.display3D.Context3DVertexBufferFormat.BYTES_4,
-		flash.display3D.Context3DVertexBufferFormat.FLOAT_1,
-		flash.display3D.Context3DVertexBufferFormat.FLOAT_2,
-		flash.display3D.Context3DVertexBufferFormat.FLOAT_3,
-		flash.display3D.Context3DVertexBufferFormat.FLOAT_4,
-	];
-	
-	static var WRAP = [
-		flash.display3D.Context3DWrapMode.CLAMP,
-		flash.display3D.Context3DWrapMode.REPEAT,
-	];
-	
-	static var FILTER = [
-		flash.display3D.Context3DTextureFilter.NEAREST,
-		flash.display3D.Context3DTextureFilter.LINEAR,
-	];
-	
-	static var MIP = [
-		flash.display3D.Context3DMipFilter.MIPNONE,
-		flash.display3D.Context3DMipFilter.MIPNEAREST,
-		flash.display3D.Context3DMipFilter.MIPLINEAR,
-	];
 	
 }

+ 1 - 1
h3d/anim/Animation.hx

@@ -123,7 +123,7 @@ class Animation {
 			var obj = base.getObjectByName(a.objectName);
 			if( obj == null )
 				throw a.objectName + " was not found";
-			var joint = flash.Lib.as(obj, h3d.scene.Skin.Joint);
+			var joint = Std.instance(obj, h3d.scene.Skin.Joint);
 			if( joint != null ) {
 				currentSkin = cast joint.parent;
 				a2.targetSkin = currentSkin;

+ 2 - 2
h3d/anim/FrameAnimation.hx

@@ -2,8 +2,8 @@ package h3d.anim;
 import h3d.anim.Animation;
 
 class FrameObject extends AnimatedObject {
-	public var frames : flash.Vector<h3d.Matrix>;
-	public var alphas : flash.Vector<Float>;
+	public var frames : haxe.ds.Vector<h3d.Matrix>;
+	public var alphas : haxe.ds.Vector<Float>;
 	
 	override function clone() : AnimatedObject {
 		var o = new FrameObject(objectName);

+ 2 - 2
h3d/anim/LinearAnimation.hx

@@ -19,8 +19,8 @@ class LinearFrame {
 class LinearObject extends AnimatedObject {
 	public var hasRotation : Bool;
 	public var hasScale : Bool;
-	public var frames : flash.Vector<LinearFrame>;
-	public var alphas : flash.Vector<Float>;
+	public var frames : haxe.ds.Vector<LinearFrame>;
+	public var alphas : haxe.ds.Vector<Float>;
 	public var matrix : h3d.Matrix;
 	override function clone() : AnimatedObject {
 		var o = new LinearObject(objectName);

+ 4 - 4
h3d/fbx/Library.hx

@@ -354,8 +354,8 @@ class Library {
 		
 			for( c in curves ) {
 				var frames = null, alpha = null;
-				var frames = c.t == null && c.r == null && c.s == null ? null : new flash.Vector(numFrames);
-				var alpha = c.a == null ? null : new flash.Vector(numFrames);
+				var frames = c.t == null && c.r == null && c.s == null ? null : new haxe.ds.Vector(numFrames);
+				var alpha = c.a == null ? null : new haxe.ds.Vector(numFrames);
 				// skip empty curves
 				if( frames == null && alpha == null )
 					continue;
@@ -442,8 +442,8 @@ class Library {
 
 			for( c in curves ) {
 				var frames = null, alpha = null;
-				var frames = c.t == null && c.r == null && c.s == null ? null : new flash.Vector(numFrames);
-				var alpha = c.a == null ? null : new flash.Vector(numFrames);
+				var frames = c.t == null && c.r == null && c.s == null ? null : new haxe.ds.Vector(numFrames);
+				var alpha = c.a == null ? null : new haxe.ds.Vector(numFrames);
 				// skip empty curves
 				if( frames == null && alpha == null )
 					continue;

+ 4 - 4
h3d/impl/Buffer.hx

@@ -38,24 +38,24 @@ class Buffer {
 		}
 	}
 	
-	public function uploadVector( data : flash.Vector<Float>, dataPos : Int, nverts : Int ) {
+	public function uploadVector( data : hxd.FloatBuffer, dataPos : Int, nverts : Int ) {
 		var cur = this;
 		while( nverts > 0 ) {
 			if( cur == null ) throw "Too many vertexes";
 			var count = nverts > cur.nvert ? cur.nvert : nverts;
-			cur.b.vbuf.uploadFromVector( dataPos == 0 ? data : data.slice(dataPos,count*b.stride+dataPos), cur.pos, count );
+			cur.b.mem.driver.uploadVertexBuffer(cur.b.vbuf, cur.pos, count, data, dataPos);
 			dataPos += count * b.stride;
 			nverts -= count;
 			cur = cur.next;
 		}
 	}
 	
-	public function upload( data : flash.utils.ByteArray, dataPos : Int, nverts : Int ) {
+	public function uploadBytes( data : haxe.io.Bytes, dataPos : Int, nverts : Int ) {
 		var cur = this;
 		while( nverts > 0 ) {
 			if( cur == null ) throw "Too many vertexes";
 			var count = nverts > cur.nvert ? cur.nvert : nverts;
-			cur.b.vbuf.uploadFromByteArray(data, dataPos, cur.pos, count);
+			cur.b.mem.driver.uploadVertexBytes(cur.b.vbuf, cur.pos, count, data, dataPos);
 			dataPos += count * b.stride * 4;
 			nverts -= count;
 			cur = cur.next;

+ 114 - 0
h3d/impl/Driver.hx

@@ -0,0 +1,114 @@
+package h3d.impl;
+
+#if flash
+typedef IndexBuffer = flash.display3D.IndexBuffer3D;
+typedef VertexBuffer = Stage3dDriver.VertexWrapper;
+typedef Texture = flash.display3D.textures.TextureBase;
+#else
+typedef IndexBuffer = Int;
+typedef VertexBuffer = Int;
+typedef Texture = Int;
+#end
+
+class Driver {
+	
+	public function isDisposed() {
+		return true;
+	}
+	
+	public function dispose() {
+	}
+	
+	public function clear( r : Float, g : Float, b : Float, a : Float ) {
+	}
+	
+	public function reset() {
+	}
+	
+	public function getDriverName( details : Bool ) {
+		return "Not available";
+	}
+	
+	public function init( onCreate : Bool -> Void, forceSoftware = false ) {
+	}
+	
+	public function resize( width : Int, height : Int, aa : Int ) {
+	}
+	
+	public function selectMaterial( mbits : Int ) {
+	}
+	
+	/** return value tells if we have shader shader **/
+	public function selectShader( shader : Shader ) : Bool {
+		return false;
+	}
+	
+	public function selectBuffer( buffer : VertexBuffer ) {
+	}
+	
+	public function getShaderInputNames() : Array<String> {
+		return null;
+	}
+	
+	public function selectMultiBuffers( buffers : Array<Buffer.BufferOffset> ) {
+	}
+	
+	public function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {
+	}
+	
+	public function setRenderZone( x : Int, y : Int, width : Int, height : Int ) {
+	}
+	
+	public function setRenderTarget( tex : Null<Texture>, useDepth : Bool, clearColor : Int ) {
+	}
+	
+	public function present() {
+	}
+	
+	public function isHardware() {
+		return true;
+	}
+	
+	public function setDebug( b : Bool ) {
+	}
+	
+	public function allocTexture( t : h3d.mat.Texture ) : Texture {
+		return null;
+	}
+
+	public function disposeTexture( t : Texture ) {
+	}
+	
+	public function disposeVertex( v : VertexBuffer ) {
+	}
+	
+	public function allocIndexes( count : Int ) : IndexBuffer {
+		return null;
+	}
+
+	public function allocVertex( count : Int, stride : Int ) : VertexBuffer {
+		return null;
+	}
+	
+	public function uploadIndexesBuffer( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : hxd.IndexBuffer, bufPos : Int ) {
+	}
+
+	public function uploadIndexesBytes( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : haxe.io.Bytes , bufPos : Int ) {
+	}
+	
+	public function uploadVertexBuffer( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : hxd.FloatBuffer, bufPos : Int ) {
+	}
+
+	public function uploadVertexBytes( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+	}
+	
+	public function disposeIndexes( i : IndexBuffer ) {
+	}
+	
+	public function uploadTextureBitmap( t : h3d.mat.Texture, bmp : hxd.BitmapData, mipLevel : Int, side : Int ) {
+	}
+
+	public function uploadTextureBytes( t : h3d.mat.Texture, bytes : haxe.io.Bytes, mipLevel : Int, side : Int ) {
+	}
+	
+}

+ 6 - 1
h3d/impl/Indexes.hx

@@ -1,10 +1,11 @@
 package h3d.impl;
 
 @:allow(h3d.impl.MemoryManager)
+@:allow(h3d.Engine)
 class Indexes {
 
 	var mem : MemoryManager;
-	public var ibuf : flash.display3D.IndexBuffer3D;
+	var ibuf : Driver.IndexBuffer;
 	public var count(default,null) : Int;
 	
 	function new(mem, ibuf, count) {
@@ -17,6 +18,10 @@ class Indexes {
 		return ibuf == null;
 	}
 	
+	public function upload( indexes : hxd.IndexBuffer, pos : Int, count : Int, bufferPos = 0 ) {
+		mem.driver.uploadIndexesBuffer(this.ibuf, pos, count, indexes, bufferPos);
+	}
+	
 	public function dispose() {
 		if( ibuf != null )
 			mem.deleteIndexes(this);

+ 39 - 77
h3d/impl/MemoryManager.hx

@@ -15,18 +15,19 @@ class FreeCell {
 @:allow(h3d)
 class BigBuffer {
 
+	var mem : MemoryManager;
 	var stride : Int;
 	var size : Int;
-	var written : Bool;
-	var vbuf : flash.display3D.VertexBuffer3D;
+	
+	var vbuf : Driver.VertexBuffer;
 	var free : FreeCell;
 	var next : BigBuffer;
 	#if debug
 	public var allocHead : Buffer;
 	#end
 	
-	function new(v, stride, size) {
-		written = false;
+	function new(mem, v, stride, size) {
+		this.mem = mem;
 		this.size = size;
 		this.stride = stride;
 		this.vbuf = v;
@@ -64,7 +65,7 @@ class BigBuffer {
 	}
 
 	function dispose() {
-		vbuf.dispose();
+		mem.driver.disposeVertex(vbuf);
 		vbuf = null;
 	}
 	
@@ -79,13 +80,13 @@ class MemoryManager {
 	static inline var MAX_MEMORY = 250 << 20; // MB
 	static inline var MAX_BUFFERS = 4096;
 
-	var ctx : flash.display3D.Context3D;
-	var empty : flash.utils.ByteArray;
+	@:allow(h3d)
+	var driver : Driver;
 	var buffers : Array<BigBuffer>;
 	var idict : Map<Indexes,Bool>;
 	
-	var tdict : haxe.ds.WeakMap<h3d.mat.Texture,flash.display3D.textures.TextureBase>;
-	var textures : Array<flash.display3D.textures.TextureBase>;
+	var tdict : haxe.ds.WeakMap<h3d.mat.Texture,Driver.Texture>;
+	var textures : Array<Driver.Texture>;
 	
 	public var indexes(default,null) : Indexes;
 	public var quadIndexes(default,null) : Indexes;
@@ -93,34 +94,33 @@ class MemoryManager {
 	public var bufferCount(default,null) : Int;
 	public var allocSize(default,null) : Int;
 
-	public function new(ctx,allocSize) {
-		this.ctx = ctx;
+	public function new(driver,allocSize) {
+		this.driver = driver;
 		this.allocSize = allocSize;
 
 		idict = new Map();
 		tdict = new haxe.ds.WeakMap();
 		textures = new Array();
-		empty = new flash.utils.ByteArray();
 		buffers = new Array();
 		
 		initIndexes();
 	}
 	
 	function initIndexes() {
-		var indices = new flash.Vector<UInt>();
-		for( i in 0...allocSize ) indices[i] = i;
+		var indices = new hxd.IndexBuffer();
+		for( i in 0...allocSize ) indices.push(i);
 		indexes = allocIndex(indices);
 
-		var indices = new flash.Vector<UInt>();
+		var indices = new hxd.IndexBuffer();
 		var p = 0;
 		for( i in 0...allocSize >> 2 ) {
 			var k = i << 2;
-			indices[p++] = k;
-			indices[p++] = k + 1;
-			indices[p++] = k + 2;
-			indices[p++] = k + 2;
-			indices[p++] = k + 1;
-			indices[p++] = k + 3;
+			indices.push(k);
+			indices.push(k + 1);
+			indices.push(k + 2);
+			indices.push(k + 2);
+			indices.push(k + 1);
+			indices.push(k + 3);
 		}
 		quadIndexes = allocIndex(indices);
 	}
@@ -234,16 +234,7 @@ class MemoryManager {
 	}
 	
 	function initTexture( t : h3d.mat.Texture ) {
-		var fmt = switch( t.format ) {
-		case Rgba, Atf:
-			flash.display3D.Context3DTextureFormat.BGRA;
-		case AtfCompressed(alpha):
-			alpha ? flash.display3D.Context3DTextureFormat.COMPRESSED_ALPHA : flash.display3D.Context3DTextureFormat.COMPRESSED;
-		}
-		if( t.isCubic )
-			t.t = ctx.createCubeTexture(t.width, fmt, t.isTarget, t.mipLevels);
-		else
-			t.t = ctx.createTexture(t.width, t.height, fmt, t.isTarget, t.mipLevels);
+		t.t = driver.allocTexture(t);
 		tdict.set(t, t.t);
 		textures.push(t.t);
 	}
@@ -251,7 +242,7 @@ class MemoryManager {
 	@:allow(h3d.impl.Indexes.dispose)
 	function deleteIndexes( i : Indexes ) {
 		idict.remove(i);
-		i.ibuf.dispose();
+		driver.disposeIndexes(i.ibuf);
 		i.ibuf = null;
 		usedMemory -= i.count * 2;
 	}
@@ -260,7 +251,7 @@ class MemoryManager {
 	function deleteTexture( t : h3d.mat.Texture ) {
 		textures.remove(t.t);
 		tdict.remove(t);
-		t.t.dispose();
+		driver.disposeTexture(t.t);
 		t.t = null;
 	}
 
@@ -295,10 +286,9 @@ class MemoryManager {
 		};
 	}
 
-	public function allocAtfTexture( width : Int, height : Int, mipLevels : Int = 0, alpha : Bool = false, compress : Bool = false, cubic : Bool = false, ?allocPos : AllocPos ) {
+	public function allocCustomTexture( fmt : h3d.mat.Data.TextureFormat, width : Int, height : Int, mipLevels : Int = 0, cubic : Bool = false, target : Bool = false, ?allocPos : AllocPos ) {
 		freeTextures();
-		var fmt = compress ? (alpha ? flash.display3D.Context3DTextureFormat.COMPRESSED_ALPHA : flash.display3D.Context3DTextureFormat.COMPRESSED) : flash.display3D.Context3DTextureFormat.BGRA;
-		return newTexture(compress ? AtfCompressed(alpha) : Atf, width, height, cubic, false, mipLevels, allocPos);
+		return newTexture(fmt, width, height, cubic, target, mipLevels, allocPos);
 	}
 	
 	public function allocTexture( width : Int, height : Int, mipMap = false, ?allocPos : AllocPos ) {
@@ -316,19 +306,6 @@ class MemoryManager {
 		return newTexture(Rgba, width, height, false, true, 0, allocPos);
 	}
 
-	public function makeTexture( ?bmp : flash.display.BitmapData, ?mbmp : h3d.mat.Bitmap, hasMipMap = false, ?allocPos : AllocPos ) {
-		var t;
-		if( bmp != null ) {
-			t = allocTexture(bmp.width, bmp.height, hasMipMap, allocPos);
-			if( hasMipMap ) t.uploadMipMap(bmp) else t.upload(bmp);
-		} else {
-			if( hasMipMap ) throw "No support for mipmap + bytes";
-			t = allocTexture(mbmp.width, mbmp.height, hasMipMap, allocPos);
-			t.uploadBytes(mbmp.bytes);
-		}
-		return t;
-	}
-
 	public function allocCubeTexture( size : Int, mipMap = false, ?allocPos : AllocPos ) {
 		freeTextures();
 		var levels = 0;
@@ -339,23 +316,23 @@ class MemoryManager {
 		return newTexture(Rgba, size, size, true, false, levels, allocPos);
 	}
 
-	public function allocIndex( indices : flash.Vector<UInt> ) {
-		var ibuf = ctx.createIndexBuffer(indices.length);
-		ibuf.uploadFromVector(indices, 0, indices.length);
+	public function allocIndex( indices : hxd.IndexBuffer ) {
+		var ibuf = driver.allocIndexes(indices.length);
 		var idx = new Indexes(this, ibuf, indices.length);
+		idx.upload(indices, 0, indices.length);
 		idict.set(idx, true);
 		usedMemory += idx.count * 2;
 		return idx;
 	}
 
-	public function allocBytes( bytes : flash.utils.ByteArray, stride : Int, align, ?allocPos : AllocPos ) {
+	public function allocBytes( bytes : haxe.io.Bytes, stride : Int, align, ?allocPos : AllocPos ) {
 		var count = Std.int(bytes.length / (stride * 4));
 		var b = alloc(count, stride, align, allocPos);
-		b.upload(bytes, 0, count);
+		b.uploadBytes(bytes, 0, count);
 		return b;
 	}
 
-	public function allocVector( v : flash.Vector<Float>, stride, align, ?allocPos : AllocPos ) {
+	public function allocVector( v : hxd.FloatBuffer, stride, align, ?allocPos : AllocPos ) {
 		var nvert = Std.int(v.length / stride);
 		var b = alloc(nvert, stride, align, allocPos);
 		b.uploadVector(v, 0, nvert);
@@ -375,7 +352,7 @@ class MemoryManager {
 			tall.remove(t);
 		var count = 0;
 		for( t in tall.keys() ) {
-			t.dispose();
+			driver.disposeTexture(t);
 			textures.remove(t);
 			count++;
 		}
@@ -498,10 +475,13 @@ class MemoryManager {
 				}
 				return alloc(nvect, stride, align, allocPos);
 			}
-			var v = ctx.createVertexBuffer(size, stride);
+			var v = driver.allocVertex(size, stride);
 			usedMemory += mem;
 			bufferCount++;
-			b = new BigBuffer(v, stride, size);
+			b = new BigBuffer(this, v, stride, size);
+			#if flash
+			untyped v.b = b;
+			#end
 			b.next = buffers[stride];
 			buffers[stride] = b;
 			free = b.free;
@@ -525,25 +505,7 @@ class MemoryManager {
 		return b;
 	}
 
-	@:allow(h3d)
-	function finalize( b : BigBuffer ) {
-		if( !b.written ) {
-			b.written = true;
-			// fill all the free positions that were unwritten with zeroes (necessary for flash)
-			var f = b.free;
-			while( f != null ) {
-				if( f.count > 0 ) {
-					var mem : UInt = f.count * b.stride * 4;
-					if( empty.length < mem ) empty.length = mem;
-					b.vbuf.uploadFromByteArray(empty, 0, f.pos, f.count);
-				}
-				f = f.next;
-			}
-		}
-	}
-	
-	public function onContextLost( newContext ) {
-		ctx = newContext;
+	public function onContextLost() {
 		indexes.dispose();
 		quadIndexes.dispose();
 		var tkeys = Lambda.array({ iterator : tdict.keys });

+ 10 - 0
h3d/impl/Shader.hx

@@ -0,0 +1,10 @@
+package h3d.impl;
+
+#if flash
+typedef Shader = hxsl.Shader;
+#else
+class Shader implements Dynamic {
+	public function new() {
+	}
+}
+#end

+ 7 - 3
h3d/impl/Shaders.hx

@@ -1,7 +1,8 @@
 package h3d.impl;
 
-class PointShader extends hxsl.Shader {
+class PointShader extends h3d.impl.Shader {
 
+#if flash
 	static var SRC = {
 		var input : {
 			pos : Float2,
@@ -18,11 +19,13 @@ class PointShader extends hxsl.Shader {
 			out = color;
 		}
 	}
+#end
 	
 }
 
-class LineShader extends hxsl.Shader {
+class LineShader extends h3d.impl.Shader {
 
+#if flash
 	static var SRC = {
 		var input : {
 			pos : Float2,
@@ -43,5 +46,6 @@ class LineShader extends hxsl.Shader {
 			out = color;
 		}
 	}
-	
+#end
+
 }

+ 422 - 0
h3d/impl/Stage3dDriver.hx

@@ -0,0 +1,422 @@
+package h3d.impl;
+import h3d.impl.Driver;
+
+#if flash
+
+@:allow(h3d.impl.Stage3dDriver)
+class VertexWrapper {
+	var vbuf : flash.display3D.VertexBuffer3D;
+	var stride : Int;
+	var written : Bool;
+	var b : MemoryManager.BigBuffer;
+	
+	function new(vbuf, stride) {
+		this.vbuf = vbuf;
+		this.stride = stride;
+	}
+	
+	function finalize( driver : Stage3dDriver ) {
+		if( written ) return;
+		written = true;
+		// fill all the free positions that were unwritten with zeroes (necessary for flash)
+		var f = b.free;
+		while( f != null ) {
+			if( f.count > 0 ) {
+				var mem : UInt = f.count * b.stride * 4;
+				if( driver.empty.length < mem ) driver.empty.length = mem;
+				driver.uploadVertexBytes(b.vbuf, f.pos, f.count, haxe.io.Bytes.ofData(driver.empty), 0);
+			}
+			f = f.next;
+		}
+	}
+
+}
+
+class Stage3dDriver extends Driver {
+	
+	var s3d : flash.display.Stage3D;
+	var ctx : flash.display3D.Context3D;
+	var onCreateCallback : Bool -> Void;
+	
+	var curMatBits : Int;
+	var curShader : hxsl.Shader.ShaderInstance;
+	var curBuffer : VertexBuffer;
+	var curMultiBuffer : Array<h3d.impl.Buffer.BufferOffset>;
+	var curAttributes : Int;
+	var curTextures : Array<h3d.mat.Texture>;
+	var curSamplerBits : Array<Int>;
+	var inTarget : Bool;
+	
+	@:allow(h3d.impl.VertexWrapper)
+	var empty : flash.utils.ByteArray;
+	
+	public function new() {
+		empty = new flash.utils.ByteArray();
+		s3d = flash.Lib.current.stage.stage3Ds[0];
+		curTextures = [];
+	}
+	
+	override function getDriverName(details:Bool) {
+		return ctx == null ? "None" : (details ? ctx.driverInfo : ctx.driverInfo.split(" ")[0]);
+	}
+	
+	override function reset() {
+		curMatBits = -1;
+		curShader = null;
+		curBuffer = null;
+		curMultiBuffer = null;
+		for( i in 0...curAttributes )
+			ctx.setVertexBufferAt(i, null);
+		curAttributes = 0;
+		for( i in 0...curTextures.length )
+			ctx.setTextureAt(i, null);
+		curTextures = [];
+		curSamplerBits = [];
+	}
+	
+	override function init( onCreate, forceSoftware = false ) {
+		this.onCreateCallback = onCreate;
+		s3d.addEventListener(flash.events.Event.CONTEXT3D_CREATE, this.onCreate);
+		s3d.requestContext3D( forceSoftware ? "software" : "auto" );
+	}
+	
+	function onCreate(_) {
+		var old = ctx;
+		if( old != null ) {
+			if( old.driverInfo != "Disposed" ) throw "Duplicate onCreate()";
+			old.dispose();
+			hxsl.Shader.ShaderGlobals.disposeAll();
+			ctx = s3d.context3D;
+			onCreateCallback(true);
+		} else {
+			ctx = s3d.context3D;
+			onCreateCallback(false);
+		}
+	}
+	
+	override function isHardware() {
+		return ctx != null && ctx.driverInfo.toLowerCase().indexOf("software") == -1;
+	}
+	
+	override function resize(width, height, aa) {
+		ctx.configureBackBuffer(width, height, aa);
+	}
+	
+	override function clear(r, g, b, a) {
+		ctx.clear(r, g, b, a);
+	}
+	
+	override function dispose() {
+		s3d.removeEventListener(flash.events.Event.CONTEXT3D_CREATE, onCreate);
+		if( ctx != null ) ctx.dispose();
+		ctx = null;
+	}
+	
+	override function isDisposed() {
+		return ctx == null || ctx.driverInfo == "Disposed";
+	}
+	
+	override function present() {
+		ctx.present();
+	}
+	
+	override function disposeTexture( t : Texture ) {
+		t.dispose();
+	}
+	
+	override function allocVertex( count : Int, stride : Int ) : VertexBuffer {
+		return new VertexWrapper(ctx.createVertexBuffer(count, stride), stride);
+	}
+
+	override function allocIndexes( count : Int ) : IndexBuffer {
+		return ctx.createIndexBuffer(count);
+	}
+	
+	override function allocTexture( t : h3d.mat.Texture ) : Texture {
+		var fmt = switch( t.format ) {
+		case Rgba, Atf:
+			flash.display3D.Context3DTextureFormat.BGRA;
+		case AtfCompressed(alpha):
+			alpha ? flash.display3D.Context3DTextureFormat.COMPRESSED_ALPHA : flash.display3D.Context3DTextureFormat.COMPRESSED;
+		}
+		return if( t.isCubic )
+			ctx.createCubeTexture(t.width, fmt, t.isTarget, t.mipLevels);
+		else
+			ctx.createTexture(t.width, t.height, fmt, t.isTarget, t.mipLevels);
+	}
+
+	override function uploadTextureBitmap( t : h3d.mat.Texture, bmp : hxd.BitmapData, mipLevel : Int, side : Int ) {
+		if( t.isCubic ) {
+			var t = flash.Lib.as(t.t, flash.display3D.textures.CubeTexture);
+			t.uploadFromBitmapData(bmp.toNative(), side, mipLevel);
+		}
+		else {
+			var t = flash.Lib.as(t.t, flash.display3D.textures.Texture);
+			t.uploadFromBitmapData(bmp.toNative(), mipLevel);
+		}
+	}
+
+	override function uploadTextureBytes( t : h3d.mat.Texture, bytes : haxe.io.Bytes, mipLevel : Int, side : Int ) {
+		switch( t.format ) {
+		case Atf, AtfCompressed(_):
+			if( t.isCubic ) {
+				var t = flash.Lib.as(t.t, flash.display3D.textures.CubeTexture);
+				t.uploadCompressedTextureFromByteArray(bytes.getData(), 0);
+			}
+			else {
+				var t = flash.Lib.as(t.t,  flash.display3D.textures.Texture);
+				t.uploadCompressedTextureFromByteArray(bytes.getData(), 0);
+			}
+		default:
+			if( t.isCubic ) {
+				var t = flash.Lib.as(t.t, flash.display3D.textures.CubeTexture);
+				t.uploadFromByteArray(bytes.getData(), 0, side, mipLevel);
+			}
+			else {
+				var t = flash.Lib.as(t.t,  flash.display3D.textures.Texture);
+				t.uploadFromByteArray(bytes.getData(), 0, mipLevel);
+			}
+		}
+	}
+	
+	override function disposeVertex( v : VertexBuffer ) {
+		v.vbuf.dispose();
+		v.b = null;
+	}
+	
+	override function disposeIndexes( i : IndexBuffer ) {
+		i.dispose();
+	}
+	
+	override function setDebug( d : Bool ) {
+		if( ctx != null ) ctx.enableErrorChecking = d && isHardware();
+	}
+	
+	override function uploadVertexBuffer( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : hxd.FloatBuffer, bufPos : Int ) {
+		var data = buf.getNative();
+		v.vbuf.uploadFromVector( bufPos == 0 ? data : data.slice(bufPos, vertexCount * v.stride + bufPos), startVertex, vertexCount );
+	}
+
+	override function uploadVertexBytes( v : VertexBuffer, startVertex : Int, vertexCount : Int, bytes : haxe.io.Bytes, bufPos : Int ) {
+		v.vbuf.uploadFromByteArray( bytes.getData(), bufPos, startVertex, vertexCount );
+	}
+
+	override function uploadIndexesBuffer( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : hxd.IndexBuffer, bufPos : Int ) {
+		var data = buf.getNative();
+		i.uploadFromVector( bufPos == 0 ? data : data.slice(bufPos, indiceCount + bufPos), startIndice, indiceCount );
+	}
+
+	override function uploadIndexesBytes( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+		i.uploadFromByteArray(buf.getData(), bufPos, startIndice, indiceCount );
+	}
+	
+	override function selectMaterial( mbits : Int ) {
+		var diff = curMatBits ^ mbits;
+		if( diff != 0 ) {
+			if( curMatBits < 0 || diff&3 != 0 )
+				ctx.setCulling(FACE[mbits&3]);
+			if( curMatBits < 0 || diff & (0xFF << 6) != 0 )
+				ctx.setBlendFactors(BLEND[(mbits>>6)&15], BLEND[(mbits>>10)&15]);
+			if( curMatBits < 0 || diff & (15 << 2) != 0 )
+				ctx.setDepthTest((mbits >> 2) & 1 == 1, COMPARE[(mbits>>3)&7]);
+			if( curMatBits < 0 || diff & (15 << 14) != 0 )
+				ctx.setColorMask((mbits >> 14) & 1 != 0, (mbits >> 14) & 2 != 0, (mbits >> 14) & 4 != 0, (mbits >> 14) & 8 != 0);
+			curMatBits = mbits;
+		}
+	}
+
+	override function selectShader( shader : Shader ) {
+		var shaderChanged = false;
+		var s = shader.getInstance();
+		if( s.program == null ) {
+			s.program = ctx.createProgram();
+			var vdata = s.vertexBytes.getData();
+			var fdata = s.fragmentBytes.getData();
+			vdata.endian = flash.utils.Endian.LITTLE_ENDIAN;
+			fdata.endian = flash.utils.Endian.LITTLE_ENDIAN;
+			s.program.upload(vdata, fdata);
+			curShader = null; // in case we had the same shader and it was disposed
+		}
+		if( s != curShader ) {
+			ctx.setProgram(s.program);
+			shaderChanged = true;
+			s.varsChanged = true;
+			// unbind extra textures
+			var tcount : Int = s.textures.length;
+			while( curTextures.length > tcount ) {
+				curTextures.pop();
+				ctx.setTextureAt(curTextures.length, null);
+			}
+			// force remapping of vertex buffer
+			curBuffer = null;
+			curMultiBuffer = null;
+			curShader = s;
+		}
+		if( s.varsChanged ) {
+			s.varsChanged = false;
+			ctx.setProgramConstantsFromVector(flash.display3D.Context3DProgramType.VERTEX, 0, s.vertexVars.toData());
+			ctx.setProgramConstantsFromVector(flash.display3D.Context3DProgramType.FRAGMENT, 0, s.fragmentVars.toData());
+			for( i in 0...s.textures.length ) {
+				var t = s.textures[i];
+				if( t == null || t.isDisposed() )
+					t = h2d.Tile.fromColor(0xFFFF00FF).getTexture();
+				var cur = curTextures[i];
+				if( t != cur ) {
+					ctx.setTextureAt(i, t.t);
+					curTextures[i] = t;
+				}
+				// if we have set one of the texture flag manually or if the shader does not configure the texture flags
+				if( !t.hasDefaultFlags() || !s.texHasConfig[s.textureMap[i]] ) {
+					if( cur == null || t.bits != curSamplerBits[i] ) {
+						ctx.setSamplerStateAt(i, WRAP[t.wrap.getIndex()], FILTER[t.filter.getIndex()], MIP[t.mipMap.getIndex()]);
+						curSamplerBits[i] = t.bits;
+					}
+				} else {
+					// the texture flags has been set by the shader, so we are in an unkown state
+					curSamplerBits[i] = -1;
+				}
+			}
+		}
+		return shaderChanged;
+	}
+	
+	override function selectBuffer( v : VertexBuffer ) {
+		if( v == curBuffer )
+			return;
+		curBuffer = v;
+		curMultiBuffer = null;
+		if( v.stride < curShader.stride )
+			throw "Buffer stride (" + v.stride + ") and shader stride (" + curShader.stride + ") mismatch";
+		if( !v.written )
+			v.finalize(this);
+		var pos = 0, offset = 0;
+		var bits = curShader.bufferFormat;
+		while( offset < curShader.stride ) {
+			var size = bits & 7;
+			ctx.setVertexBufferAt(pos++, v.vbuf, offset, FORMAT[size]);
+			offset += size == 0 ? 1 : size;
+			bits >>= 3;
+		}
+		for( i in pos...curAttributes )
+			ctx.setVertexBufferAt(i, null);
+		curAttributes = pos;
+	}
+	
+	override function getShaderInputNames() {
+		return curShader.bufferNames;
+	}
+	
+	override function selectMultiBuffers( buffers : Array<Buffer.BufferOffset> ) {
+		// select the multiple buffers elements
+		var changed = curMultiBuffer == null || curMultiBuffer.length != buffers.length;
+		if( !changed )
+			for( i in 0...curMultiBuffer.length )
+				if( buffers[i] != curMultiBuffer[i] ) {
+					changed = true;
+					break;
+				}
+		if( changed ) {
+			var pos = 0, offset = 0;
+			var bits = curShader.bufferFormat;
+			while( offset < curShader.stride ) {
+				var size = bits & 7;
+				var b = buffers[pos];
+				if( b.b.next != null )
+					throw "Buffer is split";
+				if( !b.b.b.vbuf.written )
+					b.b.b.vbuf.finalize(this);
+				ctx.setVertexBufferAt(pos, b.b.b.vbuf.vbuf, b.offset, FORMAT[size]);
+				offset += size == 0 ? 1 : size;
+				bits >>= 3;
+				pos++;
+			}
+			for( i in pos...curAttributes )
+				ctx.setVertexBufferAt(i, null);
+			curAttributes = pos;
+			curBuffer = null;
+			curMultiBuffer = buffers;
+		}
+	}
+	
+	override function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {
+		ctx.drawTriangles(ibuf, startIndex, ntriangles);
+	}
+
+	override function setRenderZone( x : Int, y : Int, width : Int, height : Int ) {
+		if( x == 0 && y == 0 && width < 0 && height < 0 )
+			ctx.setScissorRectangle(null);
+		else
+			ctx.setScissorRectangle(new flash.geom.Rectangle(x, y, width, height));
+	}
+
+	override function setRenderTarget( tex : Null<Texture>, useDepth : Bool, clearColor : Int ) {
+		if( tex == null ) {
+			ctx.setRenderToBackBuffer();
+			inTarget = false;
+		} else {
+			if( inTarget )
+				throw "Calling setTarget() while already set";
+			ctx.setRenderToTexture(tex, useDepth);
+			inTarget = true;
+			reset();
+			ctx.clear( ((clearColor>>16)&0xFF)/255 , ((clearColor>>8)&0xFF)/255, (clearColor&0xFF)/255, ((clearColor>>>24)&0xFF)/255);
+		}
+	}
+	
+	static var BLEND = [
+		flash.display3D.Context3DBlendFactor.ONE,
+		flash.display3D.Context3DBlendFactor.ZERO,
+		flash.display3D.Context3DBlendFactor.SOURCE_ALPHA,
+		flash.display3D.Context3DBlendFactor.SOURCE_COLOR,
+		flash.display3D.Context3DBlendFactor.DESTINATION_ALPHA,
+		flash.display3D.Context3DBlendFactor.DESTINATION_COLOR,
+		flash.display3D.Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA,
+		flash.display3D.Context3DBlendFactor.ONE_MINUS_SOURCE_COLOR,
+		flash.display3D.Context3DBlendFactor.ONE_MINUS_DESTINATION_ALPHA,
+		flash.display3D.Context3DBlendFactor.ONE_MINUS_DESTINATION_COLOR
+	];
+
+	static var FACE = [
+		flash.display3D.Context3DTriangleFace.NONE,
+		flash.display3D.Context3DTriangleFace.BACK,
+		flash.display3D.Context3DTriangleFace.FRONT,
+		flash.display3D.Context3DTriangleFace.FRONT_AND_BACK,
+	];
+
+	static var COMPARE = [
+		flash.display3D.Context3DCompareMode.ALWAYS,
+		flash.display3D.Context3DCompareMode.NEVER,
+		flash.display3D.Context3DCompareMode.EQUAL,
+		flash.display3D.Context3DCompareMode.NOT_EQUAL,
+		flash.display3D.Context3DCompareMode.GREATER,
+		flash.display3D.Context3DCompareMode.GREATER_EQUAL,
+		flash.display3D.Context3DCompareMode.LESS,
+		flash.display3D.Context3DCompareMode.LESS_EQUAL,
+	];
+
+	static var FORMAT = [
+		flash.display3D.Context3DVertexBufferFormat.BYTES_4,
+		flash.display3D.Context3DVertexBufferFormat.FLOAT_1,
+		flash.display3D.Context3DVertexBufferFormat.FLOAT_2,
+		flash.display3D.Context3DVertexBufferFormat.FLOAT_3,
+		flash.display3D.Context3DVertexBufferFormat.FLOAT_4,
+	];
+	
+	static var WRAP = [
+		flash.display3D.Context3DWrapMode.CLAMP,
+		flash.display3D.Context3DWrapMode.REPEAT,
+	];
+	
+	static var FILTER = [
+		flash.display3D.Context3DTextureFilter.NEAREST,
+		flash.display3D.Context3DTextureFilter.LINEAR,
+	];
+	
+	static var MIP = [
+		flash.display3D.Context3DMipFilter.MIPNONE,
+		flash.display3D.Context3DMipFilter.MIPNEAREST,
+		flash.display3D.Context3DMipFilter.MIPLINEAR,
+	];
+	
+}
+#end

+ 1 - 1
h3d/mat/Material.hx

@@ -10,7 +10,7 @@ class Material {
 	public var blendSrc(default,set) : Blend;
 	public var blendDst(default,set) : Blend;
 	public var colorMask(default,set) : Int;
-	public var shader : hxsl.Shader;
+	public var shader : h3d.impl.Shader;
 	public var renderPass : Int;
 	
 	public function new(shader) {

+ 3 - 1
h3d/mat/MeshMaterial.hx

@@ -13,8 +13,9 @@ typedef ShadowMap = {
 	var texture : Texture;
 }
 
-private class MeshShader extends hxsl.Shader {
+private class MeshShader extends h3d.impl.Shader {
 	
+#if flash
 	static var SRC = {
 
 		var input : {
@@ -148,6 +149,7 @@ private class MeshShader extends hxsl.Shader {
 		}
 		
 	}
+#end
 	
 }
 

+ 5 - 2
h3d/mat/PartMaterial.hx

@@ -1,7 +1,8 @@
 package h3d.mat;
 
-private class PartShader extends hxsl.Shader {
+private class PartShader extends h3d.impl.Shader {
 
+#if flash
 	static var SRC = {
 
 		var input : {
@@ -53,7 +54,9 @@ private class PartShader extends hxsl.Shader {
 		}
 	
 	}
-	
+
+#end
+
 }
 
 class PartMaterial extends Material {

+ 0 - 18
h3d/mat/PngBytes.hx

@@ -1,18 +0,0 @@
-package h3d.mat;
-
-class PngBytes extends flash.utils.ByteArray {
-
-	public function getBitmapBytes() {
-		return decode(haxe.io.Bytes.ofData(this));
-	}
-	
-	public static function decode( b : haxe.io.Bytes ) {
-		var mem = new haxe.io.BytesInput(b);
-		var png = new format.png.Reader(mem);
-		var data = png.read();
-		var h = format.png.Tools.getHeader(data);
-		var data = format.png.Tools.extract32(data);
-		return new Bitmap(h.width, h.height, data);
-	}
-	
-}

+ 12 - 32
h3d/mat/Texture.hx

@@ -7,7 +7,7 @@ class Texture {
 
 	static var UID = 0;
 	
-	var t : flash.display3D.textures.TextureBase;
+	var t : h3d.impl.Driver.Texture;
 	var mem : h3d.impl.MemoryManager;
 	#if debug
 	var allocPos : h3d.impl.AllocPos;
@@ -76,7 +76,8 @@ class Texture {
 		mem.resizeTexture(this, width, height);
 	}
 
-	public function uploadMipMap( bmp : flash.display.BitmapData, smoothing = false, side = 0 ) {
+	/*
+	public function uploadMipMap( bmp : hxd.BitmapData, smoothing = false, side = 0 ) {
 		upload(bmp, 0, side);
 		var w = bmp.width >> 1, h = bmp.height >> 1, mip = 1;
 		var m = new flash.geom.Matrix();
@@ -94,38 +95,14 @@ class Texture {
 			h >>= 1;
 		}
 	}
+	*/
 	
-	public function uploadAtfData( bytes : haxe.io.Bytes ) {
-		if( isCubic ) {
-			var t = flash.Lib.as(t, flash.display3D.textures.CubeTexture);
-			t.uploadCompressedTextureFromByteArray(bytes.getData(), 0);
-		}
-		else {
-			var t = flash.Lib.as(t,  flash.display3D.textures.Texture);
-			t.uploadCompressedTextureFromByteArray(bytes.getData(), 0);
-		}
-	}
-
-	public function upload( bmp : flash.display.BitmapData, mipLevel = 0, side = 0 ) {
-		if( isCubic ) {
-			var t = flash.Lib.as(t, flash.display3D.textures.CubeTexture);
-			t.uploadFromBitmapData(bmp, side, mipLevel);
-		}
-		else {
-			var t = flash.Lib.as(t,  flash.display3D.textures.Texture);
-			t.uploadFromBitmapData(bmp, mipLevel);
-		}
+	public function uploadBitmap( bmp : hxd.BitmapData, mipLevel = 0, side = 0 ) {
+		mem.driver.uploadTextureBitmap(this, bmp, mipLevel, side);
 	}
 
 	public function uploadBytes( bmp : haxe.io.Bytes, mipLevel = 0, side = 0 ) {
-		if( isCubic ) {
-			var t = flash.Lib.as(t, flash.display3D.textures.CubeTexture);
-			t.uploadFromByteArray(bmp.getData(), 0, side, mipLevel);
-		}
-		else {
-			var t = flash.Lib.as(t,  flash.display3D.textures.Texture);
-			t.uploadFromByteArray(bmp.getData(), 0, mipLevel);
-		}
+		mem.driver.uploadTextureBytes(this, bmp, mipLevel, side);
 	}
 
 	public function dispose() {
@@ -133,8 +110,11 @@ class Texture {
 			mem.deleteTexture(this);
 	}
 	
-	public static function fromBitmap( bmp : flash.display.BitmapData, hasMipMap = false, ?allocPos : h3d.impl.AllocPos ) {
-		return h3d.Engine.getCurrent().mem.makeTexture(bmp,hasMipMap,allocPos);
+	public static function fromBitmap( bmp : hxd.BitmapData, ?allocPos : h3d.impl.AllocPos ) {
+		var mem = h3d.Engine.getCurrent().mem;
+		var t = mem.allocTexture(bmp.width, bmp.height, false, allocPos);
+		t.uploadBitmap(bmp);
+		return t;
 	}
 
 }

+ 13 - 14
h3d/prim/Cube.hx

@@ -14,20 +14,19 @@ class Cube extends Polygon {
 			new Point(0, y, z),
 			new Point(x, y, z),
 		];
-		var idx = [
-			0, 1, 5,
-			0, 5, 3,
-			1, 4, 7,
-			1, 7, 5,
-			3, 5, 7,
-			3, 7, 6,
-			0, 6, 2,
-			0, 3, 6,
-			2, 7, 4,
-			2, 6, 7,
-			0, 4, 1,
-			0, 2, 4,
-		];
+		var idx = new hxd.IndexBuffer();
+		idx.push(0); idx.push(1); idx.push(5);
+		idx.push(0); idx.push(5); idx.push(3);
+		idx.push(1); idx.push(4); idx.push(7);
+		idx.push(1); idx.push(7); idx.push(5);
+		idx.push(3); idx.push(5); idx.push(7);
+		idx.push(3); idx.push(7); idx.push(6);
+		idx.push(0); idx.push(6); idx.push(2);
+		idx.push(0); idx.push(3); idx.push(6);
+		idx.push(2); idx.push(7); idx.push(4);
+		idx.push(2); idx.push(6); idx.push(7);
+		idx.push(0); idx.push(4); idx.push(1);
+		idx.push(0); idx.push(2); idx.push(4);
 		super(p, idx);
 	}
 	

+ 18 - 21
h3d/prim/FBXModel.hx

@@ -87,13 +87,10 @@ class FBXModel extends MeshPrimitive {
 		var gt = geom.getGeomTranslate();
 		if( gt == null ) gt = new h3d.prim.Point();
 		
-		var idx = new flash.Vector<UInt>();
-		var midx = new Array<flash.Vector<UInt>>();
-		var pbuf = new flash.Vector<Float>(), nbuf = (norms == null ? null : new flash.Vector<Float>()), sbuf = (skin == null ? null : new flash.utils.ByteArray()), tbuf = (tuvs == null ? null : new flash.Vector<Float>());
-		var cbuf = (colors == null ? null : new flash.Vector<Float>());
-		var pout = 0, nout = 0, sout = 0, tout = 0, cout = 0;
-		
-		if( sbuf != null ) sbuf.endian = flash.utils.Endian.LITTLE_ENDIAN;
+		var idx = new hxd.IndexBuffer();
+		var midx = new Array<hxd.IndexBuffer>();
+		var pbuf = new hxd.FloatBuffer(), nbuf = (norms == null ? null : new hxd.FloatBuffer()), sbuf = (skin == null ? null : new hxd.BytesBuffer()), tbuf = (tuvs == null ? null : new hxd.FloatBuffer());
+		var cbuf = (colors == null ? null : new hxd.FloatBuffer());
 		
 		// triangulize indexes : format is  A,B,...,-X : negative values mark the end of the polygon
 		var count = 0, pos = 0, matPos = 0;
@@ -110,20 +107,20 @@ class FBXModel extends MeshPrimitive {
 					var x = verts[vidx * 3] + gt.x;
 					var y = verts[vidx * 3 + 1] + gt.y;
 					var z = verts[vidx * 3 + 2] + gt.z;
-					pbuf[pout++] = x;
-					pbuf[pout++] = y;
-					pbuf[pout++] = z;
+					pbuf.push(x);
+					pbuf.push(y);
+					pbuf.push(z);
 
 					if( nbuf != null ) {
-						nbuf[nout++] = norms[k*3];
-						nbuf[nout++] = norms[k*3 + 1];
-						nbuf[nout++] = norms[k*3 + 2];
+						nbuf.push(norms[k*3]);
+						nbuf.push(norms[k*3 + 1]);
+						nbuf.push(norms[k*3 + 2]);
 					}
 
 					if( tbuf != null ) {
 						var iuv = tuvs.index[k];
-						tbuf[tout++] = tuvs.values[iuv*2];
-						tbuf[tout++] = 1 - tuvs.values[iuv * 2 + 1];
+						tbuf.push(tuvs.values[iuv*2]);
+						tbuf.push(1 - tuvs.values[iuv * 2 + 1]);
 					}
 					
 					if( sbuf != null ) {
@@ -133,14 +130,14 @@ class FBXModel extends MeshPrimitive {
 							sbuf.writeFloat(skin.vertexWeights[p + i]);
 							idx = (skin.vertexJoints[p + i] << (8*i)) | idx;
 						}
-						sbuf.writeUnsignedInt(idx);
+						sbuf.writeInt32(idx);
 					}
 					
 					if( cbuf != null ) {
 						var icol = colors.index[k];
-						cbuf[cout++] = colors.values[icol * 4];
-						cbuf[cout++] = colors.values[icol * 4 + 1];
-						cbuf[cout++] = colors.values[icol * 4 + 2];
+						cbuf.push(colors.values[icol * 4]);
+						cbuf.push(colors.values[icol * 4 + 1]);
+						cbuf.push(colors.values[icol * 4 + 2]);
 					}
 				}
 				// polygons are actually triangle fans
@@ -154,7 +151,7 @@ class FBXModel extends MeshPrimitive {
 					var mid = mats[matPos++];
 					var idx = midx[mid];
 					if( idx == null ) {
-						idx = new flash.Vector<UInt>();
+						idx = new hxd.IndexBuffer();
 						midx[mid] = idx;
 					}
 					for( n in 0...count - 2 ) {
@@ -175,7 +172,7 @@ class FBXModel extends MeshPrimitive {
 		if( sbuf != null ) {
 			var nverts = Std.int(sbuf.length / ((skin.bonesPerVertex + 1) * 4));
 			var skinBuf = engine.mem.alloc(nverts, skin.bonesPerVertex + 1, 0);
-			skinBuf.upload(sbuf, 0, nverts);
+			skinBuf.uploadBytes(sbuf.getBytes(), 0, nverts);
 			addBuffer("weights", skinBuf, 0);
 			addBuffer("indexes", skinBuf, skin.bonesPerVertex);
 		}

+ 22 - 23
h3d/prim/GeoSphere.hx

@@ -5,20 +5,19 @@ class GeoSphere extends Polygon {
 	public function new( subdiv = 2 ) {
 		var a = 1 / Math.sqrt(2);
 		var p = [new Point(0, 0, 1), new Point(0, 0, -1), new Point(-a, -a, 0), new Point(a, -a, 0), new Point(a, a, 0), new Point( -a, a, 0)];
-		var idx = [
-			0, 3, 4,
-			0, 4, 5,
-			0, 5, 2,
-			0, 2, 3,
-			1, 4, 3,
-			1, 5, 4,
-			1, 2, 5,
-			1, 3, 2,
-		];
+		var idx = new hxd.IndexBuffer();
+		idx.push(0); idx.push(3); idx.push(4);
+		idx.push(0); idx.push(4); idx.push(5);
+		idx.push(0); idx.push(5); idx.push(2);
+		idx.push(0); idx.push(2); idx.push(3);
+		idx.push(1); idx.push(4); idx.push(3);
+		idx.push(1); idx.push(5); idx.push(4);
+		idx.push(1); idx.push(2); idx.push(5);
+		idx.push(1); idx.push(3); idx.push(2);
 		for( k in 0...subdiv ) {
 			var i = 0;
 			var count = idx.length, np = p.length;
-			var nidx = [], k = 0;
+			var nidx = new hxd.IndexBuffer();
 			while( i < count ) {
 				var p1 = p[idx[i]], p2 = p[idx[i + 1]], p3 = p[idx[i + 2]];
 				var pa = p1.add(p2);
@@ -28,21 +27,21 @@ class GeoSphere extends Polygon {
 				pb.normalize();
 				pc.normalize();
 				
-				nidx[k++] = np;
-				nidx[k++] = np + 1;
-				nidx[k++] = np + 2;
+				nidx.push(np);
+				nidx.push(np + 1);
+				nidx.push(np + 2);
 				
-				nidx[k++] = idx[i];
-				nidx[k++] = np;
-				nidx[k++] = np + 2;
+				nidx.push(idx[i]);
+				nidx.push(np);
+				nidx.push(np + 2);
 
-				nidx[k++] = np;
-				nidx[k++] = idx[i + 1];
-				nidx[k++] = np + 1;
+				nidx.push(np);
+				nidx.push(idx[i + 1]);
+				nidx.push(np + 1);
 				
-				nidx[k++] = np + 1;
-				nidx[k++] = idx[i + 2];
-				nidx[k++] = np + 2;
+				nidx.push(np + 1);
+				nidx.push(idx[i + 2]);
+				nidx.push(np + 2);
 				
 				p[np++] = pa;
 				p[np++] = pb;

+ 2 - 2
h3d/prim/MeshPrimitive.hx

@@ -24,12 +24,12 @@ class MeshPrimitive extends Primitive {
 		bufferCache = null;
 	}
 
-	@:access(h3d.Engine.curShader)
+	@:access(h3d.Engine.driver)
 	function getBuffers( engine : h3d.Engine ) {
 		if( bufferCache == null )
 			bufferCache = new Map();
 		var buffers = [];
-		for( name in engine.curShader.bufferNames ) {
+		for( name in engine.driver.getShaderInputNames() ) {
 			var b = bufferCache.get(name);
 			if( b == null ) {
 				b = allocBuffer(engine, name);

+ 1 - 1
h3d/prim/Plan2D.hx

@@ -6,7 +6,7 @@ class Plan2D extends Primitive {
 	}
 	
 	override function alloc( engine : h3d.Engine ) {
-		var v = new flash.Vector<Float>();
+		var v = new hxd.FloatBuffer();
 		v.push( -1);
 		v.push( -1);
 		v.push( 0);

+ 1 - 1
h3d/prim/Plan3D.hx

@@ -33,7 +33,7 @@ class Plan3D extends Primitive {
 	}
 
 	override function alloc( engine : h3d.Engine ) {
-		var v = new flash.Vector<Float>();
+		var v = new hxd.FloatBuffer();
 		var hw = width * 0.5, hh = height * 0.5;
 		v.push( -hw);
 		v.push( -hh);

+ 23 - 26
h3d/prim/Polygon.hx

@@ -5,7 +5,7 @@ class Polygon extends Primitive {
 	public var points : Array<Point>;
 	public var normals : Array<Point>;
 	public var tcoords : Array<UV>;
-	public var idx : Array<Int>;
+	public var idx : hxd.IndexBuffer;
 	public var colors : Array<Point>;
 		
 	public function new( points, ?idx ) {
@@ -24,37 +24,34 @@ class Polygon extends Primitive {
 		if( colors != null )
 			size += 3;
 			
-		var buf = new flash.Vector<Float>();
-		var i = 0;
+		var buf = new hxd.FloatBuffer();
 		for( k in 0...points.length ) {
 			var p = points[k];
-			buf[i++] = p.x;
-			buf[i++] = p.y;
-			buf[i++] = p.z;
+			buf.push(p.x);
+			buf.push(p.y);
+			buf.push(p.z);
 			if( tcoords != null ) {
 				var t = tcoords[k];
-				buf[i++] = t.u;
-				buf[i++] = t.v;
+				buf.push(t.u);
+				buf.push(t.v);
 			}
 			if( normals != null ) {
 				var n = normals[k];
-				buf[i++] = n.x;
-				buf[i++] = n.y;
-				buf[i++] = n.z;
+				buf.push(n.x);
+				buf.push(n.y);
+				buf.push(n.z);
 			}
 			if( colors != null ) {
 				var c = colors[k];
-				buf[i++] = c.x;
-				buf[i++] = c.y;
-				buf[i++] = c.z;
+				buf.push(c.x);
+				buf.push(c.y);
+				buf.push(c.z);
 			}
 		}
 		buffer = engine.mem.allocVector(buf, size, idx == null ? 3 : 0);
 		
-		if( idx != null ) {
-			var idx : Array<UInt> = cast idx;
-			indexes = engine.mem.allocIndex(flash.Vector.ofArray(idx));
-		}
+		if( idx != null )
+			indexes = engine.mem.allocIndex(idx);
 	}
 
 
@@ -62,24 +59,24 @@ class Polygon extends Primitive {
 		if( idx != null && points.length != idx.length ) {
 			var p = [];
 			var used = [];
-			for( i in idx )
-				p.push(points[i].clone());
+			for( i in 0...idx.length )
+				p.push(points[idx[i]].clone());
 			if( normals != null ) {
 				var n = [];
-				for( i in idx )
-					n.push(normals[i].clone());
+				for( i in 0...idx.length )
+					n.push(normals[idx[i]].clone());
 				normals = n;
 			}
 			if( colors != null ) {
 				var n = [];
-				for( i in idx )
-					n.push(colors[i].clone());
+				for( i in 0...idx.length )
+					n.push(colors[idx[i]].clone());
 				colors = n;
 			}
 			if( tcoords != null ) {
 				var t = [];
-				for( i in idx )
-					t.push(tcoords[i].clone());
+				for( i in 0...idx.length )
+					t.push(tcoords[idx[i]].clone());
 				tcoords = t;
 			}
 			points = p;

+ 9 - 10
h3d/prim/Quads.hx

@@ -40,23 +40,22 @@ class Quads extends Primitive {
 	
 	override function alloc( engine : Engine ) {
 		dispose();
-		var v = new flash.Vector();
-		var p = 0;
+		var v = new hxd.FloatBuffer();
 		for( i in 0...pts.length ) {
 			var pt = pts[i];
-			v[p++] = pt.x;
-			v[p++] = pt.y;
-			v[p++] = pt.z;
+			v.push(pt.x);
+			v.push(pt.y);
+			v.push(pt.z);
 			if( uvs != null ) {
 				var t = uvs[i];
-				v[p++] = t.u;
-				v[p++] = t.v;
+				v.push(t.u);
+				v.push(t.v);
 			}
 			if( normals != null ) {
 				var n = normals[i];
-				v[p++] = n.x;
-				v[p++] = n.y;
-				v[p++] = n.z;
+				v.push(n.x);
+				v.push(n.y);
+				v.push(n.z);
 			}
 		}
 		var size = 3;

+ 1 - 1
h3d/prim/RawPrimitive.hx

@@ -2,7 +2,7 @@ package h3d.prim;
 
 class RawPrimitive extends Primitive {
 
-	public function new( engine : h3d.Engine, vbuf : flash.Vector<Float>, stride : Int, ?ibuf : flash.Vector<UInt> ) {
+	public function new( engine : h3d.Engine, vbuf : hxd.FloatBuffer, stride : Int, ?ibuf : hxd.IndexBuffer ) {
 		buffer = engine.mem.allocVector(vbuf, stride, ibuf == null ? 3 : 0);
 		if( ibuf != null )
 			indexes = engine.mem.allocIndex(ibuf);

+ 1 - 1
h3d/prim/Sphere.hx

@@ -9,7 +9,7 @@ class Sphere extends Polygon {
 		this.segsH = segsH;
 		this.segsW = segsW;
 		var t = 0., dt = Math.PI / segsH, dp = Math.PI * 2 / segsW;
-		var pts = [], idx = [];
+		var pts = [], idx = new hxd.IndexBuffer();
 		var dx = 1, dy = segsW + 1;
 		for( y in 0...segsH ) {
 			var p = 0.;

+ 20 - 19
h3d/scene/Image.hx

@@ -1,6 +1,7 @@
 package h3d.scene;
 
-private class ImageShader extends hxsl.Shader {
+private class ImageShader extends h3d.impl.Shader {
+	#if flash
 	static var SRC = {
 		var input : {
 			pos : Float2,
@@ -15,6 +16,7 @@ private class ImageShader extends hxsl.Shader {
 			out = tex.get(tuv);
 		}
 	}
+	#end
 }
 
 class Image extends Object {
@@ -32,31 +34,30 @@ class Image extends Object {
 	
 	@:access(h2d.Tile)
 	override function draw( ctx : RenderContext ) {
-		var tmp = new flash.Vector();
-		var pos = 0;
+		var tmp = new hxd.FloatBuffer();
 		var dx = absPos._41 * 2 / ctx.engine.width;
 		var dy = -absPos._42 * 2 / ctx.engine.height;
 		if( tile == null )
 			tile = new h2d.Tile(null, 0, 0, 0, 0);
-		tmp[pos++] = -1 * absPos._11 - 1 * absPos._21 + dx;
-		tmp[pos++] = 1 * absPos._12 + 1 * absPos._22 + dy;
-		tmp[pos++] = tile.u;
-		tmp[pos++] = tile.v;
+		tmp.push(-1 * absPos._11 - 1 * absPos._21 + dx);
+		tmp.push(1 * absPos._12 + 1 * absPos._22 + dy);
+		tmp.push(tile.u);
+		tmp.push(tile.v);
 
-		tmp[pos++] = 1 * absPos._11 + 1 * absPos._21 + dx;
-		tmp[pos++] = 1 * absPos._12 + 1 * absPos._22 + dy;
-		tmp[pos++] = tile.u2;
-		tmp[pos++] = tile.v;
+		tmp.push(1 * absPos._11 + 1 * absPos._21 + dx);
+		tmp.push(1 * absPos._12 + 1 * absPos._22 + dy);
+		tmp.push(tile.u2);
+		tmp.push(tile.v);
 
-		tmp[pos++] = -1 * absPos._11 - 1 * absPos._21 + dx;
-		tmp[pos++] = -1 * absPos._12 - 1 * absPos._22 + dy;
-		tmp[pos++] = tile.u;
-		tmp[pos++] = tile.v2;
+		tmp.push(-1 * absPos._11 - 1 * absPos._21 + dx);
+		tmp.push(-1 * absPos._12 - 1 * absPos._22 + dy);
+		tmp.push(tile.u);
+		tmp.push(tile.v2);
 
-		tmp[pos++] = 1 * absPos._11 - 1 * absPos._21 + dx;
-		tmp[pos++] = 1 * absPos._12 - 1 * absPos._22 + dy;
-		tmp[pos++] = tile.u2;
-		tmp[pos++] = tile.v2;
+		tmp.push(1 * absPos._11 - 1 * absPos._21 + dx);
+		tmp.push(1 * absPos._12 - 1 * absPos._22 + dy);
+		tmp.push(tile.u2);
+		tmp.push(tile.v2);
 		
 		cast(material.shader,ImageShader).tex = tile.getTexture();
 		var b = ctx.engine.mem.allocVector(tmp, 4, 4);

+ 10 - 10
h3d/scene/Particles.hx

@@ -36,7 +36,7 @@ class Particles extends Object {
 
 	var first : Particle;
 	var last : Particle;
-	var tmpBuf : flash.Vector<Float>;
+	var tmpBuf : hxd.FloatBuffer;
 
 	public function new( ?mat, ?parent ) {
 		super(parent);
@@ -90,7 +90,7 @@ class Particles extends Object {
 	override function draw( ctx : RenderContext ) {
 		if( first == null )
 			return;
-		if( tmpBuf == null ) tmpBuf = new flash.Vector();
+		if( tmpBuf == null ) tmpBuf = new hxd.FloatBuffer();
 		var pos = 0;
 		var p = first;
 		var tmp = tmpBuf;
@@ -100,8 +100,8 @@ class Particles extends Object {
 			tmp[pos++] = p.x;
 			tmp[pos++] = p.y;
 			tmp[pos++] = p.z;
-			tmp[pos++] = 0;
-			tmp[pos++] = 0;
+			tmp[pos++] = 0.;
+			tmp[pos++] = 0.;
 			tmp[pos++] = p.alpha;
 			if( hasFrame ) {
 				curFrame = p.frame / frameCount;
@@ -112,8 +112,8 @@ class Particles extends Object {
 			tmp[pos++] = p.x;
 			tmp[pos++] = p.y;
 			tmp[pos++] = p.z;
-			tmp[pos++] = 0;
-			tmp[pos++] = 1;
+			tmp[pos++] = 0.;
+			tmp[pos++] = 1.;
 			tmp[pos++] = p.alpha;
 			if( hasFrame ) tmp[pos++] = curFrame;
 			if( hasRotation ) tmp[pos++] = p.rotation;
@@ -121,8 +121,8 @@ class Particles extends Object {
 			tmp[pos++] = p.x;
 			tmp[pos++] = p.y;
 			tmp[pos++] = p.z;
-			tmp[pos++] = 1;
-			tmp[pos++] = 0;
+			tmp[pos++] = 1.;
+			tmp[pos++] = 0.;
 			tmp[pos++] = p.alpha;
 			if( hasFrame ) tmp[pos++] = curFrame;
 			if( hasRotation ) tmp[pos++] = p.rotation;
@@ -130,8 +130,8 @@ class Particles extends Object {
 			tmp[pos++] = p.x;
 			tmp[pos++] = p.y;
 			tmp[pos++] = p.z;
-			tmp[pos++] = 1;
-			tmp[pos++] = 1;
+			tmp[pos++] = 1.;
+			tmp[pos++] = 1.;
 			tmp[pos++] = p.alpha;
 			if( hasFrame ) tmp[pos++] = curFrame;
 			if( hasRotation ) tmp[pos++] = p.rotation;

+ 1 - 1
h3d/scene/RenderContext.hx

@@ -11,7 +11,7 @@ class RenderContext {
 	
 	public function new() {
 		time = 0.;
-		elapsedTime = 1. / flash.Lib.current.stage.frameRate;
+		elapsedTime = 1. / hxd.Stage.getInstance().getFrameRate();
 	}
 	
 	public function addPass(p) {

+ 65 - 0
hxd/BitmapData.hx

@@ -0,0 +1,65 @@
+package hxd;
+
+private typedef InnerData = #if flash flash.display.BitmapData #elseif js js.html.ImageData #else Int #end;
+
+abstract BitmapData(InnerData) {
+
+	public var width(get, never) : Int;
+	public var height(get, never) : Int;
+	
+	public inline function new(width:Int, height:Int) {
+		#if flash
+		this = new flash.display.BitmapData(width, height, true, 0);
+		#else
+		throw "TODO";
+		#end
+	}
+	
+	public inline function clear( color : Int ) {
+		#if flash
+		this.fillRect(this.rect, color);
+		#else
+		throw "TODO";
+		#end
+	}
+	
+	public inline function dispose() {
+		#if flash
+		this.dispose();
+		#end
+	}
+	
+	public inline function getPixel( x : Int, y : Int ) {
+		#if flash
+		return this.getPixel32(x, y);
+		#else
+		throw "TODO";
+		return 0;
+		#end
+	}
+
+	public inline function setPixel( x : Int, y : Int, c : Int ) {
+		#if flash
+		this.setPixel32(x, y, c);
+		#else
+		throw "TODO";
+		#end
+	}
+	
+	inline function get_width() {
+		return this.width;
+	}
+
+	inline function get_height() {
+		return this.height;
+	}
+
+	public inline function toNative() : InnerData {
+		return this;
+	}
+	
+	public static inline function fromNative( bmp : InnerData ) : BitmapData {
+		return cast bmp;
+	}
+	
+}

+ 47 - 0
hxd/BytesBuffer.hx

@@ -0,0 +1,47 @@
+package hxd;
+
+private typedef InnerData = #if flash flash.utils.ByteArray #else haxe.io.BytesOutput #end
+
+abstract BytesBuffer(InnerData) {
+	
+	public var length(get, never) : Int;
+	
+	public inline function new() {
+		#if flash
+		this = new flash.utils.ByteArray();
+		this.endian = flash.utils.Endian.LITTLE_ENDIAN;
+		#else
+		this = new haxe.io.BytesOutput();
+		#end
+	}
+	
+	public inline function writeFloat( v : Float ) {
+		this.writeFloat(v);
+	}
+	
+	public inline function writeInt32( v : Int ) {
+		#if flash
+		this.writeUnsignedInt(v);
+		#else
+		this.writeInt32(v);
+		#end
+	}
+	
+	public inline function getBytes() : haxe.io.Bytes {
+		#if flash
+		return haxe.io.Bytes.ofData(this);
+		#else
+		return this.getBytes();
+		#end
+	}
+	
+	inline function get_length() {
+		#if flash
+		return this.length;
+		#else
+		return this.length;
+		#end
+	}
+
+}
+		

+ 1 - 1
h2d/Event.hx → hxd/Event.hx

@@ -1,4 +1,4 @@
-package h2d;
+package hxd;
 
 enum EventKind {
 	EPush;

+ 70 - 0
hxd/FloatBuffer.hx

@@ -0,0 +1,70 @@
+package hxd;
+
+private typedef InnerData = #if flash flash.Vector<Float> #else Array<Float> #end
+
+private class InnerIterator {
+	var b : InnerData;
+	var len : Int;
+	var pos : Int;
+	public inline function new( b : InnerData )  {
+		this.b = b;
+		this.len = b.length;
+		this.pos = 0;
+	}
+	public inline function hasNext() {
+		return pos < len;
+	}
+	public inline function next() {
+		return b[pos++];
+	}
+}
+
+abstract FloatBuffer(InnerData) {
+
+	public var length(get, never) : Int;
+		
+	public inline function new(length = 0) {
+		#if js
+		this = untyped __new__(Array, length);
+		#else
+		this = new InnerData(length);
+		#end
+	}
+	
+	public inline function push( v : Float ) {
+		#if flash
+		this[this.length] = v;
+		#else
+		this.push(v);
+		#end
+	}
+	
+	public inline function grow( v : Int ) {
+		#if flash
+		if( v > this.length ) this.length = v;
+		#else
+		while( this.length < v ) this.push(0.);
+		#end
+	}
+	
+	@:arrayAccess inline function arrayRead(key:Int) : Float {
+		return this[key];
+	}
+
+	@:arrayAccess inline function arrayWrite(key:Int, value : Float) : Float {
+		return this[key] = value;
+	}
+	
+	public inline function getNative() : InnerData {
+		return this;
+	}
+	
+	public inline function iterator() {
+		return new InnerIterator(this);
+	}
+	
+	inline function get_length() : Int {
+		return this.length;
+	}
+	
+}

+ 58 - 0
hxd/IndexBuffer.hx

@@ -0,0 +1,58 @@
+package hxd;
+
+private typedef InnerData = #if flash flash.Vector<UInt> #else Array<Int> #end
+
+private class InnerIterator {
+	var b : InnerData;
+	var len : Int;
+	var pos : Int;
+	public inline function new( b : InnerData )  {
+		this.b = b;
+		this.len = b.length;
+		this.pos = 0;
+	}
+	public inline function hasNext() {
+		return pos < len;
+	}
+	public inline function next() {
+		return b[pos++];
+	}
+}
+
+abstract IndexBuffer(InnerData) {
+	
+	public var length(get, never) : Int;
+	
+	public inline function new(length=0) {
+		this = new InnerData(length);
+	}
+	
+	public inline function push( v : Int ) {
+		#if flash
+		this[this.length] = v;
+		#else
+		this.push(v);
+		#end
+	}
+
+	@:arrayAccess inline function arrayRead(key:Int) : Int {
+		return this[key];
+	}
+
+	@:arrayAccess inline function arrayWrite(key:Int, value : Int) : Int {
+		return this[key] = value;
+	}
+	
+	public inline function getNative() : InnerData {
+		return this;
+	}
+
+	public inline function iterator() {
+		return new InnerIterator(this);
+	}
+
+	inline function get_length() : Int {
+		return this.length;
+	}
+	
+}

+ 176 - 0
hxd/Stage.hx

@@ -0,0 +1,176 @@
+package hxd;
+
+class Stage {
+	
+	#if flash
+	var stage : flash.display.Stage;
+	var resizeEvents : List<Void -> Void>;
+	var fsDelayed : Bool;
+	#end
+	var eventTargets : List<Event -> Void>;
+	
+	public var width(get, null) : Float;
+	public var height(get, null) : Float;
+	public var mouseX(get, null) : Float;
+	public var mouseY(get, null) : Float;
+	
+	function new() {
+		eventTargets = new List();
+		#if flash
+		stage = flash.Lib.current.stage;
+		stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
+		stage.addEventListener(flash.events.Event.RESIZE, onResize);
+		resizeEvents = new List();
+		if( hxd.System.isTouch ) {
+			flash.ui.Multitouch.inputMode = flash.ui.MultitouchInputMode.TOUCH_POINT;
+			stage.addEventListener(flash.events.TouchEvent.TOUCH_BEGIN, onTouchDown);
+			stage.addEventListener(flash.events.TouchEvent.TOUCH_MOVE, onTouchMove);
+			stage.addEventListener(flash.events.TouchEvent.TOUCH_END, onTouchUp);
+		} else {
+			stage.addEventListener(flash.events.MouseEvent.MOUSE_DOWN, onMouseDown);
+			stage.addEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
+			stage.addEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
+			stage.addEventListener(flash.events.MouseEvent.MOUSE_WHEEL, onMouseWheel);
+			stage.addEventListener(flash.events.KeyboardEvent.KEY_DOWN, onKeyDown);
+			stage.addEventListener(flash.events.KeyboardEvent.KEY_UP, onKeyUp);
+		}
+		#end
+	}
+	
+	public function event( e : hxd.Event ) {
+		for( et in eventTargets )
+			et(e);
+	}
+	
+	public function addEventTarget(et) {
+		eventTargets.add(et);
+	}
+
+	public function removeEventTarget(et) {
+		eventTargets.remove(et);
+	}
+	
+	public function addResizeEvent( f : Void -> Void ) {
+		#if flash
+		resizeEvents.push(f);
+		#else
+		throw "TODO";
+		#end
+	}
+
+	public function removeResizeEvent( f : Void -> Void ) {
+		#if flash
+		resizeEvents.push(f);
+		#else
+		throw "TODO";
+		#end
+	}
+	
+	public function getFrameRate() : Float {
+		#if flash
+		return stage.frameRate;
+		#else
+		return 60.;
+		#end
+	}
+
+	public function setFullScreen( v : Bool ) {
+		#if flash
+		var isAir = flash.system.Capabilities.playerType == "Desktop";
+		var state = v ? (isAir ? flash.display.StageDisplayState.FULL_SCREEN_INTERACTIVE : flash.display.StageDisplayState.FULL_SCREEN) : flash.display.StageDisplayState.NORMAL;
+		if( stage.displayState != state ) {
+			var t = flash.Lib.getTimer();
+			// delay first fullsrceen toggle on OSX/Air to prevent the command window to spawn over
+			if( v && isAir && t < 5000 && !fsDelayed && flash.system.Capabilities.os.indexOf("Mac") != -1 ) {
+				fsDelayed = true;
+				haxe.Timer.delay(function() this.setFullScreen(v), 1000);
+				return;
+			}
+			stage.displayState = state;
+		}
+		#else
+		#end
+	}
+	
+	static var inst = null;
+	public static function getInstance() {
+		if( inst == null ) inst = new Stage();
+		return inst;
+	}
+	
+#if flash
+
+	inline function get_mouseX() {
+		return stage.mouseX;
+	}
+
+	inline function get_mouseY() {
+		return stage.mouseY;
+	}
+
+	inline function get_width() {
+		return stage.stageWidth;
+	}
+
+	inline function get_height() {
+		return stage.stageHeight;
+	}
+	
+	function onResize(_) {
+		for( e in resizeEvents )
+			e();
+	}
+
+	function onMouseDown(e:Dynamic) {
+		event(new Event(EPush, mouseX, mouseY));
+	}
+
+	function onMouseUp(e:Dynamic) {
+		event(new Event(ERelease, mouseX, mouseY));
+	}
+	
+	function onMouseMove(e:Dynamic) {
+		event(new Event(EMove, mouseX, mouseY));
+	}
+	
+	function onMouseWheel(e:flash.events.MouseEvent) {
+		var ev = new Event(EWheel, mouseX, mouseY);
+		ev.wheelDelta = -e.delta / 3.0;
+		event(ev);
+	}
+	
+	function onKeyUp(e:flash.events.KeyboardEvent) {
+		var ev = new Event(EKeyUp);
+		ev.keyCode = e.keyCode;
+		ev.charCode = e.charCode;
+		event(ev);
+	}
+
+	function onKeyDown(e:flash.events.KeyboardEvent) {
+		var ev = new Event(EKeyDown);
+		ev.keyCode = e.keyCode;
+		ev.charCode = e.charCode;
+		event(ev);
+	}
+	
+	function onTouchDown(e:flash.events.TouchEvent) {
+		var ev = new Event(EPush, e.localX, e.localY);
+		ev.touchId = e.touchPointID;
+		event(ev);
+	}
+
+	function onTouchUp(e:flash.events.TouchEvent) {
+		var ev = new Event(ERelease, e.localX, e.localY);
+		ev.touchId = e.touchPointID;
+		event(ev);
+	}
+	
+	function onTouchMove(e:flash.events.TouchEvent) {
+		var ev = new Event(EMove, e.localX, e.localY);
+		ev.touchId = e.touchPointID;
+		event(ev);
+	}
+			
+#end
+
+}

+ 31 - 1
h3d/System.hx → hxd/System.hx

@@ -1,4 +1,4 @@
-package h3d;
+package hxd;
 
 enum Cursor {
 	Default;
@@ -20,6 +20,8 @@ class System {
 	
 	public static var screenDPI(get,never) : Float;
 
+	#if flash
+	
 	static function get_isWindowed() {
 		var p = flash.system.Capabilities.playerType;
 		return p == "ActiveX" || p == "PlugIn" || p == "StandAlone" || p == "Desktop";
@@ -109,7 +111,35 @@ class System {
 		return name;
 	}
 	
+	#elseif js
+
+	static var LOOP = null;
+	
+	public static function setLoop( f : Void -> Void ) {
+		var window : Dynamic = js.Browser.window;
+		if( LOOP != null  ) {
+			var caf : Dynamic = window.cancelAnimationFrame ||
+			window.webkitCancelAnimationFrame ||
+			window.mozCancelAnimationFrame;
+			caf(LOOP);
+			LOOP = null;
+		}
+		if( f == null )
+			return;
+		var rqf : Dynamic = window.requestAnimationFrame ||
+			window.webkitRequestAnimationFrame ||
+			window.mozRequestAnimationFrame;
+		rqf(f);
+	}
 
+	public static function setCursor( c : Cursor ) {
+		throw "TODO";
+	}
+	
+	
+	#else
+
+	#end
 	#end
 	
 	public static macro function getFileContent( file : String ) {

+ 12 - 8
samples/basic/Test.hx

@@ -2,15 +2,13 @@ import h3d.scene.*;
 
 class Test {
 	
-	var root : flash.display.Sprite;
 	var engine : h3d.Engine;
 	var time : Float;
 	var scene : Scene;
 	var obj1 : Mesh;
 	var obj2 : Mesh;
 	
-	function new(root) {
-		this.root = root;
+	function new() {
 		time = 0;
 		engine = new h3d.Engine();
 		engine.debug = true;
@@ -20,15 +18,19 @@ class Test {
 	}
 	
 	function start() {
-		root.addEventListener(flash.events.Event.ENTER_FRAME, update);
+		hxd.System.setLoop(update);
 		
 		var prim = new h3d.prim.Cube();
 		prim.translate( -0.5, -0.5, -0.5);
 		prim.addUVs();
 		prim.addNormals();
 		
-		var bmp = new flash.display.BitmapData(256, 256);
-		bmp.perlinNoise(64, 64, 3, 0, true, true, 7);
+		var bmp : hxd.BitmapData = null;
+		#if flash
+		var tbmp = new flash.display.BitmapData(256, 256);
+		tbmp.perlinNoise(64, 64, 3, 0, true, true, 7);
+		bmp = hxd.BitmapData.fromNative(tbmp);
+		#end
 		var tex = h3d.mat.Texture.fromBitmap(bmp);
 		var mat = new h3d.mat.MeshMaterial(tex);
 		bmp.dispose();
@@ -44,7 +46,7 @@ class Test {
 		};
 	}
 	
-	function update(_) {
+	function update() {
 		var dist = 5;
 		time += 0.01;
 		scene.camera.pos.set(Math.cos(time) * dist, Math.sin(time) * dist, 3);
@@ -53,8 +55,10 @@ class Test {
 	}
 	
 	static function main() {
+		#if flash
 		haxe.Log.setColor(0xFF0000);
-		new Test(flash.Lib.current);
+		#end
+		new Test();
 	}
 	
 }

+ 2 - 2
tools/fbx/Viewer.hx

@@ -258,7 +258,7 @@ class Viewer {
 		var t = engine.mem.allocTexture(1024, 1024);
 		var bmp = new flash.display.BitmapData(1024, 1024, true, 0xFFFF0000);
 		var mat = new h3d.mat.MeshMaterial(t);
-		t.upload(bmp);
+		t.uploadBitmap(hxd.BitmapData.fromNative(bmp));
 		bmp.dispose();
 		loadTexture(textureName, mat);
 		mat.killAlpha = true;
@@ -305,7 +305,7 @@ class Viewer {
 			loader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, function(_) {
 				var bmp = flash.Lib.as(loader.content, flash.display.Bitmap).bitmapData;
 				t.resize(bmp.width, bmp.height);
-				t.upload(bmp);
+				t.uploadBitmap(hxd.BitmapData.fromNative(bmp));
 				mat.culling = None;
 			});
 			loader.load(new flash.net.URLRequest(textureName));

+ 6 - 6
tools/parts/Main.hx

@@ -27,7 +27,7 @@ class RangeSlider extends h2d.comp.Slider {
 		super(parent);
 		range = 0.;
 		this.cursor.customStyle = new h2d.css.Style();
-		input.onWheel = function(e:h2d.Event) {
+		input.onWheel = function(e:hxd.Event) {
 			range += e.wheelDelta * 0.01;
 			if( range < 0 ) range = 0;
 			onChange(value);
@@ -101,7 +101,7 @@ class Main {
 	}
 	
 	function init() {
-		h3d.System.setLoop(update);
+		hxd.System.setLoop(update);
 		s3d = new h3d.scene.Scene();
 		s2d = new h2d.Scene();
 		parts = [];
@@ -122,7 +122,7 @@ class Main {
 		};
 		var p = new h2d.comp.Parser( { props : props } );
 		p.register("range", function(x:haxe.xml.Fast, parent) return new RangeSlider(parent));
-		ui = p.build(new haxe.xml.Fast(Xml.parse(h3d.System.getFileContent("ui.html")).firstElement()));
+		ui = p.build(new haxe.xml.Fast(Xml.parse(hxd.System.getFileContent("ui.html")).firstElement()));
 		engine.onResized = function() ui.setStyle(null);
 		s2d.addChild(ui);
 		s3d.addPass(s2d);
@@ -131,10 +131,10 @@ class Main {
 		emit = new h3d.scene.Particles(s3d);
 		emit.hasRotation = true;
 		emit.hasSize = true;
-		setTexture(new DefaultPart(0, 0));
+		setTexture(hxd.BitmapData.fromNative(new DefaultPart(0, 0)));
 	}
 	
-	function setTexture( t : flash.display.BitmapData ) {
+	function setTexture( t : hxd.BitmapData ) {
 		if( emit.material.texture != null )
 			emit.material.texture.dispose();
 		emit.material.texture = h3d.mat.Texture.fromBitmap(t);
@@ -187,7 +187,7 @@ class Main {
 			emit.material.blend(SrcAlpha, OneMinusSrcAlpha);
 		if( addMode != props.add && props.tex == null ) {
 			addMode = props.add;
-			setTexture(addMode ? new DefaultPart(0, 0) : new DefaultPartAlpha(0, 0));
+			setTexture(hxd.BitmapData.fromNative(addMode ? new DefaultPart(0, 0) : new DefaultPartAlpha(0, 0)));
 		}
 		engine.render(s3d);
 		s2d.checkEvents();