1347 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			1347 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								import js.Browser;
							 | 
						|||
| 
								 | 
							
								import js.Syntax;
							 | 
						|||
| 
								 | 
							
								import js.html.CanvasElement;
							 | 
						|||
| 
								 | 
							
								import js.html.ClipboardEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.DeviceMotionEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.DeviceOrientationEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.KeyboardEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.MouseEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.Touch;
							 | 
						|||
| 
								 | 
							
								import js.html.TouchEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.WebSocket;
							 | 
						|||
| 
								 | 
							
								import js.html.WheelEvent;
							 | 
						|||
| 
								 | 
							
								import js.html.webgl.GL;
							 | 
						|||
| 
								 | 
							
								import kha.System;
							 | 
						|||
| 
								 | 
							
								import kha.graphics4.TextureFormat;
							 | 
						|||
| 
								 | 
							
								import kha.input.Gamepad;
							 | 
						|||
| 
								 | 
							
								import kha.input.KeyCode;
							 | 
						|||
| 
								 | 
							
								import kha.input.Keyboard;
							 | 
						|||
| 
								 | 
							
								import kha.input.Mouse;
							 | 
						|||
| 
								 | 
							
								import kha.input.Sensor;
							 | 
						|||
| 
								 | 
							
								import kha.input.Surface;
							 | 
						|||
| 
								 | 
							
								import kha.js.AudioElementAudio;
							 | 
						|||
| 
								 | 
							
								import kha.js.CanvasGraphics;
							 | 
						|||
| 
								 | 
							
								import kha.js.MobileWebAudio;
							 | 
						|||
| 
								 | 
							
								import kha.js.vr.VrInterface;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								using StringTools;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								class GamepadStates {
							 | 
						|||
| 
								 | 
							
									public var axes: Array<Float>;
							 | 
						|||
| 
								 | 
							
									public var buttons: Array<Float>;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public function new() {
							 | 
						|||
| 
								 | 
							
										axes = new Array<Float>();
							 | 
						|||
| 
								 | 
							
										buttons = new Array<Float>();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								class SystemImpl {
							 | 
						|||
| 
								 | 
							
									public static var gl: GL;
							 | 
						|||
| 
								 | 
							
									public static var gl2: Bool;
							 | 
						|||
| 
								 | 
							
									public static var halfFloat: Dynamic;
							 | 
						|||
| 
								 | 
							
									public static var anisotropicFilter: Dynamic;
							 | 
						|||
| 
								 | 
							
									public static var depthTexture: Dynamic;
							 | 
						|||
| 
								 | 
							
									public static var drawBuffers: Dynamic;
							 | 
						|||
| 
								 | 
							
									public static var elementIndexUint: Dynamic;
							 | 
						|||
| 
								 | 
							
									@:noCompletion public static var _hasWebAudio: Bool;
							 | 
						|||
| 
								 | 
							
									// public static var graphics(default, null): Graphics;
							 | 
						|||
| 
								 | 
							
									public static var khanvas: CanvasElement;
							 | 
						|||
| 
								 | 
							
									static var options: SystemOptions;
							 | 
						|||
| 
								 | 
							
									public static var mobile: Bool = false;
							 | 
						|||
| 
								 | 
							
									public static var ios: Bool = false;
							 | 
						|||
| 
								 | 
							
									public static var mobileAudioPlaying: Bool = false;
							 | 
						|||
| 
								 | 
							
									static var chrome: Bool = false;
							 | 
						|||
| 
								 | 
							
									static var firefox: Bool = false;
							 | 
						|||
| 
								 | 
							
									public static var safari: Bool = false;
							 | 
						|||
| 
								 | 
							
									public static var ie: Bool = false;
							 | 
						|||
| 
								 | 
							
									public static var insideInputEvent: Bool = false;
							 | 
						|||
| 
								 | 
							
									static public var activeMouseEvent: Null<MouseEvent>;
							 | 
						|||
| 
								 | 
							
									static public var activeWheelEvent: Null<WheelEvent>;
							 | 
						|||
| 
								 | 
							
									static public var activeKeyEvent: Null<KeyboardEvent>;
							 | 
						|||
| 
								 | 
							
									static var window: Window;
							 | 
						|||
| 
								 | 
							
									public static var estimatedRefreshRate: Int = 60;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function errorHandler(message: String, source: String, lineno: Int, colno: Int, error: Dynamic) {
							 | 
						|||
| 
								 | 
							
										Browser.console.error("Error: " + message);
							 | 
						|||
| 
								 | 
							
										if (error != null) {
							 | 
						|||
| 
								 | 
							
											if (Std.isOfType(error, haxe.Exception)) {
							 | 
						|||
| 
								 | 
							
												var err: haxe.Exception = error;
							 | 
						|||
| 
								 | 
							
												if (err.stack != null) {
							 | 
						|||
| 
								 | 
							
													Browser.console.error("Stack:\n" + err.stack);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											else if (Std.isOfType(error, js.lib.Error)) {
							 | 
						|||
| 
								 | 
							
												var err: js.lib.Error = error;
							 | 
						|||
| 
								 | 
							
												if (err.stack != null) {
							 | 
						|||
| 
								 | 
							
													Browser.console.error("Stack:\n" + err.stack);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return true;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function init(options: SystemOptions, callback: Window->Void): Void {
							 | 
						|||
| 
								 | 
							
										SystemImpl.options = options;
							 | 
						|||
| 
								 | 
							
										#if kha_debug_html5
							 | 
						|||
| 
								 | 
							
										Browser.window.onerror = cast errorHandler;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var showWindow = Syntax.code("window.electron.showWindow");
							 | 
						|||
| 
								 | 
							
										showWindow(options.title, options.window.x, options.window.y, options.width, options.height);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										initSecondStep(callback);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										chrome = true;
							 | 
						|||
| 
								 | 
							
										mobileAudioPlaying = true;
							 | 
						|||
| 
								 | 
							
										#else
							 | 
						|||
| 
								 | 
							
										mobile = isMobile();
							 | 
						|||
| 
								 | 
							
										ios = isIOS();
							 | 
						|||
| 
								 | 
							
										chrome = isChrome();
							 | 
						|||
| 
								 | 
							
										firefox = isFirefox();
							 | 
						|||
| 
								 | 
							
										safari = isSafari();
							 | 
						|||
| 
								 | 
							
										ie = isIE();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										mobileAudioPlaying = !mobile && !chrome && !firefox;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										initSecondStep(callback);
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										#if kha_live_reload
							 | 
						|||
| 
								 | 
							
										function openWebSocket(): Void {
							 | 
						|||
| 
								 | 
							
											var host = Browser.location.hostname;
							 | 
						|||
| 
								 | 
							
											if (host == "")
							 | 
						|||
| 
								 | 
							
												host = "localhost";
							 | 
						|||
| 
								 | 
							
											var port = Std.parseInt(Browser.location.port);
							 | 
						|||
| 
								 | 
							
											if (port == null)
							 | 
						|||
| 
								 | 
							
												port = 80;
							 | 
						|||
| 
								 | 
							
											final ws = new WebSocket('ws://$host:${port + 1}');
							 | 
						|||
| 
								 | 
							
											ws.onmessage = () -> Browser.location.reload();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										openWebSocket();
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function initSecondStep(callback: Window->Void): Void {
							 | 
						|||
| 
								 | 
							
										init2(options.window.width, options.window.height);
							 | 
						|||
| 
								 | 
							
										initAnimate(callback);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function initSensor(): Void {
							 | 
						|||
| 
								 | 
							
										if (ios) { // In Safari for iOS the directions are reversed on axes x, y and z
							 | 
						|||
| 
								 | 
							
											Browser.window.ondevicemotion = function(event: DeviceMotionEvent) {
							 | 
						|||
| 
								 | 
							
												Sensor._changed(0, -event.accelerationIncludingGravity.x, -event.accelerationIncludingGravity.y, -event.accelerationIncludingGravity.z);
							 | 
						|||
| 
								 | 
							
											};
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else {
							 | 
						|||
| 
								 | 
							
											Browser.window.ondevicemotion = function(event: DeviceMotionEvent) {
							 | 
						|||
| 
								 | 
							
												Sensor._changed(0, event.accelerationIncludingGravity.x, event.accelerationIncludingGravity.y, event.accelerationIncludingGravity.z);
							 | 
						|||
| 
								 | 
							
											};
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										Browser.window.ondeviceorientation = function(event: DeviceOrientationEvent) {
							 | 
						|||
| 
								 | 
							
											Sensor._changed(1, event.beta, event.gamma, event.alpha);
							 | 
						|||
| 
								 | 
							
										};
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isMobile(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										if (agent.contains("Android") || agent.contains("webOS") || agent.contains("BlackBerry") || agent.contains("Windows Phone")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										if (isIOS())
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isIOS(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										if (agent.contains("iPhone") || agent.contains("iPad") || agent.contains("iPod")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isChrome(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										if (agent.contains("Chrome")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isFirefox(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										if (agent.contains("Firefox")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isSafari(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										// Chrome has both in UA
							 | 
						|||
| 
								 | 
							
										if (agent.contains("Safari") && !agent.contains("Chrome")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function isIE(): Bool {
							 | 
						|||
| 
								 | 
							
										var agent = js.Browser.navigator.userAgent;
							 | 
						|||
| 
								 | 
							
										if (agent.contains("MSIE ") || agent.contains("Trident/")) {
							 | 
						|||
| 
								 | 
							
											return true;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function setCanvas(canvas: CanvasElement): Void {
							 | 
						|||
| 
								 | 
							
										khanvas = canvas;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getScreenRotation(): ScreenRotation {
							 | 
						|||
| 
								 | 
							
										return ScreenRotation.RotationNone;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getTime(): Float {
							 | 
						|||
| 
								 | 
							
										final now = js.Browser.window.performance != null ? js.Browser.window.performance.now() : js.lib.Date.now();
							 | 
						|||
| 
								 | 
							
										return now / 1000;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getSystemId(): String {
							 | 
						|||
| 
								 | 
							
										return "HTML5";
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function vibrate(ms: Int): Void {
							 | 
						|||
| 
								 | 
							
										Browser.navigator.vibrate(ms);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getLanguage(): String {
							 | 
						|||
| 
								 | 
							
										final lang = Browser.navigator.language;
							 | 
						|||
| 
								 | 
							
										return lang.substr(0, 2).toLowerCase();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function requestShutdown(): Bool {
							 | 
						|||
| 
								 | 
							
										Browser.window.close();
							 | 
						|||
| 
								 | 
							
										return true;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static inline var maxGamepads: Int = 4;
							 | 
						|||
| 
								 | 
							
									static var frame: Framebuffer;
							 | 
						|||
| 
								 | 
							
									static var keyboard: Keyboard = null;
							 | 
						|||
| 
								 | 
							
									static var mouse: kha.input.Mouse;
							 | 
						|||
| 
								 | 
							
									static var surface: Surface;
							 | 
						|||
| 
								 | 
							
									static var gamepads: Array<Gamepad>;
							 | 
						|||
| 
								 | 
							
									static var gamepadStates: Array<GamepadStates>;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static var minimumScroll: Int = 999;
							 | 
						|||
| 
								 | 
							
									static var mouseX: Int;
							 | 
						|||
| 
								 | 
							
									static var mouseY: Int;
							 | 
						|||
| 
								 | 
							
									static var touchX: Int;
							 | 
						|||
| 
								 | 
							
									static var touchY: Int;
							 | 
						|||
| 
								 | 
							
									static var lastFirstTouchX: Int = 0;
							 | 
						|||
| 
								 | 
							
									static var lastFirstTouchY: Int = 0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function init2(defaultWidth: Int, defaultHeight: Int, ?backbufferFormat: TextureFormat) {
							 | 
						|||
| 
								 | 
							
										#if !kha_no_keyboard
							 | 
						|||
| 
								 | 
							
										keyboard = new Keyboard();
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
										mouse = new kha.input.MouseImpl();
							 | 
						|||
| 
								 | 
							
										surface = new Surface();
							 | 
						|||
| 
								 | 
							
										gamepads = new Array<Gamepad>();
							 | 
						|||
| 
								 | 
							
										gamepadStates = new Array<GamepadStates>();
							 | 
						|||
| 
								 | 
							
										for (i in 0...maxGamepads) {
							 | 
						|||
| 
								 | 
							
											gamepads[i] = new Gamepad(i);
							 | 
						|||
| 
								 | 
							
											gamepadStates[i] = new GamepadStates();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										js.Browser.window.addEventListener("gamepadconnected", (e) -> {
							 | 
						|||
| 
								 | 
							
											var pad: js.html.Gamepad = e.gamepad;
							 | 
						|||
| 
								 | 
							
											Gamepad.sendConnectEvent(pad.index);
							 | 
						|||
| 
								 | 
							
											for (i in 0...pad.buttons.length) {
							 | 
						|||
| 
								 | 
							
												gamepadStates[pad.index].buttons[i] = 0;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										});
							 | 
						|||
| 
								 | 
							
										js.Browser.window.addEventListener("gamepaddisconnected", (e) -> {
							 | 
						|||
| 
								 | 
							
											Gamepad.sendDisconnectEvent(e.gamepad.index);
							 | 
						|||
| 
								 | 
							
										});
							 | 
						|||
| 
								 | 
							
										var sysGamepads = getGamepads();
							 | 
						|||
| 
								 | 
							
										if (sysGamepads != null) {
							 | 
						|||
| 
								 | 
							
											for (i in 0...sysGamepads.length) {
							 | 
						|||
| 
								 | 
							
												var pad = sysGamepads[i];
							 | 
						|||
| 
								 | 
							
												if (pad != null) {
							 | 
						|||
| 
								 | 
							
													gamepads[pad.index].connected = true;
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										function onCopy(e: ClipboardEvent): Void {
							 | 
						|||
| 
								 | 
							
											if (System.copyListener != null) {
							 | 
						|||
| 
								 | 
							
												var data = System.copyListener();
							 | 
						|||
| 
								 | 
							
												if (data != null)
							 | 
						|||
| 
								 | 
							
													e.clipboardData.setData("text/plain", data);
							 | 
						|||
| 
								 | 
							
												e.preventDefault();
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										function onCut(e: ClipboardEvent): Void {
							 | 
						|||
| 
								 | 
							
											if (System.cutListener != null) {
							 | 
						|||
| 
								 | 
							
												var data = System.cutListener();
							 | 
						|||
| 
								 | 
							
												if (data != null)
							 | 
						|||
| 
								 | 
							
													e.clipboardData.setData("text/plain", data);
							 | 
						|||
| 
								 | 
							
												e.preventDefault();
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										function onPaste(e: ClipboardEvent): Void {
							 | 
						|||
| 
								 | 
							
											if (System.pasteListener != null) {
							 | 
						|||
| 
								 | 
							
												System.pasteListener(e.clipboardData.getData("text/plain"));
							 | 
						|||
| 
								 | 
							
												e.preventDefault();
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var document = Browser.document;
							 | 
						|||
| 
								 | 
							
										document.addEventListener("copy", onCopy);
							 | 
						|||
| 
								 | 
							
										document.addEventListener("cut", onCut);
							 | 
						|||
| 
								 | 
							
										document.addEventListener("paste", onPaste);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										CanvasImage.init();
							 | 
						|||
| 
								 | 
							
										Scheduler.init();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										loadFinished(defaultWidth, defaultHeight);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function copyToClipboard(text: String) {
							 | 
						|||
| 
								 | 
							
										var textArea = Browser.document.createElement("textarea");
							 | 
						|||
| 
								 | 
							
										untyped textArea.value = text;
							 | 
						|||
| 
								 | 
							
										textArea.style.top = "0";
							 | 
						|||
| 
								 | 
							
										textArea.style.left = "0";
							 | 
						|||
| 
								 | 
							
										textArea.style.position = "fixed";
							 | 
						|||
| 
								 | 
							
										Browser.document.body.appendChild(textArea);
							 | 
						|||
| 
								 | 
							
										textArea.focus();
							 | 
						|||
| 
								 | 
							
										untyped textArea.select();
							 | 
						|||
| 
								 | 
							
										try {
							 | 
						|||
| 
								 | 
							
											Browser.document.execCommand("copy");
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										catch (err) {}
							 | 
						|||
| 
								 | 
							
										Browser.document.body.removeChild(textArea);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getMouse(num: Int): Mouse {
							 | 
						|||
| 
								 | 
							
										if (num != 0)
							 | 
						|||
| 
								 | 
							
											return null;
							 | 
						|||
| 
								 | 
							
										return mouse;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getKeyboard(num: Int): Keyboard {
							 | 
						|||
| 
								 | 
							
										if (num != 0)
							 | 
						|||
| 
								 | 
							
											return null;
							 | 
						|||
| 
								 | 
							
										return keyboard;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function checkGamepad(pad: js.html.Gamepad) {
							 | 
						|||
| 
								 | 
							
										for (i in 0...pad.axes.length) {
							 | 
						|||
| 
								 | 
							
											if (pad.axes[i] != null) {
							 | 
						|||
| 
								 | 
							
												var axis = pad.axes[i];
							 | 
						|||
| 
								 | 
							
												if (gamepadStates[pad.index].axes[i] != axis) {
							 | 
						|||
| 
								 | 
							
													gamepadStates[pad.index].axes[i] = axis;
							 | 
						|||
| 
								 | 
							
													gamepads[pad.index].sendAxisEvent(i, axis);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										for (i in 0...pad.buttons.length) {
							 | 
						|||
| 
								 | 
							
											if (pad.buttons[i] != null) {
							 | 
						|||
| 
								 | 
							
												if (gamepadStates[pad.index].buttons[i] != pad.buttons[i].value) {
							 | 
						|||
| 
								 | 
							
													gamepadStates[pad.index].buttons[i] = pad.buttons[i].value;
							 | 
						|||
| 
								 | 
							
													gamepads[pad.index].sendButtonEvent(i, pad.buttons[i].value);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										if (pad.axes.length <= 4 && pad.buttons.length > 7) {
							 | 
						|||
| 
								 | 
							
											// Fix for the triggers not being axis in html5
							 | 
						|||
| 
								 | 
							
											gamepadStates[pad.index].axes[4] = pad.buttons[6].value;
							 | 
						|||
| 
								 | 
							
											gamepads[pad.index].sendAxisEvent(4, pad.buttons[6].value);
							 | 
						|||
| 
								 | 
							
											gamepadStates[pad.index].axes[5] = pad.buttons[7].value;
							 | 
						|||
| 
								 | 
							
											gamepads[pad.index].sendAxisEvent(5, pad.buttons[7].value);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function getCanvasElement(): CanvasElement {
							 | 
						|||
| 
								 | 
							
										if (khanvas != null)
							 | 
						|||
| 
								 | 
							
											return khanvas;
							 | 
						|||
| 
								 | 
							
										// Only consider custom canvas ID for release builds
							 | 
						|||
| 
								 | 
							
										#if (kha_debug_html5 || !canvas_id)
							 | 
						|||
| 
								 | 
							
										return cast Browser.document.getElementById("khanvas");
							 | 
						|||
| 
								 | 
							
										#else
							 | 
						|||
| 
								 | 
							
										return cast Browser.document.getElementById(Macros.canvasId());
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function loadFinished(defaultWidth: Int, defaultHeight: Int) {
							 | 
						|||
| 
								 | 
							
										var canvas: CanvasElement = getCanvasElement();
							 | 
						|||
| 
								 | 
							
										canvas.style.cursor = "default";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var gl: Bool = false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										#if kha_webgl
							 | 
						|||
| 
								 | 
							
										try {
							 | 
						|||
| 
								 | 
							
											SystemImpl.gl = canvas.getContext("webgl2",
							 | 
						|||
| 
								 | 
							
												{
							 | 
						|||
| 
								 | 
							
													alpha: false,
							 | 
						|||
| 
								 | 
							
													antialias: options.framebuffer.samplesPerPixel > 1,
							 | 
						|||
| 
								 | 
							
													stencil: true
							 | 
						|||
| 
								 | 
							
												}); // preserveDrawingBuffer: true } ); Warning: preserveDrawingBuffer can cause huge performance issues on mobile browsers
							 | 
						|||
| 
								 | 
							
											SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											halfFloat = {HALF_FLOAT_OES: 0x140B}; // GL_HALF_FLOAT
							 | 
						|||
| 
								 | 
							
											depthTexture = {UNSIGNED_INT_24_8_WEBGL: 0x84FA}; // GL_UNSIGNED_INT_24_8
							 | 
						|||
| 
								 | 
							
											drawBuffers = {COLOR_ATTACHMENT0_WEBGL: GL.COLOR_ATTACHMENT0};
							 | 
						|||
| 
								 | 
							
											elementIndexUint = true;
							 | 
						|||
| 
								 | 
							
											SystemImpl.gl.getExtension("EXT_color_buffer_float");
							 | 
						|||
| 
								 | 
							
											SystemImpl.gl.getExtension("OES_texture_float_linear");
							 | 
						|||
| 
								 | 
							
											SystemImpl.gl.getExtension("OES_texture_half_float_linear");
							 | 
						|||
| 
								 | 
							
											anisotropicFilter = SystemImpl.gl.getExtension("EXT_texture_filter_anisotropic");
							 | 
						|||
| 
								 | 
							
											if (anisotropicFilter == null)
							 | 
						|||
| 
								 | 
							
												anisotropicFilter = SystemImpl.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic");
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											gl = true;
							 | 
						|||
| 
								 | 
							
											gl2 = true;
							 | 
						|||
| 
								 | 
							
											Shaders.init();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										catch (e:Dynamic) {
							 | 
						|||
| 
								 | 
							
											trace("Could not initialize WebGL 2, falling back to WebGL.");
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (!gl2) {
							 | 
						|||
| 
								 | 
							
											try {
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl = canvas.getContext("experimental-webgl",
							 | 
						|||
| 
								 | 
							
													{
							 | 
						|||
| 
								 | 
							
														alpha: false,
							 | 
						|||
| 
								 | 
							
														antialias: options.framebuffer.samplesPerPixel > 1,
							 | 
						|||
| 
								 | 
							
														stencil: true
							 | 
						|||
| 
								 | 
							
													}); // preserveDrawingBuffer: true } ); WARNING: preserveDrawingBuffer causes huge performance issues (on mobile browser)!
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.getExtension("OES_texture_float");
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.getExtension("OES_texture_float_linear");
							 | 
						|||
| 
								 | 
							
												halfFloat = SystemImpl.gl.getExtension("OES_texture_half_float");
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.getExtension("OES_texture_half_float_linear");
							 | 
						|||
| 
								 | 
							
												depthTexture = SystemImpl.gl.getExtension("WEBGL_depth_texture");
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.getExtension("EXT_shader_texture_lod");
							 | 
						|||
| 
								 | 
							
												SystemImpl.gl.getExtension("OES_standard_derivatives");
							 | 
						|||
| 
								 | 
							
												anisotropicFilter = SystemImpl.gl.getExtension("EXT_texture_filter_anisotropic");
							 | 
						|||
| 
								 | 
							
												if (anisotropicFilter == null)
							 | 
						|||
| 
								 | 
							
													anisotropicFilter = SystemImpl.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic");
							 | 
						|||
| 
								 | 
							
												drawBuffers = SystemImpl.gl.getExtension("WEBGL_draw_buffers");
							 | 
						|||
| 
								 | 
							
												elementIndexUint = SystemImpl.gl.getExtension("OES_element_index_uint");
							 | 
						|||
| 
								 | 
							
												gl = true;
							 | 
						|||
| 
								 | 
							
												Shaders.init();
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											catch (e:Dynamic) {
							 | 
						|||
| 
								 | 
							
												trace("Could not initialize WebGL, falling back to <canvas>.");
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										setCanvas(canvas);
							 | 
						|||
| 
								 | 
							
										window = new Window(0, defaultWidth, defaultHeight, canvas);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// var widthTransform: Float = canvas.width / Loader.the.width;
							 | 
						|||
| 
								 | 
							
										// var heightTransform: Float = canvas.height / Loader.the.height;
							 | 
						|||
| 
								 | 
							
										// var transform: Float = Math.min(widthTransform, heightTransform);
							 | 
						|||
| 
								 | 
							
										if (gl) {
							 | 
						|||
| 
								 | 
							
											var g4 = new kha.js.graphics4.Graphics();
							 | 
						|||
| 
								 | 
							
											frame = new Framebuffer(0, null, null, g4);
							 | 
						|||
| 
								 | 
							
											frame.init(new kha.graphics2.Graphics1(frame), new kha.js.graphics4.Graphics2(frame), g4); // new kha.graphics1.Graphics4(frame));
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else {
							 | 
						|||
| 
								 | 
							
											Syntax.code("kha_js_Font.Kravur = kha_Kravur; kha_Kravur = kha_js_Font");
							 | 
						|||
| 
								 | 
							
											var g2 = new CanvasGraphics(canvas.getContext("2d"));
							 | 
						|||
| 
								 | 
							
											frame = new Framebuffer(0, null, g2, null);
							 | 
						|||
| 
								 | 
							
											frame.init(new kha.graphics2.Graphics1(frame), g2, null);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										// canvas.getContext("2d").scale(transform, transform);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (!mobile && kha.audio2.Audio._init()) {
							 | 
						|||
| 
								 | 
							
											SystemImpl._hasWebAudio = true;
							 | 
						|||
| 
								 | 
							
											kha.audio2.Audio1._init();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (mobile) {
							 | 
						|||
| 
								 | 
							
											SystemImpl._hasWebAudio = false;
							 | 
						|||
| 
								 | 
							
											MobileWebAudio._init();
							 | 
						|||
| 
								 | 
							
											Syntax.code("kha_audio2_Audio1 = kha_js_MobileWebAudio");
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else {
							 | 
						|||
| 
								 | 
							
											SystemImpl._hasWebAudio = false;
							 | 
						|||
| 
								 | 
							
											Syntax.code("kha_audio2_Audio1 = kha_js_AudioElementAudio");
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										kha.vr.VrInterface.instance = new VrInterface();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Autofocus
							 | 
						|||
| 
								 | 
							
										canvas.focus();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										#if kha_disable_context_menu
							 | 
						|||
| 
								 | 
							
										canvas.oncontextmenu = function(event: Dynamic) {
							 | 
						|||
| 
								 | 
							
											event.stopPropagation();
							 | 
						|||
| 
								 | 
							
											event.preventDefault();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										#end
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										canvas.onmousedown = mouseDown;
							 | 
						|||
| 
								 | 
							
										canvas.onmousemove = mouseMove;
							 | 
						|||
| 
								 | 
							
										if (keyboard != null) {
							 | 
						|||
| 
								 | 
							
											canvas.onkeydown = keyDown;
							 | 
						|||
| 
								 | 
							
											canvas.onkeyup = keyUp;
							 | 
						|||
| 
								 | 
							
											canvas.onkeypress = keyPress;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										canvas.onblur = onBlur;
							 | 
						|||
| 
								 | 
							
										canvas.onfocus = onFocus;
							 | 
						|||
| 
								 | 
							
										canvas.onmouseleave = mouseLeave;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// IE11 does not have canvas.onwheel
							 | 
						|||
| 
								 | 
							
										canvas.addEventListener("wheel", mouseWheel, false);
							 | 
						|||
| 
								 | 
							
										canvas.addEventListener("touchstart", touchDown, false);
							 | 
						|||
| 
								 | 
							
										canvas.addEventListener("touchend", touchUp, false);
							 | 
						|||
| 
								 | 
							
										canvas.addEventListener("touchmove", touchMove, false);
							 | 
						|||
| 
								 | 
							
										canvas.addEventListener("touchcancel", touchCancel, false);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Browser.document.addEventListener("dragover", function(event) {
							 | 
						|||
| 
								 | 
							
											event.preventDefault();
							 | 
						|||
| 
								 | 
							
										});
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Browser.document.addEventListener("drop", function(event: js.html.DragEvent) {
							 | 
						|||
| 
								 | 
							
											event.preventDefault();
							 | 
						|||
| 
								 | 
							
											if (event.dataTransfer != null && event.dataTransfer.files != null) {
							 | 
						|||
| 
								 | 
							
												for (file in event.dataTransfer.files) {
							 | 
						|||
| 
								 | 
							
													LoaderImpl.dropFiles.set(file.name, file);
							 | 
						|||
| 
								 | 
							
													System.dropFiles("drop://" + file.name);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										});
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Browser.window.addEventListener("unload", function() {
							 | 
						|||
| 
								 | 
							
											System.shutdown();
							 | 
						|||
| 
								 | 
							
										});
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static var lastCanvasClientWidth: Int = -1;
							 | 
						|||
| 
								 | 
							
									static var lastCanvasClientHeight: Int = -1;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function initAnimate(callback: Window->Void) {
							 | 
						|||
| 
								 | 
							
										var canvas: CanvasElement = getCanvasElement();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var window: Dynamic = Browser.window;
							 | 
						|||
| 
								 | 
							
										var requestAnimationFrame = window.requestAnimationFrame;
							 | 
						|||
| 
								 | 
							
										if (requestAnimationFrame == null)
							 | 
						|||
| 
								 | 
							
											requestAnimationFrame = window.mozRequestAnimationFrame;
							 | 
						|||
| 
								 | 
							
										if (requestAnimationFrame == null)
							 | 
						|||
| 
								 | 
							
											requestAnimationFrame = window.webkitRequestAnimationFrame;
							 | 
						|||
| 
								 | 
							
										if (requestAnimationFrame == null)
							 | 
						|||
| 
								 | 
							
											requestAnimationFrame = window.msRequestAnimationFrame;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var isRefreshRateDetectionActive = false;
							 | 
						|||
| 
								 | 
							
										var lastTimestamp = 0.0;
							 | 
						|||
| 
								 | 
							
										final possibleRefreshRates = [30, 60, 75, 90, 120, 144, 240, 340, 360];
							 | 
						|||
| 
								 | 
							
										final refreshRatesCounts = [
							 | 
						|||
| 
								 | 
							
											for (_ in 0...possibleRefreshRates.length)
							 | 
						|||
| 
								 | 
							
												0
							 | 
						|||
| 
								 | 
							
										];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										function animate(timestamp) {
							 | 
						|||
| 
								 | 
							
											if (requestAnimationFrame == null)
							 | 
						|||
| 
								 | 
							
												Browser.window.setTimeout(animate, 1000.0 / 60.0);
							 | 
						|||
| 
								 | 
							
											else
							 | 
						|||
| 
								 | 
							
												requestAnimationFrame(animate);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											var sysGamepads = getGamepads();
							 | 
						|||
| 
								 | 
							
											if (sysGamepads != null) {
							 | 
						|||
| 
								 | 
							
												for (i in 0...sysGamepads.length) {
							 | 
						|||
| 
								 | 
							
													var pad = sysGamepads[i];
							 | 
						|||
| 
								 | 
							
													if (pad != null) {
							 | 
						|||
| 
								 | 
							
														checkGamepad(pad);
							 | 
						|||
| 
								 | 
							
													}
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											Scheduler.executeFrame();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if (canvas.getContext != null) {
							 | 
						|||
| 
								 | 
							
												#if !kha_html5_disable_automatic_size_adjust
							 | 
						|||
| 
								 | 
							
												if (lastCanvasClientWidth != canvas.clientWidth || lastCanvasClientHeight != canvas.clientHeight) {
							 | 
						|||
| 
								 | 
							
													// canvas.width is the actual backbuffer-size.
							 | 
						|||
| 
								 | 
							
													// canvas.clientWidth (which is read-only and equivalent to
							 | 
						|||
| 
								 | 
							
													// canvas.style.width in pixels) is the output-size
							 | 
						|||
| 
								 | 
							
													// and by default gets scaled by devicePixelRatio.
							 | 
						|||
| 
								 | 
							
													// We revert that scale so backbuffer and output-size
							 | 
						|||
| 
								 | 
							
													// are the same.
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
													var scale = Browser.window.devicePixelRatio;
							 | 
						|||
| 
								 | 
							
													var clientWidth = canvas.clientWidth;
							 | 
						|||
| 
								 | 
							
													var clientHeight = canvas.clientHeight;
							 | 
						|||
| 
								 | 
							
													canvas.width = clientWidth;
							 | 
						|||
| 
								 | 
							
													canvas.height = clientHeight;
							 | 
						|||
| 
								 | 
							
													if (scale != 1) {
							 | 
						|||
| 
								 | 
							
														canvas.style.width = Std.int(clientWidth / scale) + "px";
							 | 
						|||
| 
								 | 
							
														canvas.style.height = Std.int(clientHeight / scale) + "px";
							 | 
						|||
| 
								 | 
							
													}
							 | 
						|||
| 
								 | 
							
													lastCanvasClientWidth = canvas.clientWidth;
							 | 
						|||
| 
								 | 
							
													lastCanvasClientHeight = canvas.clientHeight;
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
												#end
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												System.render([frame]);
							 | 
						|||
| 
								 | 
							
												if (ie && SystemImpl.gl != null) {
							 | 
						|||
| 
								 | 
							
													// Clear alpha for IE11
							 | 
						|||
| 
								 | 
							
													SystemImpl.gl.clearColor(1, 1, 1, 1);
							 | 
						|||
| 
								 | 
							
													SystemImpl.gl.colorMask(false, false, false, true);
							 | 
						|||
| 
								 | 
							
													SystemImpl.gl.clear(GL.COLOR_BUFFER_BIT);
							 | 
						|||
| 
								 | 
							
													SystemImpl.gl.colorMask(true, true, true, true);
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											if (!isRefreshRateDetectionActive)
							 | 
						|||
| 
								 | 
							
												return;
							 | 
						|||
| 
								 | 
							
											if (lastTimestamp == 0) {
							 | 
						|||
| 
								 | 
							
												lastTimestamp = timestamp;
							 | 
						|||
| 
								 | 
							
												return;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											final fps = Math.floor(1000 / (timestamp - lastTimestamp));
							 | 
						|||
| 
								 | 
							
											if (estimatedRefreshRate < fps)
							 | 
						|||
| 
								 | 
							
												estimatedRefreshRate = fps;
							 | 
						|||
| 
								 | 
							
											lastTimestamp = timestamp;
							 | 
						|||
| 
								 | 
							
											for (i => rate in possibleRefreshRates) {
							 | 
						|||
| 
								 | 
							
												if (fps > rate - 3 && fps < rate + 3)
							 | 
						|||
| 
								 | 
							
													refreshRatesCounts[i]++;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Browser.window.setTimeout(() -> {
							 | 
						|||
| 
								 | 
							
											isRefreshRateDetectionActive = true;
							 | 
						|||
| 
								 | 
							
											Browser.window.setTimeout(() -> {
							 | 
						|||
| 
								 | 
							
												isRefreshRateDetectionActive = false;
							 | 
						|||
| 
								 | 
							
												// Use 60 hz if window was out of focus and throttled to 1 fps
							 | 
						|||
| 
								 | 
							
												var index = possibleRefreshRates.indexOf(60);
							 | 
						|||
| 
								 | 
							
												var max = 0;
							 | 
						|||
| 
								 | 
							
												for (i => count in refreshRatesCounts) {
							 | 
						|||
| 
								 | 
							
													if (count > max) {
							 | 
						|||
| 
								 | 
							
														max = count;
							 | 
						|||
| 
								 | 
							
														index = i;
							 | 
						|||
| 
								 | 
							
													}
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
												estimatedRefreshRate = possibleRefreshRates[index];
							 | 
						|||
| 
								 | 
							
											}, 1000);
							 | 
						|||
| 
								 | 
							
										}, 500);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Scheduler.start();
							 | 
						|||
| 
								 | 
							
										requestAnimationFrame(animate);
							 | 
						|||
| 
								 | 
							
										callback(SystemImpl.window);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function lockMouse(): Void {
							 | 
						|||
| 
								 | 
							
										untyped if (SystemImpl.khanvas.requestPointerLock) {
							 | 
						|||
| 
								 | 
							
											SystemImpl.khanvas.requestPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (SystemImpl.khanvas.mozRequestPointerLock) {
							 | 
						|||
| 
								 | 
							
											SystemImpl.khanvas.mozRequestPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (SystemImpl.khanvas.webkitRequestPointerLock) {
							 | 
						|||
| 
								 | 
							
											SystemImpl.khanvas.webkitRequestPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function unlockMouse(): Void {
							 | 
						|||
| 
								 | 
							
										untyped if (document.exitPointerLock) {
							 | 
						|||
| 
								 | 
							
											document.exitPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (document.mozExitPointerLock) {
							 | 
						|||
| 
								 | 
							
											document.mozExitPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (document.webkitExitPointerLock) {
							 | 
						|||
| 
								 | 
							
											document.webkitExitPointerLock();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function canLockMouse(): Bool {
							 | 
						|||
| 
								 | 
							
										return Syntax.code("'pointerLockElement' in document ||
							 | 
						|||
| 
								 | 
							
										'mozPointerLockElement' in document ||
							 | 
						|||
| 
								 | 
							
										'webkitPointerLockElement' in document");
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function isMouseLocked(): Bool {
							 | 
						|||
| 
								 | 
							
										return Syntax.code("document.pointerLockElement === kha_SystemImpl.khanvas ||
							 | 
						|||
| 
								 | 
							
											document.mozPointerLockElement === kha_SystemImpl.khanvas ||
							 | 
						|||
| 
								 | 
							
											document.webkitPointerLockElement === kha_SystemImpl.khanvas");
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("pointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("mozpointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("webkitpointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("pointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("mozpointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("webkitpointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("pointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("mozpointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("webkitpointerlockchange", func, false);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("pointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("mozpointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("webkitpointerlockerror", error, false);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function setMouseXY(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										var rect = SystemImpl.khanvas.getBoundingClientRect();
							 | 
						|||
| 
								 | 
							
										var borderWidth = SystemImpl.khanvas.clientLeft;
							 | 
						|||
| 
								 | 
							
										var borderHeight = SystemImpl.khanvas.clientTop;
							 | 
						|||
| 
								 | 
							
										mouseX = Std.int((event.clientX - rect.left - borderWidth) * SystemImpl.khanvas.width / (rect.width - 2 * borderWidth));
							 | 
						|||
| 
								 | 
							
										mouseY = Std.int((event.clientY - rect.top - borderHeight) * SystemImpl.khanvas.height / (rect.height - 2 * borderHeight));
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static var iosSoundEnabled: Bool = false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function unlockiOSSound(): Void {
							 | 
						|||
| 
								 | 
							
										if (!ios || iosSoundEnabled)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var buffer = MobileWebAudio._context.createBuffer(1, 1, 22050);
							 | 
						|||
| 
								 | 
							
										var source = MobileWebAudio._context.createBufferSource();
							 | 
						|||
| 
								 | 
							
										source.buffer = buffer;
							 | 
						|||
| 
								 | 
							
										source.connect(MobileWebAudio._context.destination);
							 | 
						|||
| 
								 | 
							
										// untyped(if (source.noteOn) source.noteOn(0));
							 | 
						|||
| 
								 | 
							
										source.start();
							 | 
						|||
| 
								 | 
							
										source.stop();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										iosSoundEnabled = true;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static var soundEnabled = false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function unlockSound(): Void {
							 | 
						|||
| 
								 | 
							
										if (!soundEnabled) {
							 | 
						|||
| 
								 | 
							
											var context = kha.audio2.Audio._context;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if (context == null) {
							 | 
						|||
| 
								 | 
							
												context = Syntax.code("kha_audio2_Audio1._context");
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if (context != null) {
							 | 
						|||
| 
								 | 
							
												context.resume().then(function(c) {
							 | 
						|||
| 
								 | 
							
													soundEnabled = true;
							 | 
						|||
| 
								 | 
							
												}).catchError(function(err) {
							 | 
						|||
| 
								 | 
							
													trace(err);
							 | 
						|||
| 
								 | 
							
												});
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											kha.audio2.Audio.wakeChannels();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										unlockiOSSound();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseLeave(): Void {
							 | 
						|||
| 
								 | 
							
										mouse.sendLeaveEvent(0);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseWheel(event: WheelEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeWheelEvent = event;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										switch (Mouse.wheelEventBlockBehavior) {
							 | 
						|||
| 
								 | 
							
											case Full:
							 | 
						|||
| 
								 | 
							
												event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case Custom(func):
							 | 
						|||
| 
								 | 
							
												if (func(event))
							 | 
						|||
| 
								 | 
							
													event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case None:
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Deltamode == 0, deltaY is in pixels.
							 | 
						|||
| 
								 | 
							
										if (event.deltaMode == 0) {
							 | 
						|||
| 
								 | 
							
											if (event.deltaY < 0) {
							 | 
						|||
| 
								 | 
							
												mouse.sendWheelEvent(0, -1);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											else if (event.deltaY > 0) {
							 | 
						|||
| 
								 | 
							
												mouse.sendWheelEvent(0, 1);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											activeWheelEvent = null;
							 | 
						|||
| 
								 | 
							
											insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Lines
							 | 
						|||
| 
								 | 
							
										if (event.deltaMode == 1) {
							 | 
						|||
| 
								 | 
							
											minimumScroll = Std.int(Math.min(minimumScroll, Math.abs(event.deltaY)));
							 | 
						|||
| 
								 | 
							
											mouse.sendWheelEvent(0, Std.int(event.deltaY / minimumScroll));
							 | 
						|||
| 
								 | 
							
											activeWheelEvent = null;
							 | 
						|||
| 
								 | 
							
											insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										activeWheelEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
										return;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseDown(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeMouseEvent = event;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										setMouseXY(event);
							 | 
						|||
| 
								 | 
							
										if (event.which == 1) { // left button
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 0, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mousemove", documentMouseMove, true);
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mouseup", mouseLeftUp);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (event.which == 2) { // middle button
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 2, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mouseup", mouseMiddleUp);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (event.which == 3) { // right button
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 1, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mouseup", mouseRightUp);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (event.which == 4) { // backwards sidebutton
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 3, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mouseup", mouseBackUp);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (event.which == 5) { // forwards sidebutton
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 4, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
											khanvas.ownerDocument.addEventListener("mouseup", mouseForwardUp);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										activeMouseEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseLeftUp(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which != 1)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mouseup", mouseLeftUp);
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mousemove", documentMouseMove, true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										mouse.sendUpEvent(0, 0, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseMiddleUp(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which != 2)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mouseup", mouseMiddleUp);
							 | 
						|||
| 
								 | 
							
										mouse.sendUpEvent(0, 2, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseRightUp(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which != 3)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mouseup", mouseRightUp);
							 | 
						|||
| 
								 | 
							
										mouse.sendUpEvent(0, 1, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseBackUp(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which != 4)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mouseup", mouseBackUp);
							 | 
						|||
| 
								 | 
							
										mouse.sendUpEvent(0, 3, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseForwardUp(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which != 5)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										khanvas.ownerDocument.removeEventListener("mouseup", mouseForwardUp);
							 | 
						|||
| 
								 | 
							
										mouse.sendUpEvent(0, 4, mouseX, mouseY);
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function documentMouseMove(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										event.stopPropagation();
							 | 
						|||
| 
								 | 
							
										mouseMove(event);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function mouseMove(event: MouseEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeMouseEvent = event;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var lastMouseX = mouseX;
							 | 
						|||
| 
								 | 
							
										var lastMouseY = mouseY;
							 | 
						|||
| 
								 | 
							
										setMouseXY(event);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var movementX = event.movementX;
							 | 
						|||
| 
								 | 
							
										var movementY = event.movementY;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.movementX == null) {
							 | 
						|||
| 
								 | 
							
											movementX = (untyped event.mozMovementX != null) ? untyped event.mozMovementX : ((untyped event.webkitMovementX != null) ? untyped event.webkitMovementX : (mouseX
							 | 
						|||
| 
								 | 
							
												- lastMouseX));
							 | 
						|||
| 
								 | 
							
											movementY = (untyped event.mozMovementY != null) ? untyped event.mozMovementY : ((untyped event.webkitMovementY != null) ? untyped event.webkitMovementY : (mouseY
							 | 
						|||
| 
								 | 
							
												- lastMouseY));
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// this ensures same behaviour across browser until they fix it
							 | 
						|||
| 
								 | 
							
										if (firefox) {
							 | 
						|||
| 
								 | 
							
											movementX = Std.int(movementX * Browser.window.devicePixelRatio);
							 | 
						|||
| 
								 | 
							
											movementY = Std.int(movementY * Browser.window.devicePixelRatio);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										mouse.sendMoveEvent(0, mouseX, mouseY, movementX, movementY);
							 | 
						|||
| 
								 | 
							
										activeMouseEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function setTouchXY(touch: Touch): Void {
							 | 
						|||
| 
								 | 
							
										var rect = SystemImpl.khanvas.getBoundingClientRect();
							 | 
						|||
| 
								 | 
							
										var borderWidth = SystemImpl.khanvas.clientLeft;
							 | 
						|||
| 
								 | 
							
										var borderHeight = SystemImpl.khanvas.clientTop;
							 | 
						|||
| 
								 | 
							
										touchX = Std.int((touch.clientX - rect.left - borderWidth) * SystemImpl.khanvas.width / (rect.width - 2 * borderWidth));
							 | 
						|||
| 
								 | 
							
										touchY = Std.int((touch.clientY - rect.top - borderHeight) * SystemImpl.khanvas.height / (rect.height - 2 * borderHeight));
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static var iosTouchs: Array<Int> = [];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function touchDown(event: TouchEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										event.stopPropagation();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										switch (Surface.touchDownEventBlockBehavior) {
							 | 
						|||
| 
								 | 
							
											case Full:
							 | 
						|||
| 
								 | 
							
												event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case Custom(func):
							 | 
						|||
| 
								 | 
							
												if (func(event))
							 | 
						|||
| 
								 | 
							
													event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case None:
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var index = 0;
							 | 
						|||
| 
								 | 
							
										for (touch in event.changedTouches) {
							 | 
						|||
| 
								 | 
							
											var id = touch.identifier;
							 | 
						|||
| 
								 | 
							
											if (ios) {
							 | 
						|||
| 
								 | 
							
												id = iosTouchs.indexOf(-1);
							 | 
						|||
| 
								 | 
							
												if (id == -1)
							 | 
						|||
| 
								 | 
							
													id = iosTouchs.length;
							 | 
						|||
| 
								 | 
							
												iosTouchs[id] = touch.identifier;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											setTouchXY(touch);
							 | 
						|||
| 
								 | 
							
											mouse.sendDownEvent(0, 0, touchX, touchY);
							 | 
						|||
| 
								 | 
							
											surface.sendTouchStartEvent(id, touchX, touchY);
							 | 
						|||
| 
								 | 
							
											if (index == 0) {
							 | 
						|||
| 
								 | 
							
												lastFirstTouchX = touchX;
							 | 
						|||
| 
								 | 
							
												lastFirstTouchY = touchY;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											index++;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function touchUp(event: TouchEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										for (touch in event.changedTouches) {
							 | 
						|||
| 
								 | 
							
											var id = touch.identifier;
							 | 
						|||
| 
								 | 
							
											if (ios) {
							 | 
						|||
| 
								 | 
							
												id = iosTouchs.indexOf(id);
							 | 
						|||
| 
								 | 
							
												iosTouchs[id] = -1;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											setTouchXY(touch);
							 | 
						|||
| 
								 | 
							
											mouse.sendUpEvent(0, 0, touchX, touchY);
							 | 
						|||
| 
								 | 
							
											surface.sendTouchEndEvent(id, touchX, touchY);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function touchMove(event: TouchEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var index = 0;
							 | 
						|||
| 
								 | 
							
										for (touch in event.changedTouches) {
							 | 
						|||
| 
								 | 
							
											setTouchXY(touch);
							 | 
						|||
| 
								 | 
							
											if (index == 0) {
							 | 
						|||
| 
								 | 
							
												var movementX = touchX - lastFirstTouchX;
							 | 
						|||
| 
								 | 
							
												var movementY = touchY - lastFirstTouchY;
							 | 
						|||
| 
								 | 
							
												lastFirstTouchX = touchX;
							 | 
						|||
| 
								 | 
							
												lastFirstTouchY = touchY;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												mouse.sendMoveEvent(0, touchX, touchY, movementX, movementY);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											var id = touch.identifier;
							 | 
						|||
| 
								 | 
							
											if (ios)
							 | 
						|||
| 
								 | 
							
												id = iosTouchs.indexOf(id);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											surface.sendMoveEvent(id, touchX, touchY);
							 | 
						|||
| 
								 | 
							
											index++;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function touchCancel(event: TouchEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										for (touch in event.changedTouches) {
							 | 
						|||
| 
								 | 
							
											var id = touch.identifier;
							 | 
						|||
| 
								 | 
							
											if (ios)
							 | 
						|||
| 
								 | 
							
												id = iosTouchs.indexOf(id);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											setTouchXY(touch);
							 | 
						|||
| 
								 | 
							
											mouse.sendUpEvent(0, 0, touchX, touchY);
							 | 
						|||
| 
								 | 
							
											surface.sendTouchEndEvent(id, touchX, touchY);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										iosTouchs = [];
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function onBlur() {
							 | 
						|||
| 
								 | 
							
										// System.pause();
							 | 
						|||
| 
								 | 
							
										System.background();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function onFocus() {
							 | 
						|||
| 
								 | 
							
										// System.resume();
							 | 
						|||
| 
								 | 
							
										System.foreground();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function keycodeToChar(key: String, keycode: Int, shift: Bool): String {
							 | 
						|||
| 
								 | 
							
										if (key != null) {
							 | 
						|||
| 
								 | 
							
											if (key.length == 1)
							 | 
						|||
| 
								 | 
							
												return key;
							 | 
						|||
| 
								 | 
							
											switch (key) {
							 | 
						|||
| 
								 | 
							
												case "Add":
							 | 
						|||
| 
								 | 
							
													return "+";
							 | 
						|||
| 
								 | 
							
												case "Subtract":
							 | 
						|||
| 
								 | 
							
													return "-";
							 | 
						|||
| 
								 | 
							
												case "Multiply":
							 | 
						|||
| 
								 | 
							
													return "*";
							 | 
						|||
| 
								 | 
							
												case "Divide":
							 | 
						|||
| 
								 | 
							
													return "/";
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										switch (keycode) {
							 | 
						|||
| 
								 | 
							
											case 187:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "*";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "+";
							 | 
						|||
| 
								 | 
							
											case 188:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return ";";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return ",";
							 | 
						|||
| 
								 | 
							
											case 189:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "_";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "-";
							 | 
						|||
| 
								 | 
							
											case 190:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return ":";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return ".";
							 | 
						|||
| 
								 | 
							
											case 191:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "'";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "#";
							 | 
						|||
| 
								 | 
							
											case 226:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return ">";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "<";
							 | 
						|||
| 
								 | 
							
											case 106:
							 | 
						|||
| 
								 | 
							
												return "*";
							 | 
						|||
| 
								 | 
							
											case 107:
							 | 
						|||
| 
								 | 
							
												return "+";
							 | 
						|||
| 
								 | 
							
											case 109:
							 | 
						|||
| 
								 | 
							
												return "-";
							 | 
						|||
| 
								 | 
							
											case 111:
							 | 
						|||
| 
								 | 
							
												return "/";
							 | 
						|||
| 
								 | 
							
											case 49:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "!";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "1";
							 | 
						|||
| 
								 | 
							
											case 50:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "\"";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "2";
							 | 
						|||
| 
								 | 
							
											case 51:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "§";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "3";
							 | 
						|||
| 
								 | 
							
											case 52:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "$";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "4";
							 | 
						|||
| 
								 | 
							
											case 53:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "%";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "5";
							 | 
						|||
| 
								 | 
							
											case 54:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "&";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "6";
							 | 
						|||
| 
								 | 
							
											case 55:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "/";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "7";
							 | 
						|||
| 
								 | 
							
											case 56:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "(";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "8";
							 | 
						|||
| 
								 | 
							
											case 57:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return ")";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "9";
							 | 
						|||
| 
								 | 
							
											case 48:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "=";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "0";
							 | 
						|||
| 
								 | 
							
											case 219:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "?";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "ß";
							 | 
						|||
| 
								 | 
							
											case 212:
							 | 
						|||
| 
								 | 
							
												if (shift)
							 | 
						|||
| 
								 | 
							
													return "`";
							 | 
						|||
| 
								 | 
							
												else
							 | 
						|||
| 
								 | 
							
													return "´";
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										if (keycode >= 96 && keycode <= 105) { // num block
							 | 
						|||
| 
								 | 
							
											return String.fromCharCode("0".code - 96 + keycode);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										if (keycode >= "A".code && keycode <= "Z".code) {
							 | 
						|||
| 
								 | 
							
											if (shift)
							 | 
						|||
| 
								 | 
							
												return String.fromCharCode(keycode);
							 | 
						|||
| 
								 | 
							
											else
							 | 
						|||
| 
								 | 
							
												return String.fromCharCode(keycode - "A".code + "a".code);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return String.fromCharCode(keycode);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function keyDown(event: KeyboardEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = event;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										preventDefaultKeyBehavior(event);
							 | 
						|||
| 
								 | 
							
										event.stopPropagation();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// prevent key repeat
							 | 
						|||
| 
								 | 
							
										if (event.repeat) {
							 | 
						|||
| 
								 | 
							
											event.preventDefault();
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										var keyCode = fixedKeyCode(event);
							 | 
						|||
| 
								 | 
							
										keyboard.sendDownEvent(keyCode);
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function fixedKeyCode(event: KeyboardEvent): KeyCode {
							 | 
						|||
| 
								 | 
							
										return switch (event.keyCode) {
							 | 
						|||
| 
								 | 
							
											case 91, 93: Meta; // left/right in Chrome
							 | 
						|||
| 
								 | 
							
											case 186: Semicolon;
							 | 
						|||
| 
								 | 
							
											case 187: Equals;
							 | 
						|||
| 
								 | 
							
											case 189: HyphenMinus;
							 | 
						|||
| 
								 | 
							
											default:
							 | 
						|||
| 
								 | 
							
												cast event.keyCode;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function preventDefaultKeyBehavior(event: KeyboardEvent): Void {
							 | 
						|||
| 
								 | 
							
										switch (Keyboard.keyBehavior) {
							 | 
						|||
| 
								 | 
							
											case Default:
							 | 
						|||
| 
								 | 
							
												defaultKeyBlock(event);
							 | 
						|||
| 
								 | 
							
											case Full:
							 | 
						|||
| 
								 | 
							
												event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case Custom(func):
							 | 
						|||
| 
								 | 
							
												if (func(cast event.keyCode))
							 | 
						|||
| 
								 | 
							
													event.preventDefault();
							 | 
						|||
| 
								 | 
							
											case None:
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function defaultKeyBlock(e: KeyboardEvent): Void {
							 | 
						|||
| 
								 | 
							
										// block if ctrl key pressed
							 | 
						|||
| 
								 | 
							
										if (e.ctrlKey || e.metaKey) {
							 | 
						|||
| 
								 | 
							
											// except for cut-copy-paste
							 | 
						|||
| 
								 | 
							
											if (e.keyCode == 67 || e.keyCode == 88 || e.keyCode == 86) {
							 | 
						|||
| 
								 | 
							
												return;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											// and quit on macOS
							 | 
						|||
| 
								 | 
							
											if (e.metaKey && e.keyCode == 81) {
							 | 
						|||
| 
								 | 
							
												return;
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											e.preventDefault();
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										// allow F-keys
							 | 
						|||
| 
								 | 
							
										if (e.keyCode >= 112 && e.keyCode <= 123)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										// allow char keys
							 | 
						|||
| 
								 | 
							
										if (e.key == null || e.key.length == 1)
							 | 
						|||
| 
								 | 
							
											return;
							 | 
						|||
| 
								 | 
							
										e.preventDefault();
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function keyUp(event: KeyboardEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = event;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										preventDefaultKeyBehavior(event);
							 | 
						|||
| 
								 | 
							
										event.stopPropagation();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var keyCode = fixedKeyCode(event);
							 | 
						|||
| 
								 | 
							
										keyboard.sendUpEvent(keyCode);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function keyPress(event: KeyboardEvent): Void {
							 | 
						|||
| 
								 | 
							
										insideInputEvent = true;
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = event;
							 | 
						|||
| 
								 | 
							
										unlockSound();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (event.which == 0)
							 | 
						|||
| 
								 | 
							
											return; // for Firefox and Safari
							 | 
						|||
| 
								 | 
							
										preventDefaultKeyBehavior(event);
							 | 
						|||
| 
								 | 
							
										event.stopPropagation();
							 | 
						|||
| 
								 | 
							
										keyboard.sendPressEvent(String.fromCharCode(event.which));
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										activeKeyEvent = null;
							 | 
						|||
| 
								 | 
							
										insideInputEvent = false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function canSwitchFullscreen(): Bool {
							 | 
						|||
| 
								 | 
							
										return Syntax.code("'fullscreenElement ' in document ||
							 | 
						|||
| 
								 | 
							
										'mozFullScreenElement' in document ||
							 | 
						|||
| 
								 | 
							
										'webkitFullscreenElement' in document ||
							 | 
						|||
| 
								 | 
							
										'msFullscreenElement' in document
							 | 
						|||
| 
								 | 
							
										");
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("fullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("mozfullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("webkitfullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("MSFullscreenChange", func, false);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("fullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("mozfullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("webkitfullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.addEventListener("MSFullscreenError", error, false);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("fullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("mozfullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("webkitfullscreenchange", func, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("MSFullscreenChange", func, false);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("fullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("mozfullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("webkitfullscreenerror", error, false);
							 | 
						|||
| 
								 | 
							
										js.Browser.document.removeEventListener("MSFullscreenError", error, false);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function setKeepScreenOn(on: Bool): Void {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function loadUrl(url: String): Void {
							 | 
						|||
| 
								 | 
							
										js.Browser.window.open(url, "_blank");
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getGamepadId(index: Int): String {
							 | 
						|||
| 
								 | 
							
										var sysGamepads = getGamepads();
							 | 
						|||
| 
								 | 
							
										if (sysGamepads != null && untyped sysGamepads[index]) {
							 | 
						|||
| 
								 | 
							
											return sysGamepads[index].id;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										return "unknown";
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getGamepadVendor(index: Int): String {
							 | 
						|||
| 
								 | 
							
										return "unknown";
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float) {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									static function getGamepads(): Array<js.html.Gamepad> {
							 | 
						|||
| 
								 | 
							
										if (chrome && kha.vr.VrInterface.instance != null && kha.vr.VrInterface.instance.IsVrEnabled()) {
							 | 
						|||
| 
								 | 
							
											return null; // Chrome crashes if navigator.getGamepads() is called when using VR
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										if (untyped navigator.getGamepads) {
							 | 
						|||
| 
								 | 
							
											return js.Browser.navigator.getGamepads();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else {
							 | 
						|||
| 
								 | 
							
											return null;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function getPen(num: Int): kha.input.Pen {
							 | 
						|||
| 
								 | 
							
										return null;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function safeZone(): Float {
							 | 
						|||
| 
								 | 
							
										return 1.0;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function login(): Void {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function automaticSafeZone(): Bool {
							 | 
						|||
| 
								 | 
							
										return true;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function setSafeZone(value: Float): Void {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function unlockAchievement(id: Int): Void {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function waitingForLogin(): Bool {
							 | 
						|||
| 
								 | 
							
										return false;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function disallowUserChange(): Void {}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public static function allowUserChange(): Void {}
							 | 
						|||
| 
								 | 
							
								}
							 |