Fetched repo updates and use a newer gdx-teavm version

This commit is contained in:
2025-09-14 17:10:52 +03:00
360 changed files with 18615 additions and 5308 deletions

View File

@@ -30,7 +30,6 @@ import com.badlogic.gdx.controllers.ControllerMapping;
import com.badlogic.gdx.controllers.Controllers;
import com.watabou.noosa.Game;
import com.watabou.noosa.ui.Cursor;
import com.watabou.utils.DeviceCompat;
import com.watabou.utils.PointF;
public class ControllerHandler implements ControllerListener {
@@ -65,9 +64,7 @@ public class ControllerHandler implements ControllerListener {
private static boolean failedInit = false;
public static boolean controllersSupported() {
if (DeviceCompat.isAndroid() && Gdx.app.getVersion() < 16) {
return false;
} else if (failedInit) {
if (failedInit) {
return false;
} else if (initialized){
return true;

View File

@@ -33,36 +33,7 @@ public class InputHandler extends InputAdapter {
private InputMultiplexer multiplexer;
public InputHandler( Input input ){
//An input multiplexer, with additional coord tweaks for power saver mode
multiplexer = new InputMultiplexer(){
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenX /= (Game.dispWidth / (float)Game.width);
screenY /= (Game.dispHeight / (float)Game.height);
return super.touchDown(screenX, screenY, pointer, button);
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
screenX /= (Game.dispWidth / (float)Game.width);
screenY /= (Game.dispHeight / (float)Game.height);
return super.touchDragged(screenX, screenY, pointer);
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
screenX /= (Game.dispWidth / (float)Game.width);
screenY /= (Game.dispHeight / (float)Game.height);
return super.touchUp(screenX, screenY, pointer, button);
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
screenX /= (Game.dispWidth / (float)Game.width);
screenY /= (Game.dispHeight / (float)Game.height);
return super.mouseMoved(screenX, screenY);
}
};
multiplexer = new InputMultiplexer();
input.setInputProcessor(multiplexer);
addInputProcessor(this);
input.setCatchKey( Input.Keys.BACK, true);

View File

@@ -183,7 +183,7 @@ public class PointerEvent {
}
if (clearKeyboardThisPress){
//most press events should clear the keyboard
Game.platform.setOnscreenKeyboardVisible(false);
Game.platform.setOnscreenKeyboardVisible(false, false);
}
}
pointerEvents.clear();

View File

@@ -177,7 +177,7 @@ public class Camera extends Gizmo {
float deadX = 0;
float deadY = 0;
if (followTarget != null){
if (followTarget != null && followTarget.visible){
//manually assign here to avoid an allocation from sprite.center()
panTarget.x = followTarget.x + followTarget.width()/2;
panTarget.y = followTarget.y + followTarget.height()/2;

View File

@@ -21,7 +21,6 @@
package com.watabou.noosa;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.controllers.Controllers;
@@ -46,18 +45,11 @@ import java.io.StringWriter;
public class Game implements ApplicationListener {
public static Game instance;
//actual size of the display
public static int dispWidth;
public static int dispHeight;
// Size of the EGL surface view
public static int width;
public static int height;
//number of pixels from bottom of view before rendering starts
public static int bottomInset;
// Density: mdpi=1, hdpi=1.5, xhdpi=2...
public static float density = 1;
@@ -93,13 +85,12 @@ public class Game implements ApplicationListener {
@Override
public void create() {
dispHeight = Gdx.graphics.getDisplayMode().height;
dispWidth = Gdx.graphics.getDisplayMode().width;
density = Gdx.graphics.getDensity();
if (density == Float.POSITIVE_INFINITY){
density = 100f / 160f; //assume 100PPI if density can't be found
} else if (DeviceCompat.isDesktop()) {
int dispWidth = Gdx.graphics.getDisplayMode().width;
int dispHeight = Gdx.graphics.getDisplayMode().height;
float reportedWidth = dispWidth / Gdx.graphics.getPpiX();
float reportedHeight = dispHeight / Gdx.graphics.getPpiY();
@@ -142,18 +133,11 @@ public class Game implements ApplicationListener {
Vertexbuffer.reload();
}
height -= bottomInset;
if (height != Game.height || width != Game.width) {
Game.width = width;
Game.height = height;
//TODO might be better to put this in platform support
if (Gdx.app.getType() != Application.ApplicationType.Android){
Game.dispWidth = Game.width;
Game.dispHeight = Game.height;
}
resetScene();
}
}
@@ -283,7 +267,9 @@ public class Game implements ApplicationListener {
}
protected void update() {
Game.elapsed = Game.timeScale * Gdx.graphics.getDeltaTime();
//game will not process more than 200ms of graphics time per frame
float frameDelta = Math.min(0.2f, Gdx.graphics.getDeltaTime());
Game.elapsed = Game.timeScale * frameDelta;
Game.timeTotal += Game.elapsed;
Game.realTime = TimeUtils.millis();

View File

@@ -63,9 +63,11 @@ public class MovieClip extends Image {
while (frameTimer > curAnim.delay) {
frameTimer -= curAnim.delay;
if (curFrame >= curAnim.frames.length - 1) {
curFrame = curAnim.frames.length - 1;
if (curAnim.looped) {
curFrame = 0;
} else {
curFrame = curAnim.frames.length - 1;
frameTimer = 0;
}
finished = true;
if (listener != null) {

View File

@@ -29,6 +29,7 @@ import com.watabou.glwrap.Attribute;
import com.watabou.glwrap.Quad;
import com.watabou.glwrap.Uniform;
import com.watabou.glwrap.Vertexbuffer;
import com.watabou.utils.DeviceCompat;
import java.nio.Buffer;
import java.nio.FloatBuffer;
@@ -213,12 +214,12 @@ public class NoosaScript extends Script {
//This fixes pixel scaling issues on some hidpi displays (mainly on macOS)
// because for some reason all other openGL operations work on virtual pixels
// but glScissor operations work on real pixels
float xScale = (Gdx.graphics.getBackBufferWidth() / (float)Game.width );
float yScale = ((Gdx.graphics.getBackBufferHeight()-Game.bottomInset) / (float)Game.height );
float xScale = DeviceCompat.getRealPixelScaleX();
float yScale = DeviceCompat.getRealPixelScaleY();
activeGL.glScissor(
Math.round(camera.x * xScale),
Math.round((Game.height - camera.screenHeight - camera.y) * yScale) + Game.bottomInset,
Math.round((Game.height - camera.screenHeight - camera.y) * yScale),
Math.round(camera.screenWidth * xScale),
Math.round(camera.screenHeight * yScale));
} else {

View File

@@ -23,8 +23,10 @@ package com.watabou.noosa;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Container;
@@ -62,8 +64,11 @@ public class TextInput extends Component {
//use a custom viewport here to ensure stage camera matches game camera
Viewport viewport = new Viewport() {};
viewport.setWorldSize(Game.width, Game.height);
viewport.setScreenBounds(0, Game.bottomInset, Game.width, Game.height);
viewport.setScreenBounds(0, 0, Game.width, Game.height);
viewport.setCamera(new OrthographicCamera());
//TODO this is needed for the moment as Spritebatch switched to using VAOs in libGDX v1.13.1
// This results in HARD crashes atm, whereas old vertex arrays work fine
SpriteBatch.overrideVertexType = Mesh.VertexDataType.VertexArray;
stage = new Stage(viewport);
Game.inputHandler.addInputProcessor(stage);
@@ -136,13 +141,13 @@ public class TextInput extends Component {
textField.setOnscreenKeyboard(new TextField.OnscreenKeyboard() {
@Override
public void show(boolean visible) {
Game.platform.setOnscreenKeyboardVisible(visible);
Game.platform.setOnscreenKeyboardVisible(visible, multiline);
}
});
container.setActor(textField);
stage.setKeyboardFocus(textField);
Game.platform.setOnscreenKeyboardVisible(true);
Game.platform.setOnscreenKeyboardVisible(true, multiline);
}
public void enterPressed(){
@@ -253,7 +258,7 @@ public class TextInput extends Component {
stage.dispose();
skin.dispose();
Game.inputHandler.removeInputProcessor(stage);
Game.platform.setOnscreenKeyboardVisible(false);
Game.platform.setOnscreenKeyboardVisible(false, false);
if (!DeviceCompat.isDesktop()) Game.platform.updateSystemUI();
}
}

View File

@@ -90,6 +90,26 @@ public class TextureFilm {
}
}
}
//creates a film for a texture with known size without needing to reference it
public TextureFilm( int txWidth, int txHeight, int width, int height){
texWidth = txWidth;
texHeight = txHeight;
float uw = (float)width / texWidth;
float vh = (float)height / texHeight;
int cols = texWidth / width;
int rows = texHeight / height;
for (int i=0; i < rows; i++) {
for (int j=0; j < cols; j++) {
RectF rect = new RectF( j * uw, i * vh, (j+1) * uw, (i+1) * vh );
add( i * cols + j, rect );
}
}
}
public void add( Object id, RectF rect ) {
frames.put( id, rect );

View File

@@ -24,7 +24,6 @@ package com.watabou.noosa.audio;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.watabou.noosa.Game;
import com.watabou.utils.Callback;
import java.util.HashMap;
import java.util.HashSet;
@@ -62,44 +61,30 @@ public enum Sample {
}
}
private static LinkedList<String> loadingQueue = new LinkedList<>();
public synchronized void load( final String... assets ) {
for (String asset : assets){
if (!ids.containsKey(asset) && !loadingQueue.contains(asset)){
loadingQueue.add(asset);
public synchronized void load( final String asset){
if (asset != null) {
try {
Sound newSound = Gdx.audio.newSound(Gdx.files.internal(asset));
ids.put(asset, newSound);
} catch (Exception e){
Game.reportException(e);
}
}
//cancel if all assets are already loaded
if (loadingQueue.isEmpty()) return;
//load one at a time on the UI thread to prevent this blocking the UI
//yes this may cause hitching, but only in the first couple seconds of game runtime
Game.runOnRenderThread(loadingCallback);
}
private Callback loadingCallback = new Callback() {
@Override
public void call() {
synchronized (INSTANCE) {
String asset = loadingQueue.poll();
if (asset != null) {
try {
Sound newSound = Gdx.audio.newSound(Gdx.files.internal(asset));
ids.put(asset, newSound);
} catch (Exception e){
Game.reportException(e);
}
}
if (!loadingQueue.isEmpty()){
Game.runOnRenderThread(this);
private static final LinkedList<String> loadingQueue = new LinkedList<>();
//queues multiple assets for loading, which happens in update()
// this prevents blocking while we load many assets
public void load( final String[] assets ) {
synchronized (loadingQueue) {
for (String asset : assets) {
if (!ids.containsKey(asset) && !loadingQueue.contains(asset)) {
loadingQueue.add(asset);
}
}
}
};
}
public synchronized void unload( Object src ) {
if (ids.containsKey( src )) {
@@ -170,6 +155,12 @@ public enum Sample {
}
public void update(){
synchronized (loadingQueue) {
if (!loadingQueue.isEmpty()) {
load(loadingQueue.poll());
}
}
synchronized (delayedSFX) {
if (delayedSFX.isEmpty()) return;
for (DelayedSoundEffect sfx : delayedSFX.toArray(new DelayedSoundEffect[0])) {

View File

@@ -29,20 +29,6 @@ import com.badlogic.gdx.Application;
//TODO migrate to platformSupport class
public class DeviceCompat {
public static boolean supportsFullScreen(){
switch (Gdx.app.getType()){
case Android:
//Android 4.4+ supports hiding UI via immersive mode
return Gdx.app.getVersion() >= 19;
case iOS:
//iOS supports hiding UI via drawing into the gesture safe area
return Gdx.graphics.getSafeInsetBottom() != 0;
default:
//TODO implement functionality for other platforms here
return true;
}
}
//return APi level on Android, major OS version on iOS, 0 on desktop
public static int getPlatformVersion(){
@@ -80,13 +66,15 @@ public class DeviceCompat {
Gdx.app.log( tag, message );
}
public static RectF getSafeInsets(){
RectF result = new RectF();
result.left = Gdx.graphics.getSafeInsetLeft();
result.top = Gdx.graphics.getSafeInsetTop();
result.right = Gdx.graphics.getSafeInsetRight();
result.bottom = Gdx.graphics.getSafeInsetBottom();
return result;
//some devices (macOS mainly) report virtual pixels to Shattered, but sometimes we want real pixel precision
//this returns the number of real pixels per virtual pixel in the X dimension...
public static float getRealPixelScaleX(){
return (Gdx.graphics.getBackBufferWidth() / (float)Game.width );
}
//...and in the Y dimension
public static float getRealPixelScaleY(){
return (Gdx.graphics.getBackBufferHeight() / (float)Game.height );
}
}

View File

@@ -22,6 +22,7 @@
package com.watabou.utils;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.PixmapPacker;
@@ -34,6 +35,28 @@ import java.util.HashMap;
public abstract class PlatformSupport {
public abstract void updateDisplaySize();
public boolean supportsFullScreen(){
return true; //default
}
public static final int INSET_ALL = 3; //All insets, from hole punches to nav bars
public static final int INSET_LRG = 2; //Only big insets, full size notches and nav bars
public static final int INSET_BLK = 1; //only complete blocker assets like navbars
public RectF getSafeInsets( int level ){
return new RectF(
Gdx.graphics.getSafeInsetLeft(),
Gdx.graphics.getSafeInsetTop(),
Gdx.graphics.getSafeInsetRight(),
Gdx.graphics.getSafeInsetBottom()
);
}
//returns a display cutout (if one is present) in device pixels, or null is none is present
public RectF getDisplayCutout(){
return null;
}
public abstract void updateSystemUI();
@@ -57,8 +80,9 @@ public abstract class PlatformSupport {
return Gdx.net.openURI( uri );
}
public void setOnscreenKeyboardVisible(boolean value){
Gdx.input.setOnscreenKeyboardVisible(value);
public void setOnscreenKeyboardVisible(boolean value, boolean multiline){
//by default ignore multiline
Gdx.input.setOnscreenKeyboardVisible(value, Input.OnscreenKeyboardType.Default);
}
//TODO should consider spinning this into its own class, rather than platform support getting ever bigger