package kha; import kha.System.SystemOptions; import kha.input.Keyboard; import kha.input.KeyCode; import kha.input.Mouse; import kha.java.Graphics; import kha.System; import kha.Window; import java.javax.swing.JFrame; import java.lang.Class; import java.lang.System in Sys; import java.lang.Object; import java.lang.Throwable; import java.NativeArray; @:access(kha.System) class JWindow extends JFrame implements java.awt.event.KeyListener implements java.awt.event.MouseListener implements java.awt.event.MouseMotionListener implements java.awt.event.MouseWheelListener { public var instance: JWindow; var WIDTH: Int; var HEIGHT: Int; var syncrate = 60; var canvas: java.awt.Canvas; var vsynced = false; var reset = false; var framebuffer: kha.Framebuffer; var painter: kha.java.Painter; public static var mouseX: Int; public static var mouseY: Int; public function new() { super(); instance = this; painter = new kha.java.Painter(); framebuffer = new kha.Framebuffer(0, null, painter, null); var g1 = new kha.graphics2.Graphics1(framebuffer); framebuffer.init(g1, painter, null); } public function start(): Void { createGame(); setupWindow(); createVSyncedDoubleBuffer(); mainLoop(); } function setupWindow(): Void { setIgnoreRepaint(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); canvas = new java.awt.Canvas(); canvas.setIgnoreRepaint(true); canvas.setSize(WIDTH, HEIGHT); canvas.setFocusable(false); add(canvas); setResizable(false); pack(); var screen: java.awt.Dimension = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); var x = Std.int((screen.width - WIDTH) / 2); var y = Std.int((screen.height - HEIGHT) / 2); setLocation(x, y); setTitle("Game"); setVisible(true); addKeyListener(this); canvas.addMouseListener(this); canvas.addMouseMotionListener(this); canvas.addMouseWheelListener(this); } function createVSyncedDoubleBuffer(): Void { vsynced = true; canvas.createBufferStrategy(2); var bufferStrategy: java.awt.image.BufferStrategy = canvas.getBufferStrategy(); if (bufferStrategy != null) { var caps: java.awt.BufferCapabilities = bufferStrategy.getCapabilities(); try { // Class var ebcClass = Class.forName("sun.java2d.pipe.hw.ExtendedBufferCapabilities"); var vstClass = Class.forName("sun.java2d.pipe.hw.ExtendedBufferCapabilities$VSyncType"); // java.lang.reflect.Constructor // new Class[] { java.awt.BufferCapabilities.class, vstClass } untyped var _class = untyped __java__("java.awt.BufferCapabilities.class"); var classes: NativeArray> = NativeArray.make(_class, vstClass); var ebcConstructor = ebcClass.getConstructor(classes[0]); var vSyncType: Object = vstClass.getField("VSYNC_ON").get(null); // (java.awt.BufferCapabilities) // new Object[] var objs: NativeArray = NativeArray.make(cast(caps, Object), vSyncType); var newCaps: java.awt.BufferCapabilities = ebcConstructor.newInstance(objs); canvas.createBufferStrategy(2, newCaps); // setCanChangeRefreshRate(false); // setRefreshRate(60); } catch (t:Throwable) { vsynced = false; t.printStackTrace(); canvas.createBufferStrategy(2); } } if (vsynced) checkVSync(); } function checkVSync(): Void { var starttime = Sys.nanoTime(); for (i in 0...3) { canvas.getBufferStrategy().show(); java.awt.Toolkit.getDefaultToolkit().sync(); } var endtime = Sys.nanoTime(); if (endtime - starttime > 1000 * 1000 * 1000 / 60) { vsynced = true; Sys.out.println("VSync enabled."); } else Sys.out.println("VSync not enabled, sorry."); } function mainLoop(): Void { var lasttime = Sys.nanoTime(); while (true) { if (vsynced) update(); else { var time = Sys.nanoTime(); while (time >= lasttime + 1000 * 1000 * 1000 / syncrate) { lasttime += 1000 * 1000 * 1000 / syncrate; update(); } } render(); if (reset) resetGame(); } } function createGame(): Void { WIDTH = System.windowWidth(); HEIGHT = System.windowHeight(); } function resetGame(): Void { reset = false; createGame(); } @:overload function update(): Void { Scheduler.executeFrame(); } function render(): Void { var bf: java.awt.image.BufferStrategy = canvas.getBufferStrategy(); var g: java.awt.Graphics2D = null; try { g = cast bf.getDrawGraphics(); painter.graphics = g; painter.setRenderHint(); System.render([framebuffer]); } catch (e:Any) { trace(e); } g.dispose(); bf.show(); java.awt.Toolkit.getDefaultToolkit().sync(); } @Override public function keyPressed(e: java.awt.event.KeyEvent): Void { // var keyCode: Int = e.getKeyCode(); // switch (keyCode) { // case java.awt.event.KeyEvent.VK_RIGHT: // pressKey(keyCode, KeyCode.RIGHT); // case java.awt.event.KeyEvent.VK_LEFT: // pressKey(keyCode, KeyCode.LEFT); // case java.awt.event.KeyEvent.VK_UP: // pressKey(keyCode, KeyCode.UP); // case java.awt.event.KeyEvent.VK_DOWN: // pressKey(keyCode, KeyCode.DOWN); // case java.awt.event.KeyEvent.VK_SPACE: // pressKey(keyCode, KeyCode.BUTTON_1); // case java.awt.event.KeyEvent.VK_CONTROL: // pressKey(keyCode, KeyCode.BUTTON_2); // case java.awt.event.KeyEvent.VK_ENTER: // //pressKey(keyCode, Key.ENTER); // case java.awt.event.KeyEvent.VK_BACK_SPACE: // //pressKey(keyCode, Key.BACKSPACE); // default: // } } @Override public function keyReleased(e: java.awt.event.KeyEvent): Void { // var keyCode: Int = e.getKeyCode(); // switch (keyCode) { // case java.awt.event.KeyEvent.VK_RIGHT: // releaseKey(keyCode, KeyCode.RIGHT); // case java.awt.event.KeyEvent.VK_LEFT: // releaseKey(keyCode, KeyCode.LEFT); // case java.awt.event.KeyEvent.VK_UP: // releaseKey(keyCode, KeyCode.UP); // case java.awt.event.KeyEvent.VK_DOWN: // releaseKey(keyCode, KeyCode.DOWN); // case java.awt.event.KeyEvent.VK_SPACE: // releaseKey(keyCode, KeyCode.BUTTON_1); // case java.awt.event.KeyEvent.VK_CONTROL: // releaseKey(keyCode, KeyCode.BUTTON_2); // case java.awt.event.KeyEvent.VK_ENTER: // //releaseKey(keyCode, Key.ENTER); // case java.awt.event.KeyEvent.VK_BACK_SPACE: // //releaseKey(keyCode, Key.BACKSPACE); // default: // } } @Override public function keyTyped(e: java.awt.event.KeyEvent): Void { // game.charKey(e.getKeyChar()); } public function getSyncrate(): Int { return syncrate; } @Override public function mouseClicked(arg0: java.awt.event.MouseEvent): Void {} @Override public function mouseEntered(arg0: java.awt.event.MouseEvent): Void {} @Override public function mouseExited(arg0: java.awt.event.MouseEvent): Void {} @Override public function mousePressed(arg0: java.awt.event.MouseEvent): Void { mouseX = arg0.getX(); mouseY = arg0.getY(); // if (javax.swing.SwingUtilities.isLeftMouseButton(arg0)) // game.mouseDown(arg0.getX(), arg0.getY()); // else if (javax.swing.SwingUtilities.isRightMouseButton(arg0)) // game.rightMouseDown(arg0.getX(), arg0.getY()); } @Override public function mouseReleased(arg0: java.awt.event.MouseEvent): Void { mouseX = arg0.getX(); mouseY = arg0.getY(); // if (javax.swing.SwingUtilities.isLeftMouseButton(arg0)) // game.mouseUp(arg0.getX(), arg0.getY()); // else if (javax.swing.SwingUtilities.isRightMouseButton(arg0)) // game.rightMouseUp(arg0.getX(), arg0.getY()); } @Override public function mouseDragged(arg0: java.awt.event.MouseEvent): Void { mouseX = arg0.getX(); mouseY = arg0.getY(); // game.mouseMove(arg0.getPoint().x, arg0.getPoint().y); } @Override public function mouseMoved(arg0: java.awt.event.MouseEvent): Void { mouseX = arg0.getX(); mouseY = arg0.getY(); // if (game != null) game.mouseMove(arg0.getPoint().x, arg0.getPoint().y); } @Override public function mouseWheelMoved(arg0: java.awt.event.MouseWheelEvent): Void { mouseX = arg0.getX(); mouseY = arg0.getY(); // game.mouseWheel(-arg0.getWheelRotation()); //invert } } @:allow(kha.SystemImpl.JWindow) class SystemImpl { public static var graphics(default, null): Graphics; static var keyboard: Keyboard; static var mouse: Mouse; static var keyreleased: Array; public static function init(options: SystemOptions, callback: Window->Void) { init2(); Scheduler.init(); if (options.width != -1) myPixelWidth = options.width; if (options.height != -1) myPixelHeight = options.height; var window = new Window(options.width, options.height); Scheduler.start(); callback(window); var jWindow = new JWindow(); jWindow.start(); } public static function initEx(title: String, options: Array, windowCallback: Int->Void, callback: Window->Void) { init({title: title, width: options[0].width, height: options[0].height}, callback); } static var startTime: Float; public static function init2(): Void { graphics = new Graphics(); startTime = getTimestamp(); mouse = new Mouse(); keyboard = new Keyboard(); keyreleased = [for (i in 0...256) true]; } public static function getKeyboard(num: Int): Keyboard { if (num == 0) return keyboard; else return null; } public static function getMouse(num: Int): Mouse { if (num == 0) return mouse; else return null; } function pressKey(keyCode: Int, button: KeyCode): Void { if (keyreleased[keyCode]) { // avoid auto-repeat keyreleased[keyCode] = false; keyboard.sendDownEvent(button); } } function releaseKey(keyCode: Int, button: KeyCode): Void { keyreleased[keyCode] = true; keyboard.sendUpEvent(button); } public static function getFrequency(): Int { return 1000; } public static function getTimestamp(): Float { return cast java.lang.System.currentTimeMillis(); } public static function getTime(): Float { return (getTimestamp() - startTime) / getFrequency(); } public static function getScreenRotation(): ScreenRotation { return ScreenRotation.RotationNone; } public static function getVsync(): Bool { return true; } public static function getRefreshRate(): Int { return 60; } public static function getSystemId(): String { return "java"; } public static function vibrate(ms: Int): Void {} public static function getLanguage(): String { final lang = java.util.Locale.getDefault().getLanguage(); return lang.substr(0, 2).toLowerCase(); } static var myPixelWidth = 640; static var myPixelHeight = 480; public static function windowWidth(id: Int): Int { return myPixelWidth; } public static function windowHeight(id: Int): Int { return myPixelHeight; } public static function screenDpi(): Int { return 96; } public static function changeResolution(width: Int, height: Int): Void {} public static function requestShutdown(): Bool { return false; } public static function canSwitchFullscreen(): Bool { return false; } public static function isFullscreen(): Bool { return false; } public static function requestFullscreen(): Void {} public static function exitFullscreen(): Void {} public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {} public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {} public function lockMouse(): Void {} public function unlockMouse(): Void {} public function canLockMouse(): Bool { return false; } public function isMouseLocked(): Bool { return false; } public function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {} public function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {} public static function setKeepScreenOn(on: Bool): Void {} public static function loadUrl(url: String): Void {} public static function safeZone(): Float { return 1.0; } public static function waitingForLogin(): Bool { return false; } public static function disallowUserChange(): Void {} public static function allowUserChange(): Void {} 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 getGamepadId(index: Int): String { return "unkown"; } public static function getGamepadVendor(index: Int): String { return "unknown"; } public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float) {} }