Better Android keyboard support

This commit is contained in:
Anuken 2019-09-21 15:35:59 -04:00
parent 1957b6aa12
commit 0d25d83651
10 changed files with 78 additions and 59 deletions

View File

@ -200,7 +200,7 @@ project(":core"){
} }
dependencies{ dependencies{
if(System.properties["user.name"] == "anuke2"){ if(System.properties["user.name"] == "anuke"){
task cleanGen{ task cleanGen{
doFirst{ doFirst{
delete{ delete{
@ -270,7 +270,6 @@ project(":tools"){
dependencies{ dependencies{
compile project(":core") compile project(":core")
//for render tests
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"

View File

@ -535,6 +535,7 @@ setting.antialias.name = Antialias[lightgray] (requires restart)[]
setting.indicators.name = Enemy/Ally Indicators setting.indicators.name = Enemy/Ally Indicators
setting.autotarget.name = Auto-Target setting.autotarget.name = Auto-Target
setting.keyboard.name = Mouse+Keyboard Controls setting.keyboard.name = Mouse+Keyboard Controls
setting.touchscreen.name = Touchscreen Controls
setting.fpscap.name = Max FPS setting.fpscap.name = Max FPS
setting.fpscap.none = None setting.fpscap.none = None
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS

View File

@ -204,9 +204,16 @@ public class Control implements ApplicationListener, Loadable{
player.add(); player.add();
} }
Events.on(ClientLoadEvent.class, e -> { Events.on(ClientLoadEvent.class, e -> input.add());
Core.input.addProcessor(input); }
});
public void setInput(InputHandler newInput){
boolean added = Core.input.getInputProcessors().contains(input);
input.remove();
this.input = newInput;
if(added){
newInput.add();
}
} }
public void playMap(Map map, Rules rules){ public void playMap(Map map, Rules rules){
@ -379,7 +386,7 @@ public class Control implements ApplicationListener, Loadable{
//update and load any requested assets //update and load any requested assets
assets.update(); assets.update();
input.updateController(); input.updateState();
//autosave global data if it's modified //autosave global data if it's modified
data.checkSave(); data.checkSave();

View File

@ -22,6 +22,7 @@ import io.anuke.mindustry.entities.type.EffectEntity;
import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.*; import io.anuke.mindustry.world.blocks.defense.ForceProjector.*;
@ -128,7 +129,7 @@ public class Renderer implements ApplicationListener{
}else{ }else{
camera.position.lerpDelta(position, 0.08f); camera.position.lerpDelta(position, 0.08f);
} }
}else if(!mobile || settings.getBool("keyboard")){ }else if(control.input instanceof DesktopInput){
camera.position.lerpDelta(position, 0.08f); camera.position.lerpDelta(position, 0.08f);
} }

View File

@ -567,7 +567,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
data.unlockContent(mech); data.unlockContent(mech);
} }
if(mobile && !Core.settings.getBool("keyboard")){ if(control.input instanceof MobileInput){
updateTouch(); updateTouch();
}else{ }else{
updateKeyboard(); updateKeyboard();
@ -723,50 +723,41 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
//update shooting if not building, not mining and there's ammo left //update shooting if not building, not mining and there's ammo left
if(!isBuilding() && getMineTile() == null){ if(!isBuilding() && getMineTile() == null){
//autofire: mobile only! //autofire
if(mobile){ if(target == null){
if(target == null){ isShooting = false;
isShooting = false; if(Core.settings.getBool("autotarget")){
if(Core.settings.getBool("autotarget")){ target = Units.closestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.derelict, u -> u.getTeam() != Team.derelict);
target = Units.closestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.derelict, u -> u.getTeam() != Team.derelict);
if(mech.canHeal && target == null){ if(mech.canHeal && target == null){
target = Geometry.findClosest(x, y, indexer.getDamaged(Team.sharded)); target = Geometry.findClosest(x, y, indexer.getDamaged(Team.sharded));
if(target != null && dst(target) > getWeapon().bullet.range()){ if(target != null && dst(target) > getWeapon().bullet.range()){
target = null; target = null;
}else if(target != null){ }else if(target != null){
target = ((Tile)target).entity; target = ((Tile)target).entity;
}
}
if(target != null){
setMineTile(null);
} }
} }
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity)target).damaged() && target.getTeam() == team &&
mech.canHeal && dst(target) < getWeapon().bullet.range())){ if(target != null){
//rotate toward and shoot the target setMineTile(null);
if(mech.turnCursor){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
} }
}
Vector2 intercept = Predict.intercept(this, target, getWeapon().bullet.speed); }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity)target).damaged() && target.getTeam() == team &&
mech.canHeal && dst(target) < getWeapon().bullet.range())){
pointerX = intercept.x; //rotate toward and shoot the target
pointerY = intercept.y; if(mech.turnCursor){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
updateShooting();
isShooting = true;
} }
}else if(isShooting()){ Vector2 intercept = Predict.intercept(this, target, getWeapon().bullet.speed);
Vector2 vec = Core.input.mouseWorld(control.input.getMouseX(),
control.input.getMouseY()); pointerX = intercept.x;
pointerX = vec.x; pointerY = intercept.y;
pointerY = vec.y;
updateShooting(); updateShooting();
isShooting = true;
} }
} }
} }

View File

@ -280,7 +280,7 @@ public class DesktopInput extends InputHandler{
} }
@Override @Override
public void updateController(){ public void updateState(){
if(state.is(State.menu)){ if(state.is(State.menu)){
droppingItem = false; droppingItem = false;
mode = none; mode = none;

View File

@ -132,7 +132,7 @@ public abstract class InputHandler implements InputProcessor{
} }
public void updateController(){ public void updateState(){
} }
@ -275,6 +275,10 @@ public abstract class InputHandler implements InputProcessor{
frag.remove(); frag.remove();
} }
public void add(){
Core.input.addProcessor(this);
}
public boolean canShoot(){ public boolean canShoot(){
return block == null && !Core.scene.hasMouse() && !onConfigurable() && !isDroppingItem(); return block == null && !Core.scene.hasMouse() && !onConfigurable() && !isDroppingItem();
} }

View File

@ -36,6 +36,7 @@ public class MobileInput extends InputHandler implements GestureListener{
//gesture data //gesture data
private Vector2 vector = new Vector2(); private Vector2 vector = new Vector2();
private float lastZoom = -1; private float lastZoom = -1;
private GestureDetector detector;
/** Position where the player started dragging a line. */ /** Position where the player started dragging a line. */
private int lineStartX, lineStartY; private int lineStartX, lineStartY;
@ -65,12 +66,6 @@ public class MobileInput extends InputHandler implements GestureListener{
private int prevX, prevY, prevRotation; private int prevX, prevY, prevRotation;
public MobileInput(){
Events.on(ClientLoadEvent.class, e -> {
Core.input.getInputProcessors().add(new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
});
}
//region utility methods //region utility methods
/** Check and assign targets for a specific position. */ /** Check and assign targets for a specific position. */
@ -445,6 +440,20 @@ public class MobileInput extends InputHandler implements GestureListener{
//endregion //endregion
//region input events //region input events
@Override
public void add(){
super.add();
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
}
@Override
public void remove(){
super.remove();
if(detector != null){
Core.input.removeProcessor(detector);
}
}
@Override @Override
public boolean touchDown(int screenX, int screenY, int pointer, KeyCode button){ public boolean touchDown(int screenX, int screenY, int pointer, KeyCode button){
if(state.is(State.menu) || player.isDead()) return false; if(state.is(State.menu) || player.isDead()) return false;

View File

@ -13,13 +13,7 @@ public class ControlsDialog extends KeybindDialog{
setFillParent(true); setFillParent(true);
title.setAlignment(Align.center); title.setAlignment(Align.center);
titleTable.row(); titleTable.row();
titleTable.add(new Image()) titleTable.add(new Image()).growX().height(3f).pad(4f).get().setColor(Pal.accent);
.growX().height(3f).pad(4f).get().setColor(Pal.accent);
if(Vars.mobile){
cont.row();
cont.add("$keybinds.mobile")
.center().growX().wrap().get().setAlignment(Align.center);
}
} }
@Override @Override

View File

@ -17,6 +17,7 @@ import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.gen.*; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.*;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
import static io.anuke.arc.Core.bundle; import static io.anuke.arc.Core.bundle;
@ -202,8 +203,20 @@ public class SettingsMenuDialog extends SettingsDialog{
game.screenshakePref(); game.screenshakePref();
if(mobile){ if(mobile){
game.checkPref("autotarget", true); game.checkPref("autotarget", true);
game.checkPref("keyboard", false); game.checkPref("keyboard", false, val -> control.setInput(val ? new DesktopInput() : new MobileInput()));
if(Core.settings.getBool("keyboard")){
control.setInput(new DesktopInput());
}
} }
//the issue with touchscreen support on desktop is that:
//1) I can't test it
//2) the SDL backend doesn't support multitouch
/*else{
game.checkPref("touchscreen", false, val -> control.setInput(!val ? new DesktopInput() : new MobileInput()));
if(Core.settings.getBool("touchscreen")){
control.setInput(new MobileInput());
}
}*/
game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Core.bundle.format("setting.seconds", i)); game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Core.bundle.format("setting.seconds", i));
if(!mobile){ if(!mobile){