LNXSDK/Kha/Backends/Java/kha/SystemImpl.hx

468 lines
13 KiB
Haxe
Raw Permalink Normal View History

2025-01-22 16:18:30 +01:00
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<Class<Dynamic>> = 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<Object> = 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<Bool>;
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<WindowOptions>, 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) {}
}