diff --git a/buildfiles/html5/haxe/ApplicationMain.hx b/buildfiles/html5/haxe/ApplicationMain.hx index 546bb9604..232f2ec2e 100755 --- a/buildfiles/html5/haxe/ApplicationMain.hx +++ b/buildfiles/html5/haxe/ApplicationMain.hx @@ -1,204 +1,31 @@ -#if (!lime && !flambe) +#if lime_html5 + + import ::APP_MAIN_PACKAGE::::APP_MAIN_CLASS::; + import lime.LiME; + + class ApplicationMain { + + public static function main () { -import ::APP_MAIN_PACKAGE::::APP_MAIN_CLASS::; -import nme.display.Bitmap; -import nme.display.Loader; -import nme.events.Event; -import nme.media.Sound; -import nme.net.URLLoader; -import nme.net.URLRequest; -import nme.net.URLLoaderDataFormat; -import nme.Assets; -import nme.Lib; - - -class ApplicationMain { - - - private static var completed:Int; - private static var preloader:NMEPreloader; - private static var total:Int; - - public static var loaders:Hash ; - public static var urlLoaders:Hash ; - - - public static function main () { - - completed = 0; - loaders = new Hash (); - urlLoaders = new Hash (); - total = 0; - - ::if (WIN_WIDTH == "0")::::if (WIN_HEIGHT == "0"):: - browser.Lib.preventDefaultTouchMove (); - ::end::::end:: - - ::if (PRELOADER_NAME!=""):: - preloader = new ::PRELOADER_NAME:: (); - ::else:: - preloader = new NMEPreloader (); - ::end:: - Lib.current.addChild (preloader); - preloader.onInit (); - - ::foreach assets:: - ::if (type=="image"):: - var loader:Loader = new Loader (); - loaders.set ("::resourceName::", loader); - total ++; - ::elseif (type == "binary"):: - var urlLoader:URLLoader = new URLLoader (); - urlLoader.dataFormat = BINARY; - urlLoaders.set ("::resourceName::", urlLoader); - total ++; - ::elseif (type == "text"):: - var urlLoader:URLLoader = new URLLoader (); - urlLoader.dataFormat = TEXT; - urlLoaders.set ("::resourceName::", urlLoader); - total ++; - ::end::::end:: - - if (total == 0) { - begin (); + //Create the game class, give it the runtime + var _main_ = Type.createInstance (::APP_MAIN::, []); + //Create an instance of lime + var _lime = new LiME(); + + //Create the config from the project.nmml info + var config = { + width : ::WIN_WIDTH::, + height : ::WIN_HEIGHT::, + title : "::APP_TITLE::" + }; + + //Start up + _lime.init( _main_, config ); - } else { - - for (path in loaders.keys ()) { - - var loader:Loader = loaders.get (path); - loader.contentLoaderInfo.addEventListener ("complete", loader_onComplete); - loader.load (new URLRequest (path)); - - } - - for (path in urlLoaders.keys ()) { - - var urlLoader:URLLoader = urlLoaders.get (path); - urlLoader.addEventListener ("complete", loader_onComplete); - urlLoader.load (new URLRequest (path)); - - } - - } - - } - - - private static function begin ():Void { - - preloader.addEventListener (Event.COMPLETE, preloader_onComplete); - preloader.onLoaded (); - - } - - - public static function getAsset(inName:String):Dynamic { - - ::foreach assets:: - if (inName=="::id::") { - ::if (type == "image"):: - return Assets.getBitmapData ("::id::"); - ::elseif (type=="sound"):: - return Assets.getSound ("::id::"); - ::elseif (type=="music"):: - return Assets.getSound ("::id::"); - ::elseif (type== "font"):: - return Assets.getFont ("::id::"); - ::elseif (type== "text"):: - return Assets.getText ("::id::"); - ::else:: - return Assets.getBytes ("::id::"); - ::end:: - } - ::end:: - return null; - - } - - - - - // Event Handlers - - - - - private static function loader_onComplete (event:Event):Void { - - completed ++; - - preloader.onUpdate (completed, total); - - if (completed == total) { - - begin (); - - } - - } - - - private static function preloader_onComplete (event:Event):Void { - - preloader.removeEventListener (Event.COMPLETE, preloader_onComplete); - - Lib.current.removeChild(preloader); - preloader = null; - - if (Reflect.field(::APP_MAIN::, "main") == null) - { - var mainDisplayObj = new ::APP_MAIN::(); - if (Std.is(mainDisplayObj, browser.display.DisplayObject)) - nme.Lib.current.addChild(cast mainDisplayObj); - } - else - { - Reflect.callMethod (::APP_MAIN::, Reflect.field (::APP_MAIN::, "main"), []); - } - - } - - -} + } //main + } //ApplicationMain -::foreach assets:: - ::if (type=="font"):: - class NME_::flatName:: extends nme.text.Font { } - ::end:: -::end:: - - -#else - - -import ::APP_MAIN_PACKAGE::::APP_MAIN_CLASS::; -import lime.LiME; - -class ApplicationMain { - - public static function main () { - - //Create the game class, give it the runtime - var _main_ = Type.createInstance (::APP_MAIN::, []); - //Create an instance of lime - var _lime = new LiME(); - - //Create the config from the project.nmml info - var config = { - width : ::WIN_WIDTH::, - height : ::WIN_HEIGHT::, - title : "::APP_TITLE::" - }; - - //Start up - _lime.init( _main_, config ); - - } //main -} //ApplicationMain - - -#end \ No newline at end of file +#end //lime_html5 diff --git a/buildfiles/html5/haxe/NMEPreloader.hx b/buildfiles/html5/haxe/NMEPreloader.hx new file mode 100644 index 000000000..e1bab587f --- /dev/null +++ b/buildfiles/html5/haxe/NMEPreloader.hx @@ -0,0 +1,113 @@ +// import flash.display.Sprite; +// import flash.events.Event; + + +class NMEPreloader // extends Sprite +{ + // private var outline:Sprite; + // private var progress:Sprite; + + public function new() + { + // super(); + + // var backgroundColor = getBackgroundColor (); + // var r = backgroundColor >> 16 & 0xFF; + // var g = backgroundColor >> 8 & 0xFF; + // var b = backgroundColor & 0xFF; + // var perceivedLuminosity = (0.299 * r + 0.587 * g + 0.114 * b); + // var color = 0x000000; + + // if (perceivedLuminosity < 70) { + + // color = 0xFFFFFF; + + // } + + // var x = 30; + // var height = 9; + // var y = getHeight () / 2 - height / 2; + // var width = getWidth () - x * 2; + + // var padding = 3; + + // outline = new Sprite (); + // outline.graphics.lineStyle (1, color, 0.15, true); + // outline.graphics.drawRoundRect (0, 0, width, height, padding * 2, padding * 2); + // outline.x = x; + // outline.y = y; + // addChild (outline); + + // progress = new Sprite (); + // progress.graphics.beginFill (color, 0.35); + // progress.graphics.drawRect (0, 0, width - padding * 2, height - padding * 2); + // progress.x = x + padding; + // progress.y = y + padding; + // progress.scaleX = 0; + // addChild (progress); + } + + + public function getBackgroundColor():Int + { + return ::WIN_BACKGROUND::; + } + + + public function getHeight():Float + { + var height = ::WIN_HEIGHT::; + + if (height > 0) { + + return height; + + } else { + + return 640;// flash.Lib.current.stage.stageHeight; + + } + } + + + public function getWidth():Float + { + var width = ::WIN_WIDTH::; + + if (width > 0) { + + return width; + + } else { + + return 960;// todo flash.Lib.current.stage.stageWidth; + + } + } + + + public function onInit() + { + + } + + + public function onLoaded() { + // dispatchEvent (new Event (Event.COMPLETE)); + } + + + public function onUpdate(bytesLoaded:Int, bytesTotal:Int) { + + var percentLoaded = bytesLoaded / bytesTotal; + + if (percentLoaded > 1) + { + percentLoaded == 1; + } + + progress.scaleX = percentLoaded; + } + + +} \ No newline at end of file diff --git a/buildfiles/html5/template/index.html b/buildfiles/html5/template/index.html index 1ad943b34..03f4da944 100755 --- a/buildfiles/html5/template/index.html +++ b/buildfiles/html5/template/index.html @@ -3,6 +3,17 @@ ::APP_TITLE:: + + @@ -24,7 +35,7 @@ ::end:: ::if DEBUG::::end:: - + diff --git a/examples/SimpleOpenGL/src/Main.hx b/examples/SimpleOpenGL/src/Main.hx index d1b5e347f..35729598b 100644 --- a/examples/SimpleOpenGL/src/Main.hx +++ b/examples/SimpleOpenGL/src/Main.hx @@ -54,6 +54,30 @@ class Main { } + //Called by lime + public function onmousemove(_event:Dynamic) { + // trace(_event); + } + + //Called by lime + public function onkeydown(_event:Dynamic) { + trace(_event); + } + + //Called by lime + public function onkeyup(_event:Dynamic) { + // trace(_event); + } + + //Called by lime + public function onmousedown(_event:Dynamic) { + // trace(_event); + } + //Called by lime + public function onmouseup(_event:Dynamic) { + // trace(_event); + } + //Called by lime public function render() { diff --git a/lime/InputHandler.hx b/lime/InputHandler.hx index cc94cce9b..1a781274f 100644 --- a/lime/InputHandler.hx +++ b/lime/InputHandler.hx @@ -9,6 +9,36 @@ class InputHandler { public function startup() { lib._debug(':: lime :: \t InputHandler Initialized.'); + + #if lime_html5 + //on html5 we need to listen for events on the canvas + //lib.window_handle = canvas element + lib.window_handle.addEventListener('contextmenu', function(e){ + e.preventDefault(); + }); + + lib.window_handle.addEventListener('mousedown', function(e){ + e.preventDefault(); + lime_mousedown(e); + }); + lib.window_handle.addEventListener('mousemove', function(e){ + e.preventDefault(); + lime_mousemove(e); + }); + lib.window_handle.addEventListener('mouseup', function(e){ + e.preventDefault(); + lime_mouseup(e); + }); + + js.Browser.document.addEventListener('keydown', function(e){ + e.value = e.which+32; + lime_onkeydown(e); + }); + js.Browser.document.addEventListener('keyup', function(e){ + e.value = e.which+32; + lime_onkeyup(e); + }); + #end //lime_html5 } public function shutdown() { @@ -21,52 +51,84 @@ class InputHandler { //Keyboard - public function core_onchar(_event:Dynamic) { + public function lime_onchar(_event:Dynamic) { + if(lib.host.onchar != null) { + lib.host.onchar(_event); + } + + lime_onkeydown(_event); //if (onKey != null) { // untyped onKey(_event.code, _event.down, _event.char, _event.flags); //} } - public function core_onkeydown(_event:Dynamic) { + public function lime_onkeydown(_event:Dynamic) { + if(lib.host.onkeydown != null) { + lib.host.onkeydown(_event); + } //nmeOnKey(_event, KeyboardEvent.KEY_DOWN); } - public function core_onkeyup(_event:Dynamic) { + public function lime_onkeyup(_event:Dynamic) { + if(lib.host.onkeyup != null) { + lib.host.onkeyup(_event); + } //nmeOnKey(_event, KeyboardEvent.KEY_UP); } - public function core_gotinputfocus(_event:Dynamic) { + public function lime_gotinputfocus(_event:Dynamic) { + if(lib.host.ongotinputfocus != null) { + lib.host.ongotinputfocus(_event); + } //var evt = new Event(FocusEvent.FOCUS_IN); //nmeDispatchEvent(evt); } - public function core_lostinputfocus(_event:Dynamic) { + public function lime_lostinputfocus(_event:Dynamic) { + if(lib.host.onlostinputfocus != null) { + lib.host.onlostinputfocus(_event); + } //var evt = new Event(FocusEvent.FOCUS_OUT); //nmeDispatchEvent(evt); } //Mouse - public function core_mousemove(_event:Dynamic) { + public function lime_mousemove(_event:Dynamic) { + if(lib.host.onmousemove != null) { + lib.host.onmousemove(_event); + } //nmeOnMouse(_event, MouseEvent.MOUSE_MOVE, true); } - public function core_mousedown(_event:Dynamic) { + public function lime_mousedown(_event:Dynamic) { + if(lib.host.onmousedown != null) { + lib.host.onmousedown(_event); + } //nmeOnMouse(_event, MouseEvent.MOUSE_DOWN, true); } - public function core_mouseclick(_event:Dynamic) { + public function lime_mouseclick(_event:Dynamic) { + if(lib.host.onmouseclick != null) { + lib.host.onmouseclick(_event); + } //nmeOnMouse(_event, MouseEvent.CLICK, true); } - public function core_mouseup(_event:Dynamic) { + public function lime_mouseup(_event:Dynamic) { + if(lib.host.onmouseup != null) { + lib.host.onmouseup(_event); + } //nmeOnMouse(_event, MouseEvent.MOUSE_UP, true); } //Touch - public function core_touchbegin(_event:Dynamic) { + public function lime_touchbegin(_event:Dynamic) { + if(lib.host.ontouchbegin != null) { + lib.host.ontouchbegin(_event); + } //var touchInfo = new TouchInfo(); //nmeTouchInfo.set(_event.value, touchInfo); //nmeOnTouch(_event, TouchEvent.TOUCH_BEGIN, touchInfo); @@ -75,12 +137,18 @@ class InputHandler { // nmeOnMouse(_event, MouseEvent.MOUSE_DOWN, false); } - public function core_touchmove(_event:Dynamic) { + public function lime_touchmove(_event:Dynamic) { + if(lib.host.ontouchmove != null) { + lib.host.ontouchmove(_event); + } //var touchInfo = nmeTouchInfo.get(_event.value); //nmeOnTouch(_event, TouchEvent.TOUCH_MOVE, touchInfo); } - public function core_touchend(_event:Dynamic) { + public function lime_touchend(_event:Dynamic) { + if(lib.host.ontouchend != null) { + lib.host.ontouchend(_event); + } //var touchInfo = nmeTouchInfo.get(_event.value); //nmeOnTouch(_event, TouchEvent.TOUCH_END, touchInfo); //nmeTouchInfo.remove(_event.value); @@ -89,29 +157,47 @@ class InputHandler { // nmeOnMouse(_event, MouseEvent.MOUSE_UP, false); } - public function core_touchtap(_event:Dynamic) { + public function lime_touchtap(_event:Dynamic) { + if(lib.host.ontouchtap != null) { + lib.host.ontouchtap(_event); + } //nmeOnTouchTap(_event.TouchEvent.TOUCH_TAP); } //Joystick - public function core_joyaxismove(_event:Dynamic) { + public function lime_joyaxismove(_event:Dynamic) { + if(lib.host.onjoyaxismove != null) { + lib.host.onjoyaxismove(_event); + } //nmeOnJoystick(_event, JoystickEvent.AXIS_MOVE); } - public function core_joyballmove(_event:Dynamic) { + public function lime_joyballmove(_event:Dynamic) { + if(lib.host.onjoyballmove != null) { + lib.host.onjoyballmove(_event); + } //nmeOnJoystick(_event, JoystickEvent.BALL_MOVE); } - public function core_joyhatmove(_event:Dynamic) { + public function lime_joyhatmove(_event:Dynamic) { + if(lib.host.onjoyhatmove != null) { + lib.host.onjoyhatmove(_event); + } //nmeOnJoystick(_event, JoystickEvent.HAT_MOVE); } - public function core_joybuttondown(_event:Dynamic) { + public function lime_joybuttondown(_event:Dynamic) { + if(lib.host.onjoybuttondown != null) { + lib.host.onjoybuttondown(_event); + } //nmeOnJoystick(_event, JoystickEvent.BUTTON_DOWN); } - public function core_joybuttonup(_event:Dynamic) { + public function lime_joybuttonup(_event:Dynamic) { + if(lib.host.onjoybuttonup != null) { + lib.host.onjoybuttonup(_event); + } //nmeOnJoystick(_event, JoystickEvent.BUTTON_UP); } diff --git a/lime/LiME.hx b/lime/LiME.hx index 31d88eacd..5ad5ed2e6 100644 --- a/lime/LiME.hx +++ b/lime/LiME.hx @@ -122,7 +122,9 @@ class LiME { var event_type:Int = Std.int(Reflect.field(_event, "type")); - _debug('event_from_stage : ' + event_type, true, true); + if(event_type != SystemEvents.poll) { + _debug('event_from_stage : ' + event_type, true, true); + } switch(event_type) { @@ -136,64 +138,63 @@ class LiME { //keyboard case SystemEvents.char: - input.core_onchar(_event); + input.lime_onchar(_event); case SystemEvents.keydown: - input.core_onkeydown(_event); + input.lime_onkeydown(_event); case SystemEvents.keyup: - input.core_onkeyup(_event); + input.lime_onkeyup(_event); case SystemEvents.gotinputfocus: - input.core_gotinputfocus(_event); + input.lime_gotinputfocus(_event); case SystemEvents.lostinputfocus: - input.core_lostinputfocus(_event); + input.lime_lostinputfocus(_event); //mouse case SystemEvents.mousemove: - input.core_mousemove(_event); + input.lime_mousemove(_event); case SystemEvents.mousedown: - input.core_mousedown(_event); - + input.lime_mousedown(_event); case SystemEvents.mouseclick: - input.core_mouseclick(_event); + input.lime_mouseclick(_event); case SystemEvents.mouseup: - input.core_mouseup(_event); + input.lime_mouseup(_event); //touch case SystemEvents.touchbegin: - input.core_touchbegin(_event); + input.lime_touchbegin(_event); case SystemEvents.touchmove: - input.core_touchmove(_event); + input.lime_touchmove(_event); case SystemEvents.touchend: - input.core_touchend(_event); + input.lime_touchend(_event); case SystemEvents.touchtap: - input.core_touchtap(_event); + input.lime_touchtap(_event); //joystick case SystemEvents.joyaxismove: - input.core_joyaxismove(_event); + input.lime_joyaxismove(_event); case SystemEvents.joyballmove: - input.core_joyballmove(_event); + input.lime_joyballmove(_event); case SystemEvents.joyhatmove: - input.core_joyhatmove(_event); + input.lime_joyhatmove(_event); case SystemEvents.joybuttondown: - input.core_joybuttondown(_event); + input.lime_joybuttondown(_event); case SystemEvents.joybuttonup: - input.core_joybuttonup(_event); + input.lime_joybuttonup(_event); //Window diff --git a/lime/WindowHandler.hx b/lime/WindowHandler.hx index c04c1074e..d948fe1f7 100644 --- a/lime/WindowHandler.hx +++ b/lime/WindowHandler.hx @@ -25,9 +25,9 @@ class WindowHandler { lib.config.height, //height Window.RESIZABLE | Window.HARDWARE | - Window.VSYNC | + // Window.VSYNC | Window.HW_AA | - Window.HW_AA_HIRES | + // Window.HW_AA_HIRES | Window.ALLOW_SHADERS | Window.REQUIRE_SHADERS | Window.DEPTH_BUFFER | diff --git a/lime/geometry/Matrix3D.hx b/lime/geometry/Matrix3D.hx index faaa9a69b..c464927cd 100644 --- a/lime/geometry/Matrix3D.hx +++ b/lime/geometry/Matrix3D.hx @@ -291,10 +291,10 @@ class Matrix3D return invertable; } - - /*public function pointAt(pos:Vector3D, ?at:Vector3D, ?up:Vector3D):Void { - if (at == null) at = new Vector3D(0,0,-1); - if (up == null) up = new Vector3D(0,-1,0); +/* + public function pointAt(pos:phoenix.Vector, ?at:phoenix.Vector, ?up:phoenix.Vector):Matrix3D { + if (at == null) at = new phoenix.Vector(0,0,-1); + if (up == null) up = new phoenix.Vector(0,-1,0); //pos.x*=-1; //pos.y*=-1; @@ -305,28 +305,28 @@ class Matrix3D //up.x*=-1; //up.y*=-1; //up.z*=-1; - var dir:Vector3D = at.subtract(pos); - var vup:Vector3D = up.clone(); - var right:Vector3D; + var dir:phoenix.Vector = at.subtract(pos); + var vup:phoenix.Vector = up.clone(); + var right:phoenix.Vector; - dir.normalize(); - vup.normalize(); + dir.normalized; + vup.normalized; var dir2 = dir.clone(); - dir2.scaleBy(vup.dotProduct(dir)); + dir2.multiply_(vup.dot(dir)); vup = vup.subtract(dir2); if (vup.length > 0) { - vup.normalize(); + vup.normalized; } else { - vup = dir.x != 0 ? new Vector3D(-dir.y,dir.x,0) : new Vector3D(1,0,0); + vup = dir.x != 0 ? new phoenix.Vector(-dir.y,dir.x,0) : new phoenix.Vector(1,0,0); } - right = vup.crossProduct(dir); - right.normalize(); + right = phoenix.Vector.Cross(vup, dir); + right.normalized; rawData[0] = right.x; rawData[4] = right.y; @@ -344,8 +344,10 @@ class Matrix3D rawData[7] = pos.y; rawData[11] = pos.z; rawData[15] = 1.0; - }*/ + return this; + } +*/ inline public function prepend(rhs:Matrix3D):Void { var m111:Float = rhs.rawData[0], m121:Float = rhs.rawData[4], m131:Float = rhs.rawData[8], m141:Float = rhs.rawData[12], diff --git a/lime/utils/Assets.hx b/lime/utils/Assets.hx index 8424fdbac..74f508a3a 100644 --- a/lime/utils/Assets.hx +++ b/lime/utils/Assets.hx @@ -347,18 +347,29 @@ class Assets { * @return A new String object */ public static function getText(id:String):String { - - var bytes = getBytes(id); - - if (bytes == null) { - return null; - - } else { + #if lime_native + var bytes = getBytes(id); + if (bytes == null) { + return null; + } else { + return bytes.readUTFBytes(bytes.length); + } + #end //lime_native - return bytes.readUTFBytes(bytes.length); - - } + #if lime_html5 + + var req = new haxe.Http(id); + var results : Dynamic; + + req.async = false; + req.onData = function(e) { results = e; } + req.request(); + req = null; + + return results; + + #end //lime_html5 } diff --git a/lime/utils/ByteArray.hx b/lime/utils/ByteArray.hx index ccf6a4946..c536ca4c4 100644 --- a/lime/utils/ByteArray.hx +++ b/lime/utils/ByteArray.hx @@ -1,634 +1,9 @@ package lime.utils; -// #if (cpp || neko) -#if (lime_native || lime_html5) -import lime.utils.Libs; +#if lime_native + typedef ByteArray = lime.utils.native.ByteArray; +#end //lime_native -import haxe.io.Bytes; -import haxe.io.BytesData; -// import nme.errors.EOFError; // Ensure that the neko->haxe callbacks are initialized -import lime.utils.CompressionAlgorithm; -import lime.utils.IDataInput; - -#if !lime_html5 - - #if neko - import neko.Lib; - import neko.zip.Compress; - import neko.zip.Uncompress; - import neko.zip.Flush; - #else - import cpp.Lib; - import cpp.zip.Compress; - import cpp.zip.Uncompress; - import cpp.zip.Flush; - #end - -#end - -class ByteArray extends Bytes #if !haxe3 , #end implements ArrayAccess #if !haxe3 , #end implements IDataInput #if !haxe3 , #end implements IMemoryRange -{ - - public var bigEndian:Bool; - public var bytesAvailable(get_bytesAvailable, null):Int; - public var endian(get_endian, set_endian):String; - public var position:Int; - public var byteLength(get_byteLength,null):Int; - - #if neko - /** @private */ private var alloced:Int; - #end - - public function new(inSize = 0) - { - bigEndian = true; - position = 0; - - if (inSize >= 0) - { - #if neko - alloced = inSize < 16 ? 16 : inSize; - var bytes = untyped __dollar__smake(alloced); - super(inSize, bytes); - #else - var data = new BytesData(); - if (inSize > 0) - untyped data[inSize - 1] = 0; - super(inSize, data); - #end - } - } - - @:keep - inline public function __get(pos:Int):Int - { - // Neko/cpp pseudo array accessors... - // No bounds checking is done in the cpp case - #if cpp - return untyped b[pos]; - #else - return get(pos); - #end - } - - #if !no_nme_io - /** @private */ static function __init__() { - var factory = function(inLen:Int) { return new ByteArray(inLen); }; - var resize = function(inArray:ByteArray, inLen:Int) - { - if (inLen > 0) - inArray.ensureElem(inLen - 1, true); - inArray.length = inLen; - - }; - - var bytes = function(inArray:ByteArray) { return inArray==null ? null : inArray.b; } - var slen = function(inArray:ByteArray) { return inArray == null ? 0 : inArray.length; } - - #if !lime_html5 - var init = Libs.load("nme", "nme_byte_array_init", 4); - init(factory, slen, resize, bytes); - #end //lime_html5 - } - #end - - @:keep - inline public function __set(pos:Int, v:Int):Void - { - // No bounds checking is done in the cpp case - #if cpp - untyped b[pos] = v; - #else - set(pos, v); - #end - } - - public function asString():String - { - return readUTFBytes(length); - } - - public function checkData(inLength:Int) - { - if (inLength + position > length) - ThrowEOFi(); - } - - public function clear() - { - position = 0; - length = 0; - } - -#if !lime_html5 -//todo- sven - - public function compress(algorithm:CompressionAlgorithm = null) - { - #if neko - var src = alloced == length ? this : sub(0, length); - #else - var src = this; - #end - - var result:Bytes; - - if (algorithm == CompressionAlgorithm.LZMA) - { - result = Bytes.ofData(nme_lzma_encode( cast src.getData()) ); - - } else - { - var windowBits = switch(algorithm) - { - case DEFLATE: -15; - case GZIP: 31; - default: 15; - } - - #if enable_deflate - result = Compress.run(src, 8, windowBits); - #else - result = Compress.run(src, 8); - #end - } - - b = result.b; - length = result.length; - position = length; - #if neko - alloced = length; - #end - } - - public function deflate() - { - compress(CompressionAlgorithm.DEFLATE); - } - -#end //!lime_html5 - - /** @private */ private function ensureElem(inSize:Int, inUpdateLenght:Bool) { - var len = inSize + 1; - - #if neko - if (alloced < len) - { - alloced =((len+1) * 3) >> 1; - var new_b = untyped __dollar__smake(alloced); - untyped __dollar__sblit(new_b, 0, b, 0, length); - b = new_b; - } - #else - if (b.length < len) - untyped b.__SetSize(len); - #end - - if (inUpdateLenght && length < len) - length = len; - } - - static public function fromBytes(inBytes:Bytes) - { - var result = new ByteArray( -1); - result.nmeFromBytes(inBytes); - return result; - } - - public function getLength():Int { return length; } - - // IMemoryRange - public function getByteBuffer():ByteArray { return this; } - public function getStart():Int { return 0; } - -#if !lime_html5 - - public function inflate() { - - uncompress(CompressionAlgorithm.DEFLATE); - - } - -#end //!lime_html5 - - private inline function nmeFromBytes(inBytes:Bytes):Void - { - b = inBytes.b; - length = inBytes.length; - - #if neko - alloced = length; - #end - } - - public inline function readBoolean():Bool - { - return(position < length) ? __get(position++) != 0 : ThrowEOFi() != 0; - } - - public inline function readByte():Int - { - var val:Int = readUnsignedByte(); - return((val & 0x80) != 0) ?(val - 0x100) : val; - } - - public function readBytes(outData:ByteArray, inOffset:Int = 0, inLen:Int = 0):Void - { - if (inLen == 0) - inLen = length - position; - - if (position + inLen > length) - ThrowEOFi(); - - if (outData.length < inOffset + inLen) - outData.ensureElem(inOffset + inLen - 1, true); - - #if neko - outData.blit(inOffset, this, position, inLen); - #else - var b1 = b; - var b2 = outData.b; - var p = position; - for(i in 0...inLen) - b2[inOffset + i] = b1[p + i]; - #end - - position += inLen; - } - - public function readDouble():Float - { - #if !lime_html5 - - if (position + 8 > length) - ThrowEOFi(); - - #if neko - var bytes = new Bytes(8, untyped __dollar__ssub(b, position, 8)); - #elseif cpp - var bytes = new Bytes(8, b.slice(position, position + 8)); - #end - - position += 8; - return _double_of_bytes(bytes.b, bigEndian); - - #end //!lime_html5 - - return 0.0; - } - - #if !no_nme_io - static public function readFile(inString:String):ByteArray - { - return nme_byte_array_read_file(inString); - } - #end - - public function readFloat():Float - { - #if !lime_html5 - - if (position + 4 > length) - ThrowEOFi(); - - #if neko - var bytes = new Bytes(4, untyped __dollar__ssub(b, position, 4)); - #elseif cpp - var bytes = new Bytes(4, b.slice(position, position + 4)); - #end - - position += 4; - return _float_of_bytes(bytes.b, bigEndian); - - #end //!lime_html5 - - return 0.0; - } - - public function readInt():Int - { - var ch1 = readUnsignedByte(); - var ch2 = readUnsignedByte(); - var ch3 = readUnsignedByte(); - var ch4 = readUnsignedByte(); - - return bigEndian ?(ch1 << 24) |(ch2 << 16) |(ch3 << 8) | ch4 :(ch4 << 24) |(ch3 << 16) |(ch2 << 8) | ch1; - } - - public inline function readMultiByte(inLen:Int, charSet:String):String - { - // TODO - use code page - return readUTFBytes(inLen); - } - - public function readShort():Int - { - var ch1 = readUnsignedByte(); - var ch2 = readUnsignedByte(); - - var val = bigEndian ?((ch1 << 8) | ch2) :((ch2 << 8) | ch1); - - return((val & 0x8000) != 0) ?(val - 0x10000) : val; - } - - inline public function readUnsignedByte():Int - { - return(position < length) ? __get(position++) : ThrowEOFi(); - } - - public function readUnsignedInt():Int - { - var ch1 = readUnsignedByte(); - var ch2 = readUnsignedByte(); - var ch3 = readUnsignedByte(); - var ch4 = readUnsignedByte(); - - return bigEndian ?(ch1 << 24) |(ch2 << 16) |(ch3 << 8) | ch4 :(ch4 << 24) |(ch3 << 16) |(ch2 << 8) | ch1; - } - - public function readUnsignedShort():Int - { - var ch1 = readUnsignedByte(); - var ch2 = readUnsignedByte(); - - return bigEndian ?(ch1 << 8) | ch2 :(ch2 << 8) + ch1; - } - - public function readUTF():String - { - var len = readUnsignedShort(); - return readUTFBytes(len); - } - - public function readUTFBytes(inLen:Int):String - { - if (position + inLen > length) - ThrowEOFi(); - - var p = position; - position += inLen; - - #if lime_native - - #if neko - return new String(untyped __dollar__ssub(b, p, inLen)); - #elseif cpp - var result:String=""; - untyped __global__.__hxcpp_string_of_bytes(b, result, p, inLen); - return result; - #end - - #else - return "-"; - #end - - } - - public function setLength(inLength:Int):Void - { - if (inLength > 0) - ensureElem(inLength - 1, false); - length = inLength; - } - - // ArrayBuffer interface - public function slice(inBegin:Int, ?inEnd:Int):ByteArray - { - var begin = inBegin; - - if (begin < 0) - { - begin += length; - if (begin < 0) - begin = 0; - } - - var end:Int = inEnd == null ? length : inEnd; - - if (end < 0) - { - end += length; - - if (end < 0) - end = 0; - } - - if (begin >= end) - return new ByteArray(); - - var result = new ByteArray(end - begin); - - var opos = position; - result.blit(0, this, begin, end - begin); - - return result; - } - - /** @private */ private function ThrowEOFi():Int { - throw "new EOFError();"; //todo sven - return 0; - } - -#if !lime_html5 -//todo sven - - public function uncompress(algorithm:CompressionAlgorithm = null):Void - { - if (algorithm == null) algorithm = CompressionAlgorithm.GZIP; - - #if neko - var src = alloced == length ? this : sub(0, length); - #else - var src = this; - #end - - var result:Bytes; - - if (algorithm == CompressionAlgorithm.LZMA) - { - result = Bytes.ofData(nme_lzma_decode(src.getData())); - - } else - { - var windowBits = switch(algorithm) - { - case DEFLATE: -15; - case GZIP: 31; - default: 15; - } - - #if enable_deflate - result = Uncompress.run(src, null, windowBits); - #else - result = Uncompress.run(src, null); - #end - } - - b = result.b; - length = result.length; - position = 0; - #if neko - alloced = length; - #end - } - -#end //!lime_html5 - - /** @private */ inline function write_uncheck(inByte:Int) { - #if cpp - untyped b.__unsafe_set(position++, inByte); - #else - untyped __dollar__sset(b, position++, inByte & 0xff); - #end - } - - public function writeBoolean(value:Bool) - { - writeByte(value ? 1 : 0); - } - - inline public function writeByte(value:Int) - { - ensureElem(position, true); - - #if cpp - b[position++] = untyped value; - #else - untyped __dollar__sset(b, position++, value & 0xff); - #end - } - - public function writeBytes(bytes:Bytes, inOffset:Int = 0, inLength:Int = 0) - { - if (inLength == 0) inLength = bytes.length - inOffset; - ensureElem(position + inLength - 1, true); - var opos = position; - position += inLength; - blit(opos, bytes, inOffset, inLength); - } - - public function writeDouble(x:Float) - { - #if !lime_html5 - - #if neko - var bytes = new Bytes(8, _double_bytes(x, bigEndian)); - #elseif cpp - var bytes = Bytes.ofData(_double_bytes(x, bigEndian)); - #end - - writeBytes(bytes); - - #end //!lime_html5 - } - - #if !no_nme_io - public function writeFile(inString:String):Void - { - nme_byte_array_overwrite_file(inString, this); - } - #end - - public function writeFloat(x:Float) - { - #if !lime_html5 - - #if neko - var bytes = new Bytes(4, _float_bytes(x, bigEndian)); - #elseif cpp - var bytes = Bytes.ofData(_float_bytes(x, bigEndian)); - #end - - writeBytes(bytes); - - #end //!lime_html5 - } - - public function writeInt(value:Int) - { - ensureElem(position + 3, true); - - if (bigEndian) - { - write_uncheck(value >> 24); - write_uncheck(value >> 16); - write_uncheck(value >> 8); - write_uncheck(value); - - } else - { - write_uncheck(value); - write_uncheck(value >> 8); - write_uncheck(value >> 16); - write_uncheck(value >> 24); - } - } - - // public function writeMultiByte(value:String, charSet:String) - // public function writeObject(object:*) - public function writeShort(value:Int) - { - ensureElem(position + 1, true); - - if (bigEndian) - { - write_uncheck(value >> 8); - write_uncheck(value); - - } else - { - write_uncheck(value); - write_uncheck(value >> 8); - } - } - - public function writeUnsignedInt(value:Int) - { - writeInt(value); - } - - public function writeUTF(s:String) - { - #if neko - var bytes = new Bytes(s.length, untyped s.__s); - #else - var bytes = Bytes.ofString(s); - #end - - writeShort(bytes.length); - writeBytes(bytes); - } - - public function writeUTFBytes(s:String) - { - #if neko - var bytes = new Bytes(s.length, untyped s.__s); - #else - var bytes = Bytes.ofString(s); - #end - - writeBytes(bytes); - } - - // Getters & Setters - private function get_bytesAvailable():Int { return length - position; } - private function get_byteLength():Int { return length; } - private function get_endian():String { return bigEndian ? Endian.BIG_ENDIAN : Endian.LITTLE_ENDIAN; } - private function set_endian(s:String):String { bigEndian =(s == Endian.BIG_ENDIAN); return s; } - - // Native Methods - /** @private */ private static var _double_bytes = Libs.load("std", "double_bytes", 2); - /** @private */ private static var _double_of_bytes = Libs.load("std", "double_of_bytes", 2); - /** @private */ private static var _float_bytes = Libs.load("std", "float_bytes", 2); - /** @private */ private static var _float_of_bytes = Libs.load("std", "float_of_bytes", 2); - #if !no_nme_io - private static var nme_byte_array_overwrite_file = Libs.load("nme","nme_byte_array_overwrite_file", 2); - private static var nme_byte_array_read_file = Libs.load("nme", "nme_byte_array_read_file", 1); - #end - private static var nme_lzma_encode = Libs.load("nme", "nme_lzma_encode", 1); - private static var nme_lzma_decode = Libs.load("nme", "nme_lzma_decode", 1); -} - -#else -typedef ByteArray = flash.utils.ByteArray; -#end +#if lime_html5 + typedef ByteArray = lime.utils.html5.ByteArray; +#end //lime_html5 diff --git a/lime/utils/URLLoader.hx b/lime/utils/URLLoader.hx new file mode 100644 index 000000000..447d9378b --- /dev/null +++ b/lime/utils/URLLoader.hx @@ -0,0 +1,320 @@ +package lime.utils; +#if js + + +// import flash.events.Event; +// import flash.events.EventDispatcher; +import flash.events.HTTPStatusEvent; +import flash.events.IOErrorEvent; +import flash.events.ProgressEvent; +// import flash.errors.IOError; +// import flash.events.SecurityErrorEvent; + +import flash.utils.ByteArray; +import js.html.EventTarget; +import js.html.XMLHttpRequest; +import js.Browser; +import js.Lib; + + +class URLLoader extends EventDispatcher { + + public var bytesLoaded:Int; + public var bytesTotal:Int; + public var data:Dynamic; + public var dataFormat(default, set):URLLoaderDataFormat; + private function set_dataFormat(inputVal:URLLoaderDataFormat):URLLoaderDataFormat { + // prevent inadvertently using typed arrays when they are unsupported + // @todo move these sorts of tests somewhere common in the vein of Modernizr + if (inputVal == URLLoaderDataFormat.BINARY + && !Reflect.hasField(Browser.window, "ArrayBuffer")) { + dataFormat = URLLoaderDataFormat.TEXT; + } else { + dataFormat = inputVal; + } + return dataFormat; + } + + + public function new(request:URLRequest = null) { + + super(); + + bytesLoaded = 0; + bytesTotal = 0; + dataFormat = URLLoaderDataFormat.TEXT; + + if (request != null) { + + load(request); + + } + + } + + + public function close():Void { + + + + } + + + private dynamic function getData():Dynamic { + + return null; + + } + + + public function load(request:URLRequest):Void { + + requestUrl(request.url, request.method, request.data, request.formatRequestHeaders()); + + } + + + private function registerEvents(subject:EventTarget):Void { + + var self = this; + if (untyped __js__("typeof XMLHttpRequestProgressEvent") != __js__('"undefined"')) { + + subject.addEventListener("progress", onProgress, false); + + } + + untyped subject.onreadystatechange = function() { + + if (subject.readyState != 4) return; + + var s = try subject.status catch( e : Dynamic ) null; + + if (s == untyped __js__("undefined")) { + + s = null; + + } + + if (s != null) { + + self.onStatus(s); + + } + + //js.Lib.alert (s); + + if (s != null && s >= 200 && s < 400) { + + self.onData(subject.response); + + } else { + + if (s == null) { + + self.onError("Failed to connect or resolve host"); + + } else if (s == 12029) { + + self.onError("Failed to connect to host"); + + } else if (s == 12007) { + + self.onError("Unknown host"); + + } else if (s == 0) { + + self.onError("Unable to make request (may be blocked due to cross-domain permissions)"); + self.onSecurityError("Unable to make request (may be blocked due to cross-domain permissions)"); + + } else { + + self.onError("Http Error #" + subject.status); + + } + + } + + }; + + } + + + private function requestUrl(url:String, method:String, data:Dynamic, requestHeaders:Array):Void { + + var xmlHttpRequest:XMLHttpRequest = untyped __new__("XMLHttpRequest"); + registerEvents(cast xmlHttpRequest); + var uri:Dynamic = ""; + + if (Std.is(data, ByteArray)) { + + var data:ByteArray = cast data; + + switch (dataFormat) { + + case BINARY: uri = data.nmeGetBuffer(); + default: uri = data.readUTFBytes(data.length); + + } + + } else if (Std.is(data, URLVariables)) { + + var data:URLVariables = cast data; + + for (p in Reflect.fields(data)) { + + if (uri.length != 0) uri += "&"; + uri += StringTools.urlEncode(p) + "=" + StringTools.urlEncode(Reflect.field(data, p)); + + } + + } else { + + if (data != null) { + + uri = data.toString(); + + } + + } + + try { + + if (method == "GET" && uri != null && uri != "") { + + var question = url.split("?").length <= 1; + xmlHttpRequest.open(method, url + (if (question) "?" else "&") + uri, true); + uri = ""; + + } else { + + //js.Lib.alert ("open: " + method + ", " + url + ", true"); + xmlHttpRequest.open(method, url, true); + + } + + } catch(e:Dynamic) { + + onError(e.toString()); + return; + + } + + //js.Lib.alert ("dataFormat: " + dataFormat); + + switch (dataFormat) { + + case BINARY: untyped xmlHttpRequest.responseType = 'arraybuffer'; + default: + + } + + for (header in requestHeaders) { + + //js.Lib.alert ("setRequestHeader: " + header.name + ", " + header.value); + xmlHttpRequest.setRequestHeader(header.name, header.value); + + } + + //js.Lib.alert ("uri: " + uri); + + xmlHttpRequest.send(uri); + onOpen(); + + getData = function() { + + if (xmlHttpRequest.response != null) { + + return xmlHttpRequest.response; + + } else { + + return xmlHttpRequest.responseText; + + } + + }; + + } + + + + + // Event Handlers + + + + + private function onData(_):Void { + + var content:Dynamic = getData(); + + switch (dataFormat) { + + case BINARY: this.data = ByteArray.nmeOfBuffer(content); + default: this.data = Std.string(content); + + } + + var evt = new Event(Event.COMPLETE); + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onError(msg:String):Void { + + var evt = new IOErrorEvent(IOErrorEvent.IO_ERROR); + evt.text = msg; + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onOpen():Void { + + var evt = new Event(Event.OPEN); + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onProgress(event:XMLHttpRequestProgressEvent):Void { + + var evt = new ProgressEvent(ProgressEvent.PROGRESS); + evt.currentTarget = this; + evt.bytesLoaded = event.loaded; + evt.bytesTotal = event.total; + dispatchEvent(evt); + + } + + + private function onSecurityError(msg:String):Void { + + var evt = new SecurityErrorEvent(SecurityErrorEvent.SECURITY_ERROR); + evt.text = msg; + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onStatus(status:Int):Void { + + var evt = new HTTPStatusEvent(HTTPStatusEvent.HTTP_STATUS, false, false, status); + evt.currentTarget = this; + dispatchEvent(evt); + + } + + +} + + +typedef XMLHttpRequestProgressEvent = Dynamic; + + +#end \ No newline at end of file diff --git a/lime/utils/html5/ByteArray.hx b/lime/utils/html5/ByteArray.hx new file mode 100644 index 000000000..4079b6933 --- /dev/null +++ b/lime/utils/html5/ByteArray.hx @@ -0,0 +1,516 @@ +package lime.utils.html5; +#if js + + +// import flash.errors.IOError; +// import flash.utils.UInt; +import haxe.io.Bytes; +import haxe.io.BytesBuffer; +import haxe.io.BytesData; +import haxe.io.Input; +import js.html.DataView; +import js.html.Uint8Array; + +#if format +import format.tools.Inflate; +#end + + +@:autoBuild(openfl.Assets.embedFile()) +class ByteArray implements ArrayAccess { + + + public var bytesAvailable(get_bytesAvailable, null):Int; + public var endian(get_endian, set_endian):String; + public var length(default, set_length):Int = 0; + public var objectEncoding:Int; + public var position:Int = 0; + + private var allocated:Int = 0; + public var byteView:Uint8Array; + private var data:DataView; + // NOTE: default ByteArray endian is BIG_ENDIAN + private var littleEndian:Bool = false; + + + public function new():Void { + + _nmeResizeBuffer(allocated); + //this.byteView = untyped __new__("Uint8Array", allocated); + //this.data = untyped __new__("DataView", this.byteView.buffer); + + } + + + public function __get(pos:Int):Int { return data.getUint8(pos); } + public function __set(pos:Int, v:Int):Void { data.setUint8(pos, v); } + + + private function _getUTFBytesCount(value:String):Int { + + var count:Int = 0; + // utf8-decode + + for (i in 0...value.length) { + + var c = StringTools.fastCodeAt(value, i); + + if (c <= 0x7F) { + + count += 1; + + } else if (c <= 0x7FF) { + + count += 2; + + } else if (c <= 0xFFFF) { + + count += 3; + + } else { + + count += 4; + + } + + } + + return count; + + } + + + private function _nmeResizeBuffer(len:Int):Void { + + var oldByteView:Uint8Array = this.byteView; + var newByteView:Uint8Array = untyped __new__("Uint8Array", len); + + if (oldByteView != null) + { + if (oldByteView.length <= len) newByteView.set(oldByteView); + else newByteView.set(oldByteView.subarray(0, len)); + } + + this.byteView = newByteView; + this.data = untyped __new__("DataView", newByteView.buffer); + + } + + + public function clear() { + + length = 0; + + } + + + @:extern private inline function ensureWrite(lengthToEnsure:Int):Void { + + if (this.length < lengthToEnsure) this.length = lengthToEnsure; + } + + + static public function fromBytes(inBytes:Bytes) + { + var result = new ByteArray(); + result.nmeFromBytes(inBytes); + return result; + } + + public function getData() { + return data.buffer; + } + + private inline function nmeFromBytes(inBytes:Bytes):Void + { + byteView = untyped __new__("Uint8Array", inBytes.getData()); + length = byteView.length; + allocated = length; + } + + + public inline function nmeGet(pos:Int):Int { + + var data:Dynamic = data; + return data.getUint8(pos); + + } + + + public inline function nmeGetBuffer() { + + return data.buffer; + + } + + + public static function nmeOfBuffer(buffer:ArrayBuffer):ByteArray { + + var bytes = new ByteArray(); + bytes.length = bytes.allocated ;//= buffer.byteLength; todo + bytes.data = untyped __new__("DataView", buffer); + bytes.byteView = untyped __new__("Uint8Array", buffer); + return bytes; + + } + + + public inline function nmeSet(pos:Int, v:Int):Void { + + var data:Dynamic = data; + data.setUint8(pos, v); + + } + + + public inline function readBoolean():Bool { + + return (this.readByte() != 0); + + } + + + public inline function readByte():Int { + + var data:Dynamic = data; + return data.getUint8(this.position++); + + } + + + public function readBytes(bytes:ByteArray, ?offset:Int, ?length:Int):Void { + + if (offset < 0 || length < 0) { + throw ("Read error - Out of bounds"); + } + + if (offset == null) offset = 0; + if (length == null) length = this.length; + + bytes.ensureWrite(offset + length); + + bytes.byteView.set(byteView.subarray(this.position, this.position + length), offset); + bytes.position = offset; + + this.position += length; + if (bytes.position + length > bytes.length) bytes.length = bytes.position + length; + + } + + + public function readDouble():Float { + + var double = data.getFloat64(this.position, littleEndian); + this.position += 8; + return double; + + } + + + public function readFloat():Float { + + var float = data.getFloat32(this.position, littleEndian); + this.position += 4; + return float; + + } + + + private function readFullBytes(bytes:Bytes, pos:Int, len:Int):Void { + + // NOTE: It is used somewhere? + + ensureWrite(len); + + for (i in pos...(pos + len)) { + + var data:Dynamic = data; + data.setInt8(this.position++, bytes.get(i)); + + } + + } + + + public function readInt():Int { + + var int = data.getInt32(this.position, littleEndian); + this.position += 4; + return int; + + } + + + public function readShort():Int { + + var short = data.getInt16(this.position, littleEndian); + this.position += 2; + return short; + + } + + + public inline function readUnsignedByte():Int { + + var data:Dynamic = data; + return data.getUint8(this.position++); + + } + + + public function readUnsignedInt():Int { + + var uInt = data.getUint32(this.position, littleEndian); + this.position += 4; + return uInt; + + } + + + public function readUnsignedShort():Int { + + var uShort = data.getUint16(this.position, littleEndian); + this.position += 2; + return uShort; + + } + + + public function readUTF():String { + + var bytesCount = readUnsignedShort(); + return readUTFBytes(bytesCount); + + } + + + public function readUTFBytes(len:Int):String { + + var value = ""; + var max = this.position + len; + + // utf8-encode + while (this.position < max) { + + var data:Dynamic = data; + var c = data.getUint8(this.position++); + + if (c < 0x80) { + + if (c == 0) break; + value += String.fromCharCode(c); + + } else if (c < 0xE0) { + + value += String.fromCharCode(((c & 0x3F) << 6) |(data.getUint8(this.position++) & 0x7F)); + + } else if (c < 0xF0) { + + var c2 = data.getUint8(this.position++); + value += String.fromCharCode(((c & 0x1F) << 12) |((c2 & 0x7F) << 6) |(data.getUint8(this.position++) & 0x7F)); + + } else { + + var c2 = data.getUint8(this.position++); + var c3 = data.getUint8(this.position++); + value += String.fromCharCode(((c & 0x0F) << 18) |((c2 & 0x7F) << 12) |((c3 << 6) & 0x7F) |(data.getUint8(this.position++) & 0x7F)); + + } + + } + + return value; + + } + + + public function toString ():String { + + var cachePosition = position; + position = 0; + var value = readUTFBytes (length); + position = cachePosition; + return value; + + } + + + #if format + public function uncompress():Void { + + var bytes = Bytes.ofData(cast byteView); + var buf = Inflate.run(bytes).getData(); + this.byteView = untyped __new__("Uint8Array", buf); + this.data = untyped __new__("DataView", byteView.buffer); + this.length = this.allocated = byteView.buffer.byteLength; + + } + #end + + + public inline function writeBoolean(value:Bool):Void { + + this.writeByte(value ? 1 : 0); + + } + + + public function writeByte(value:Int):Void { + + ensureWrite(this.position + 1); + var data:Dynamic = data; + data.setInt8(this.position, value); + this.position += 1; + + } + + + public function writeBytes(bytes:ByteArray, ?offset:Int, ?length:Int):Void { + + if (offset < 0 || length < 0) throw ("Write error - Out of bounds"); + + ensureWrite(this.position + length); + byteView.set(bytes.byteView.subarray(offset, offset + length), this.position); + this.position += length; + + } + + + public function writeDouble(x:Float):Void { + + ensureWrite(this.position + 8); + data.setFloat64(this.position, x, littleEndian); + this.position += 8; + + } + + + public function writeFloat(x:Float):Void { + + ensureWrite(this.position + 4); + data.setFloat32(this.position, x, littleEndian); + this.position += 4; + + } + + + public function writeInt(value:Int):Void { + + ensureWrite(this.position + 4); + data.setInt32(this.position, value, littleEndian); + this.position += 4; + + } + + + public function writeShort(value:Int):Void { + + ensureWrite(this.position + 2); + data.setInt16(this.position, value, littleEndian); + this.position += 2; + + } + + + public function writeUnsignedInt(value:Int):Void { + + ensureWrite(this.position + 4); + data.setUint32(this.position, value, littleEndian); + this.position += 4; + + } + + + public function writeUnsignedShort(value:Int):Void { + + ensureWrite(this.position + 2); + data.setUint16(this.position, value, littleEndian); + this.position += 2; + + } + + + public function writeUTF(value:String):Void { + + writeUnsignedShort(_getUTFBytesCount(value)); + writeUTFBytes(value); + + } + + + public function writeUTFBytes(value:String):Void { + + // utf8-decode + for (i in 0...value.length) { + + var c = StringTools.fastCodeAt(value, i); + + if (c <= 0x7F) { + + writeByte(c); + + } else if (c <= 0x7FF) { + + writeByte(0xC0 |(c >> 6)); + writeByte(0x80 |(c & 63)); + + } else if (c <= 0xFFFF) { + + writeByte(0xE0 |(c >> 12)); + writeByte(0x80 |((c >> 6) & 63)); + writeByte(0x80 |(c & 63)); + + } else { + + writeByte(0xF0 |(c >> 18)); + writeByte(0x80 |((c >> 12) & 63)); + writeByte(0x80 |((c >> 6) & 63)); + writeByte(0x80 |(c & 63)); + + } + + } + + } + + + + + // Getters & Setters + + + + + inline private function get_bytesAvailable():Int { return length - position; } + + + inline function get_endian():String { + + return littleEndian ? Endian.LITTLE_ENDIAN : Endian.BIG_ENDIAN; + + } + + + inline function set_endian(endian:String):String { + + littleEndian = (endian == Endian.LITTLE_ENDIAN); + return endian; + + } + + + private inline function set_length(value:Int):Int { + + if (allocated < value) + _nmeResizeBuffer(allocated = Std.int(Math.max(value, allocated * 2))); + else if (allocated > value) + _nmeResizeBuffer(allocated = value); + length = value; + return value; + } + + +} + + +#end diff --git a/lime/utils/html5/URLLoader.hx b/lime/utils/html5/URLLoader.hx new file mode 100644 index 000000000..bf3b14f6a --- /dev/null +++ b/lime/utils/html5/URLLoader.hx @@ -0,0 +1,324 @@ +package lime.utils.html5; +#if js + + +// import flash.events.Event; +// import flash.events.EventDispatcher; +import lime.utils.html5.HTTPStatusEvent; +// import flash.events.IOErrorEvent; +import lime.utils.html5.ProgressEvent; +// import flash.errors.IOError; +// import flash.events.SecurityErrorEvent; + +import flash.utils.ByteArray; +import js.html.EventTarget; +import js.html.XMLHttpRequest; +import js.Browser; +import js.Lib; + + +class URLLoader { //extends EventDispatcher { + + + public var bytesLoaded:Int; + public var bytesTotal:Int; + public var data:Dynamic; + public var dataFormat(default, set):Dynamic; + private function set_dataFormat(inputVal:Dynamic):Dynamic { + // prevent inadvertently using typed arrays when they are unsupported + // @todo move these sorts of tests somewhere common in the vein of Modernizr + + // if (inputVal == URLLoaderDataFormat.BINARY + // && !Reflect.hasField(Browser.window, "ArrayBuffer")) { + // dataFormat = URLLoaderDataFormat.TEXT; + // } else { + // dataFormat = inputVal; + // } + + return dataFormat; + } + + + public function new(request){//:URLRequest = null) { + + super(); + + bytesLoaded = 0; + bytesTotal = 0; + dataFormat = URLLoaderDataFormat.TEXT; + + if (request != null) { + + load(request); + + } + + } + + + public function close():Void { + + + + } + + + private dynamic function getData():Dynamic { + + return null; + + } + + + public function load(request) {//:URLRequest):Void { + + requestUrl(request.url, request.method, request.data, request.formatRequestHeaders()); + + } + + + private function registerEvents(subject:EventTarget):Void { + + var self = this; + if (untyped __js__("typeof XMLHttpRequestProgressEvent") != __js__('"undefined"')) { + + subject.addEventListener("progress", onProgress, false); + + } + + untyped subject.onreadystatechange = function() { + + if (subject.readyState != 4) return; + + var s = try subject.status catch( e : Dynamic ) null; + + if (s == untyped __js__("undefined")) { + + s = null; + + } + + if (s != null) { + + self.onStatus(s); + + } + + //js.Lib.alert (s); + + if (s != null && s >= 200 && s < 400) { + + self.onData(subject.response); + + } else { + + if (s == null) { + + self.onError("Failed to connect or resolve host"); + + } else if (s == 12029) { + + self.onError("Failed to connect to host"); + + } else if (s == 12007) { + + self.onError("Unknown host"); + + } else if (s == 0) { + + self.onError("Unable to make request (may be blocked due to cross-domain permissions)"); + self.onSecurityError("Unable to make request (may be blocked due to cross-domain permissions)"); + + } else { + + self.onError("Http Error #" + subject.status); + + } + + } + + }; + + } + + + private function requestUrl(url:String, method:String, data:Dynamic, requestHeaders:Array):Void { + + var xmlHttpRequest:XMLHttpRequest = untyped __new__("XMLHttpRequest"); + registerEvents(cast xmlHttpRequest); + var uri:Dynamic = ""; + + if (Std.is(data, ByteArray)) { + + var data:ByteArray = cast data; + + switch (dataFormat) { + + case BINARY: uri = data.nmeGetBuffer(); + default: uri = data.readUTFBytes(data.length); + + } + + } else if (Std.is(data, URLVariables)) { + + var data:URLVariables = cast data; + + for (p in Reflect.fields(data)) { + + if (uri.length != 0) uri += "&"; + uri += StringTools.urlEncode(p) + "=" + StringTools.urlEncode(Reflect.field(data, p)); + + } + + } else { + + if (data != null) { + + uri = data.toString(); + + } + + } + + try { + + if (method == "GET" && uri != null && uri != "") { + + var question = url.split("?").length <= 1; + xmlHttpRequest.open(method, url + (if (question) "?" else "&") + uri, true); + uri = ""; + + } else { + + //js.Lib.alert ("open: " + method + ", " + url + ", true"); + xmlHttpRequest.open(method, url, true); + + } + + } catch(e:Dynamic) { + + onError(e.toString()); + return; + + } + + //js.Lib.alert ("dataFormat: " + dataFormat); + + switch (dataFormat) { + + case BINARY: untyped xmlHttpRequest.responseType = 'arraybuffer'; + default: + + } + + for (header in requestHeaders) { + + //js.Lib.alert ("setRequestHeader: " + header.name + ", " + header.value); + xmlHttpRequest.setRequestHeader(header.name, header.value); + + } + + //js.Lib.alert ("uri: " + uri); + + xmlHttpRequest.send(uri); + onOpen(); + + getData = function() { + + if (xmlHttpRequest.response != null) { + + return xmlHttpRequest.response; + + } else { + + return xmlHttpRequest.responseText; + + } + + }; + + } + + + + + // Event Handlers + + + + + private function onData(_):Void { + + var content:Dynamic = getData(); + + switch (dataFormat) { + + case BINARY: this.data = ByteArray.nmeOfBuffer(content); + default: this.data = Std.string(content); + + } + + var evt = new Event(Event.COMPLETE); + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onError(msg:String):Void { + + var evt = new IOErrorEvent(IOErrorEvent.IO_ERROR); + evt.text = msg; + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onOpen():Void { + + var evt = new Event(Event.OPEN); + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onProgress(event:XMLHttpRequestProgressEvent):Void { + + var evt = new ProgressEvent(ProgressEvent.PROGRESS); + evt.currentTarget = this; + evt.bytesLoaded = event.loaded; + evt.bytesTotal = event.total; + dispatchEvent(evt); + + } + + + private function onSecurityError(msg:String):Void { + + var evt = new SecurityErrorEvent(SecurityErrorEvent.SECURITY_ERROR); + evt.text = msg; + evt.currentTarget = this; + dispatchEvent(evt); + + } + + + private function onStatus(status:Int):Void { + + // todo: + // var evt = new HTTPStatusEvent(HTTPStatusEvent.HTTP_STATUS, false, false, status); + // evt.currentTarget = this; + // dispatchEvent(evt); + + } + + +} + + +typedef XMLHttpRequestProgressEvent = Dynamic; + + +#end \ No newline at end of file diff --git a/lime/utils/native/ByteArray.hx b/lime/utils/native/ByteArray.hx new file mode 100644 index 000000000..4a24b79c1 --- /dev/null +++ b/lime/utils/native/ByteArray.hx @@ -0,0 +1,634 @@ +package lime.utils.native; +// #if (cpp || neko) +#if (lime_native || lime_html5) + +import lime.utils.Libs; + +import haxe.io.Bytes; +import haxe.io.BytesData; +// import nme.errors.EOFError; // Ensure that the neko->haxe callbacks are initialized +import lime.utils.CompressionAlgorithm; +import lime.utils.IDataInput; + +#if !lime_html5 + + #if neko + import neko.Lib; + import neko.zip.Compress; + import neko.zip.Uncompress; + import neko.zip.Flush; + #else + import cpp.Lib; + import cpp.zip.Compress; + import cpp.zip.Uncompress; + import cpp.zip.Flush; + #end + +#end + +class ByteArray extends Bytes #if !haxe3 , #end implements ArrayAccess #if !haxe3 , #end implements IDataInput #if !haxe3 , #end implements IMemoryRange +{ + + public var bigEndian:Bool; + public var bytesAvailable(get_bytesAvailable, null):Int; + public var endian(get_endian, set_endian):String; + public var position:Int; + public var byteLength(get_byteLength,null):Int; + + #if neko + /** @private */ private var alloced:Int; + #end + + public function new(inSize = 0) + { + bigEndian = true; + position = 0; + + if (inSize >= 0) + { + #if neko + alloced = inSize < 16 ? 16 : inSize; + var bytes = untyped __dollar__smake(alloced); + super(inSize, bytes); + #else + var data = new BytesData(); + if (inSize > 0) + untyped data[inSize - 1] = 0; + super(inSize, data); + #end + } + } + + @:keep + inline public function __get(pos:Int):Int + { + // Neko/cpp pseudo array accessors... + // No bounds checking is done in the cpp case + #if cpp + return untyped b[pos]; + #else + return get(pos); + #end + } + + #if !no_nme_io + /** @private */ static function __init__() { + var factory = function(inLen:Int) { return new ByteArray(inLen); }; + var resize = function(inArray:ByteArray, inLen:Int) + { + if (inLen > 0) + inArray.ensureElem(inLen - 1, true); + inArray.length = inLen; + + }; + + var bytes = function(inArray:ByteArray) { return inArray==null ? null : inArray.b; } + var slen = function(inArray:ByteArray) { return inArray == null ? 0 : inArray.length; } + + #if !lime_html5 + var init = Libs.load("nme", "nme_byte_array_init", 4); + init(factory, slen, resize, bytes); + #end //lime_html5 + } + #end + + @:keep + inline public function __set(pos:Int, v:Int):Void + { + // No bounds checking is done in the cpp case + #if cpp + untyped b[pos] = v; + #else + set(pos, v); + #end + } + + public function asString():String + { + return readUTFBytes(length); + } + + public function checkData(inLength:Int) + { + if (inLength + position > length) + ThrowEOFi(); + } + + public function clear() + { + position = 0; + length = 0; + } + +#if !lime_html5 +//todo- sven + + public function compress(algorithm:CompressionAlgorithm = null) + { + #if neko + var src = alloced == length ? this : sub(0, length); + #else + var src = this; + #end + + var result:Bytes; + + if (algorithm == CompressionAlgorithm.LZMA) + { + result = Bytes.ofData(nme_lzma_encode( cast src.getData()) ); + + } else + { + var windowBits = switch(algorithm) + { + case DEFLATE: -15; + case GZIP: 31; + default: 15; + } + + #if enable_deflate + result = Compress.run(src, 8, windowBits); + #else + result = Compress.run(src, 8); + #end + } + + b = result.b; + length = result.length; + position = length; + #if neko + alloced = length; + #end + } + + public function deflate() + { + compress(CompressionAlgorithm.DEFLATE); + } + +#end //!lime_html5 + + /** @private */ private function ensureElem(inSize:Int, inUpdateLenght:Bool) { + var len = inSize + 1; + + #if neko + if (alloced < len) + { + alloced =((len+1) * 3) >> 1; + var new_b = untyped __dollar__smake(alloced); + untyped __dollar__sblit(new_b, 0, b, 0, length); + b = new_b; + } + #else + if (b.length < len) + untyped b.__SetSize(len); + #end + + if (inUpdateLenght && length < len) + length = len; + } + + static public function fromBytes(inBytes:Bytes) + { + var result = new ByteArray( -1); + result.nmeFromBytes(inBytes); + return result; + } + + public function getLength():Int { return length; } + + // IMemoryRange + public function getByteBuffer():ByteArray { return this; } + public function getStart():Int { return 0; } + +#if !lime_html5 + + public function inflate() { + + uncompress(CompressionAlgorithm.DEFLATE); + + } + +#end //!lime_html5 + + private inline function nmeFromBytes(inBytes:Bytes):Void + { + b = inBytes.b; + length = inBytes.length; + + #if neko + alloced = length; + #end + } + + public inline function readBoolean():Bool + { + return(position < length) ? __get(position++) != 0 : ThrowEOFi() != 0; + } + + public inline function readByte():Int + { + var val:Int = readUnsignedByte(); + return((val & 0x80) != 0) ?(val - 0x100) : val; + } + + public function readBytes(outData:ByteArray, inOffset:Int = 0, inLen:Int = 0):Void + { + if (inLen == 0) + inLen = length - position; + + if (position + inLen > length) + ThrowEOFi(); + + if (outData.length < inOffset + inLen) + outData.ensureElem(inOffset + inLen - 1, true); + + #if neko + outData.blit(inOffset, this, position, inLen); + #else + var b1 = b; + var b2 = outData.b; + var p = position; + for(i in 0...inLen) + b2[inOffset + i] = b1[p + i]; + #end + + position += inLen; + } + + public function readDouble():Float + { + #if !lime_html5 + + if (position + 8 > length) + ThrowEOFi(); + + #if neko + var bytes = new Bytes(8, untyped __dollar__ssub(b, position, 8)); + #elseif cpp + var bytes = new Bytes(8, b.slice(position, position + 8)); + #end + + position += 8; + return _double_of_bytes(bytes.b, bigEndian); + + #end //!lime_html5 + + return 0.0; + } + + #if !no_nme_io + static public function readFile(inString:String):ByteArray + { + return nme_byte_array_read_file(inString); + } + #end + + public function readFloat():Float + { + #if !lime_html5 + + if (position + 4 > length) + ThrowEOFi(); + + #if neko + var bytes = new Bytes(4, untyped __dollar__ssub(b, position, 4)); + #elseif cpp + var bytes = new Bytes(4, b.slice(position, position + 4)); + #end + + position += 4; + return _float_of_bytes(bytes.b, bigEndian); + + #end //!lime_html5 + + return 0.0; + } + + public function readInt():Int + { + var ch1 = readUnsignedByte(); + var ch2 = readUnsignedByte(); + var ch3 = readUnsignedByte(); + var ch4 = readUnsignedByte(); + + return bigEndian ?(ch1 << 24) |(ch2 << 16) |(ch3 << 8) | ch4 :(ch4 << 24) |(ch3 << 16) |(ch2 << 8) | ch1; + } + + public inline function readMultiByte(inLen:Int, charSet:String):String + { + // TODO - use code page + return readUTFBytes(inLen); + } + + public function readShort():Int + { + var ch1 = readUnsignedByte(); + var ch2 = readUnsignedByte(); + + var val = bigEndian ?((ch1 << 8) | ch2) :((ch2 << 8) | ch1); + + return((val & 0x8000) != 0) ?(val - 0x10000) : val; + } + + inline public function readUnsignedByte():Int + { + return(position < length) ? __get(position++) : ThrowEOFi(); + } + + public function readUnsignedInt():Int + { + var ch1 = readUnsignedByte(); + var ch2 = readUnsignedByte(); + var ch3 = readUnsignedByte(); + var ch4 = readUnsignedByte(); + + return bigEndian ?(ch1 << 24) |(ch2 << 16) |(ch3 << 8) | ch4 :(ch4 << 24) |(ch3 << 16) |(ch2 << 8) | ch1; + } + + public function readUnsignedShort():Int + { + var ch1 = readUnsignedByte(); + var ch2 = readUnsignedByte(); + + return bigEndian ?(ch1 << 8) | ch2 :(ch2 << 8) + ch1; + } + + public function readUTF():String + { + var len = readUnsignedShort(); + return readUTFBytes(len); + } + + public function readUTFBytes(inLen:Int):String + { + if (position + inLen > length) + ThrowEOFi(); + + var p = position; + position += inLen; + + #if lime_native + + #if neko + return new String(untyped __dollar__ssub(b, p, inLen)); + #elseif cpp + var result:String=""; + untyped __global__.__hxcpp_string_of_bytes(b, result, p, inLen); + return result; + #end + + #else + return "-"; + #end + + } + + public function setLength(inLength:Int):Void + { + if (inLength > 0) + ensureElem(inLength - 1, false); + length = inLength; + } + + // ArrayBuffer interface + public function slice(inBegin:Int, ?inEnd:Int):ByteArray + { + var begin = inBegin; + + if (begin < 0) + { + begin += length; + if (begin < 0) + begin = 0; + } + + var end:Int = inEnd == null ? length : inEnd; + + if (end < 0) + { + end += length; + + if (end < 0) + end = 0; + } + + if (begin >= end) + return new ByteArray(); + + var result = new ByteArray(end - begin); + + var opos = position; + result.blit(0, this, begin, end - begin); + + return result; + } + + /** @private */ private function ThrowEOFi():Int { + throw "new EOFError();"; //todo sven + return 0; + } + +#if !lime_html5 +//todo sven + + public function uncompress(algorithm:CompressionAlgorithm = null):Void + { + if (algorithm == null) algorithm = CompressionAlgorithm.GZIP; + + #if neko + var src = alloced == length ? this : sub(0, length); + #else + var src = this; + #end + + var result:Bytes; + + if (algorithm == CompressionAlgorithm.LZMA) + { + result = Bytes.ofData(nme_lzma_decode(src.getData())); + + } else + { + var windowBits = switch(algorithm) + { + case DEFLATE: -15; + case GZIP: 31; + default: 15; + } + + #if enable_deflate + result = Uncompress.run(src, null, windowBits); + #else + result = Uncompress.run(src, null); + #end + } + + b = result.b; + length = result.length; + position = 0; + #if neko + alloced = length; + #end + } + +#end //!lime_html5 + + /** @private */ inline function write_uncheck(inByte:Int) { + #if cpp + untyped b.__unsafe_set(position++, inByte); + #else + untyped __dollar__sset(b, position++, inByte & 0xff); + #end + } + + public function writeBoolean(value:Bool) + { + writeByte(value ? 1 : 0); + } + + inline public function writeByte(value:Int) + { + ensureElem(position, true); + + #if cpp + b[position++] = untyped value; + #else + untyped __dollar__sset(b, position++, value & 0xff); + #end + } + + public function writeBytes(bytes:Bytes, inOffset:Int = 0, inLength:Int = 0) + { + if (inLength == 0) inLength = bytes.length - inOffset; + ensureElem(position + inLength - 1, true); + var opos = position; + position += inLength; + blit(opos, bytes, inOffset, inLength); + } + + public function writeDouble(x:Float) + { + #if !lime_html5 + + #if neko + var bytes = new Bytes(8, _double_bytes(x, bigEndian)); + #elseif cpp + var bytes = Bytes.ofData(_double_bytes(x, bigEndian)); + #end + + writeBytes(bytes); + + #end //!lime_html5 + } + + #if !no_nme_io + public function writeFile(inString:String):Void + { + nme_byte_array_overwrite_file(inString, this); + } + #end + + public function writeFloat(x:Float) + { + #if !lime_html5 + + #if neko + var bytes = new Bytes(4, _float_bytes(x, bigEndian)); + #elseif cpp + var bytes = Bytes.ofData(_float_bytes(x, bigEndian)); + #end + + writeBytes(bytes); + + #end //!lime_html5 + } + + public function writeInt(value:Int) + { + ensureElem(position + 3, true); + + if (bigEndian) + { + write_uncheck(value >> 24); + write_uncheck(value >> 16); + write_uncheck(value >> 8); + write_uncheck(value); + + } else + { + write_uncheck(value); + write_uncheck(value >> 8); + write_uncheck(value >> 16); + write_uncheck(value >> 24); + } + } + + // public function writeMultiByte(value:String, charSet:String) + // public function writeObject(object:*) + public function writeShort(value:Int) + { + ensureElem(position + 1, true); + + if (bigEndian) + { + write_uncheck(value >> 8); + write_uncheck(value); + + } else + { + write_uncheck(value); + write_uncheck(value >> 8); + } + } + + public function writeUnsignedInt(value:Int) + { + writeInt(value); + } + + public function writeUTF(s:String) + { + #if neko + var bytes = new Bytes(s.length, untyped s.__s); + #else + var bytes = Bytes.ofString(s); + #end + + writeShort(bytes.length); + writeBytes(bytes); + } + + public function writeUTFBytes(s:String) + { + #if neko + var bytes = new Bytes(s.length, untyped s.__s); + #else + var bytes = Bytes.ofString(s); + #end + + writeBytes(bytes); + } + + // Getters & Setters + private function get_bytesAvailable():Int { return length - position; } + private function get_byteLength():Int { return length; } + private function get_endian():String { return bigEndian ? Endian.BIG_ENDIAN : Endian.LITTLE_ENDIAN; } + private function set_endian(s:String):String { bigEndian =(s == Endian.BIG_ENDIAN); return s; } + + // Native Methods + /** @private */ private static var _double_bytes = Libs.load("std", "double_bytes", 2); + /** @private */ private static var _double_of_bytes = Libs.load("std", "double_of_bytes", 2); + /** @private */ private static var _float_bytes = Libs.load("std", "float_bytes", 2); + /** @private */ private static var _float_of_bytes = Libs.load("std", "float_of_bytes", 2); + #if !no_nme_io + private static var nme_byte_array_overwrite_file = Libs.load("nme","nme_byte_array_overwrite_file", 2); + private static var nme_byte_array_read_file = Libs.load("nme", "nme_byte_array_read_file", 1); + #end + private static var nme_lzma_encode = Libs.load("nme", "nme_lzma_encode", 1); + private static var nme_lzma_decode = Libs.load("nme", "nme_lzma_decode", 1); +} + +#else +typedef ByteArray = flash.utils.ByteArray; +#end