Skip to content

Commit eee682a

Browse files
committed
Fix alt-tab during full screen crash
1 parent f552884 commit eee682a

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

engine/src/main/java/org/destinationsol/game/SolCam.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,15 @@ public Vector2 worldToScreen(SolShip ship) {
323323
distanceDifference.y = .5f - distanceDifference.y;
324324
return distanceDifference;
325325
}
326+
327+
/** @return true if the camera matrix does not have Nan or infinite values */
328+
public boolean isMatrixValid() {
329+
for(float i : myCam.combined.val) {
330+
if(!Float.isFinite(i)) {
331+
return false;
332+
}
333+
}
334+
335+
return true;
336+
}
326337
}

engine/src/main/java/org/destinationsol/game/screens/ShipMixedControl.java

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.destinationsol.assets.Assets;
2525
import org.destinationsol.common.SolMath;
2626
import org.destinationsol.game.Hero;
27+
import org.destinationsol.game.SolCam;
2728
import org.destinationsol.game.SolGame;
2829
import org.destinationsol.game.input.Mover;
2930
import org.destinationsol.game.input.Shooter;
@@ -38,15 +39,15 @@ public class ShipMixedControl implements ShipUiControl {
3839
public final SolUiControl shoot2Ctrl;
3940
public final SolUiControl abilityCtrl;
4041
private final SolUiControl myDownCtrl;
41-
private final Vector2 myMouseWorldPos;
42+
private final Vector2 myMouseScreenPos;
4243
private final TextureAtlas.AtlasRegion myCursor;
4344
private boolean myRight;
4445
private boolean myLeft;
4546

4647
ShipMixedControl(SolApplication solApplication, List<SolUiControl> controls) {
4748
GameOptions gameOptions = solApplication.getOptions();
4849
myCursor = Assets.getAtlasRegion("engine:uiCursorTarget");
49-
myMouseWorldPos = new Vector2();
50+
myMouseScreenPos = new Vector2();
5051
upCtrl = new SolUiControl(null, false, gameOptions.getKeyUpMouse());
5152
controls.add(upCtrl);
5253
myDownCtrl = new SolUiControl(null, false, gameOptions.getKeyDownMouse());
@@ -63,16 +64,19 @@ public class ShipMixedControl implements ShipUiControl {
6364
public void update(SolApplication solApplication, boolean enabled) {
6465
GameOptions gameOptions = solApplication.getOptions();
6566
blur();
66-
if (!enabled) {
67+
SolGame game = solApplication.getGame();
68+
if (!enabled || problemWithProjections(game.getCam())) {
6769
return;
6870
}
6971
SolInputManager im = solApplication.getInputManager();
70-
SolGame game = solApplication.getGame();
7172
Hero hero = game.getHero();
7273
if (hero.isNonTranscendent()) {
73-
myMouseWorldPos.set(Gdx.input.getX(), Gdx.input.getY());
74-
game.getCam().screenToWorld(myMouseWorldPos);
75-
float desiredAngle = SolMath.angle(hero.getPosition(), myMouseWorldPos);
74+
myMouseScreenPos.set(Gdx.input.getX(), Gdx.input.getY());
75+
// project mouse coordinates [0;width] and [0;height] to screen coordinates [0,1], [0,1] by scaling down
76+
myMouseScreenPos.scl(1.0f / Gdx.graphics.getWidth(), 1.0f / Gdx.graphics.getHeight());
77+
Vector2 shipOnScreen = game.getCam().worldToScreen(hero.getShip()); // unproject hero to screen coordinates
78+
assertHeroAndMouseCoords(myMouseScreenPos, shipOnScreen);
79+
float desiredAngle = SolMath.angle(shipOnScreen, myMouseScreenPos);
7680
Boolean ntt = Mover.needsToTurn(hero.getAngle(), desiredAngle, hero.getRotationSpeed(), hero.getRotationAcceleration(), Shooter.MIN_SHOOT_AAD);
7781
if (ntt != null) {
7882
if (ntt) {
@@ -95,6 +99,33 @@ public void update(SolApplication solApplication, boolean enabled) {
9599
}
96100
}
97101

102+
/**
103+
* When alt+tabbing in full screen mode, the client area can become 0 with/height, and when alt+tabbing back,
104+
* the camera matrix can contain NaN values for the first frame
105+
* @return true if projections should not be done this update
106+
*/
107+
private boolean problemWithProjections(SolCam camera) {
108+
return Gdx.graphics.getWidth() == 0 || Gdx.graphics.getHeight() == 0 ||
109+
camera.getViewWidth() <= 0.f || camera.getViewHeight() <= 0.f || !camera.isMatrixValid();
110+
}
111+
112+
/**
113+
* Assert that the following vectors do not contain NaN or infinite values
114+
* @param mouseCoords mouse coordinates in [0;1] screen space
115+
* @param heroCoords hero coordinates projected to [0;1] screen space
116+
*/
117+
private void assertHeroAndMouseCoords(Vector2 mouseCoords, Vector2 heroCoords) {
118+
if(Double.isNaN(mouseCoords.x) || Double.isNaN(mouseCoords.y)) {
119+
System.err.println("Screen size: " + Gdx.graphics.getWidth() + " " + Gdx.graphics.getHeight());
120+
throw new RuntimeException("Mouse coordinates are not valid: " + mouseCoords.x + " " + mouseCoords.y);
121+
}
122+
123+
if(Double.isNaN(heroCoords.x) || Double.isNaN(heroCoords.y)) {
124+
System.err.println("Screen size: " + Gdx.graphics.getWidth() + " " + Gdx.graphics.getHeight());
125+
throw new RuntimeException("Hero coordinates are not valid: " + heroCoords.x + " " + heroCoords.y);
126+
}
127+
}
128+
98129
@Override
99130
public boolean isLeft() {
100131
return myLeft;

0 commit comments

Comments
 (0)