v3.2.4: added support for 'medium' display cutouts like dynamic island
This commit is contained in:
@@ -53,9 +53,9 @@ public abstract class PlatformSupport {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns a display cutout (if one is present) in device pixels, or null is none is present
|
//returns a display cutout (if one is present) in device pixels, or empty if none is present
|
||||||
public RectF getDisplayCutout(){
|
public RectF getDisplayCutout(){
|
||||||
return null;
|
return new RectF();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void updateSystemUI();
|
public abstract void updateSystemUI();
|
||||||
|
|||||||
@@ -66,6 +66,35 @@ public class AndroidPlatformSupport extends PlatformSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RectF getDisplayCutout() {
|
||||||
|
RectF cutoutRect = new RectF();
|
||||||
|
|
||||||
|
//some extra logic here is because cutouts can apparently be returned inverted
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
DisplayCutout cutout = AndroidLauncher.instance.getApplicationWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
|
||||||
|
|
||||||
|
Rect largest = null;
|
||||||
|
if (cutout != null) {
|
||||||
|
for (Rect r : cutout.getBoundingRects()) {
|
||||||
|
if (largest == null
|
||||||
|
|| Math.abs(r.height() * r.width()) > Math.abs(largest.height() * largest.width())) {
|
||||||
|
largest = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (largest != null){
|
||||||
|
cutoutRect.left = Math.min(largest.left, largest.right);
|
||||||
|
cutoutRect.right = Math.max(largest.left, largest.right);
|
||||||
|
cutoutRect.top = Math.min(largest.top, largest.bottom);
|
||||||
|
cutoutRect.bottom = Math.max(largest.top, largest.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cutoutRect;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RectF getSafeInsets( int level ) {
|
public RectF getSafeInsets( int level ) {
|
||||||
RectF insets = new RectF();
|
RectF insets = new RectF();
|
||||||
@@ -90,6 +119,7 @@ public class AndroidPlatformSupport extends PlatformSupport {
|
|||||||
boolean largeCutout = false;
|
boolean largeCutout = false;
|
||||||
int screenSize = Game.width * Game.height;
|
int screenSize = Game.width * Game.height;
|
||||||
for (Rect r : cutout.getBoundingRects()){
|
for (Rect r : cutout.getBoundingRects()){
|
||||||
|
//use abs as some cutouts can apparently be returned inverted
|
||||||
int cutoutSize = Math.abs(r.height() * r.width());
|
int cutoutSize = Math.abs(r.height() * r.width());
|
||||||
//display cutouts are considered large if they take up more than 0.605% of the screen
|
//display cutouts are considered large if they take up more than 0.605% of the screen
|
||||||
//in reality we want less than about 0.5%, but some cutouts over-report their size
|
//in reality we want less than about 0.5%, but some cutouts over-report their size
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ import com.watabou.noosa.audio.Sample;
|
|||||||
import com.watabou.noosa.particles.Emitter;
|
import com.watabou.noosa.particles.Emitter;
|
||||||
import com.watabou.noosa.tweeners.Tweener;
|
import com.watabou.noosa.tweeners.Tweener;
|
||||||
import com.watabou.utils.Callback;
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.DeviceCompat;
|
||||||
import com.watabou.utils.GameMath;
|
import com.watabou.utils.GameMath;
|
||||||
import com.watabou.utils.PlatformSupport;
|
import com.watabou.utils.PlatformSupport;
|
||||||
import com.watabou.utils.Point;
|
import com.watabou.utils.Point;
|
||||||
@@ -234,7 +235,8 @@ public class GameScene extends PixelScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RectF insets = getCommonInsets();
|
RectF insets = getCommonInsets();
|
||||||
insets.top = Game.platform.getSafeInsets(PlatformSupport.INSET_LRG).scale(1f/defaultZoom).top;
|
//we want to check if large is the same as blocking here
|
||||||
|
float largeInsetTop = Game.platform.getSafeInsets(PlatformSupport.INSET_LRG).scale(1f/defaultZoom).top;
|
||||||
|
|
||||||
scene = this;
|
scene = this;
|
||||||
|
|
||||||
@@ -368,32 +370,52 @@ public class GameScene extends PixelScene {
|
|||||||
|
|
||||||
menu = new MenuPane();
|
menu = new MenuPane();
|
||||||
menu.camera = uiCamera;
|
menu.camera = uiCamera;
|
||||||
menu.setPos( uiCamera.width-MenuPane.WIDTH-insets.right, insets.top);
|
menu.setPos( uiCamera.width-MenuPane.WIDTH-insets.right, largeInsetTop);
|
||||||
add(menu);
|
add(menu);
|
||||||
|
|
||||||
//TODO buff indicator and boss HP need to be moved down slightly on iOS devices with dynamic island
|
|
||||||
//TODO buff indicator probably cut off on some Android devices, get display cutout size and check?
|
|
||||||
//TODO need to reject inputs on the bars (just turn then into hotareas?
|
|
||||||
//TODO make top bar transparent and add 1px of top status and menu bar to it?
|
//TODO make top bar transparent and add 1px of top status and menu bar to it?
|
||||||
|
|
||||||
|
//most cutouts supported by the game are small
|
||||||
|
// but some are more 'medium' can can be supported with a little UI offsetting
|
||||||
|
float mediumCutoutOffset = 0;
|
||||||
|
if (largeInsetTop != insets.top){
|
||||||
|
//most notably iOS's Dynamic island, which must exist in this case
|
||||||
|
if (DeviceCompat.isiOS()){
|
||||||
|
//TODO we should handle this logic in platformSupport, not hardcode it here
|
||||||
|
mediumCutoutOffset = 7;
|
||||||
|
} else if (DeviceCompat.isAndroid()) {
|
||||||
|
//some android hole punches can also be big too
|
||||||
|
RectF cutout = Game.platform.getDisplayCutout().scale(1f / defaultZoom);
|
||||||
|
//if the cutout is positioned to obstruct the buff bar
|
||||||
|
//TODO could buff bar just be squished in some cases here?
|
||||||
|
if (cutout.left < 80
|
||||||
|
&& cutout.top < 10
|
||||||
|
&& cutout.right > 32
|
||||||
|
&& cutout.bottom > 11) {
|
||||||
|
mediumCutoutOffset = (int) Math.floor(cutout.bottom - 11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
status = new StatusPane( SPDSettings.interfaceSize() > 0 );
|
status = new StatusPane( SPDSettings.interfaceSize() > 0 );
|
||||||
status.camera = uiCamera;
|
status.camera = uiCamera;
|
||||||
status.setRect(insets.left, uiSize > 0 ? uiCamera.height-39-insets.bottom : insets.top, uiCamera.width - insets.left - insets.right, 0 );
|
StatusPane.cutoutOffset = mediumCutoutOffset;
|
||||||
|
status.setRect(insets.left, uiSize > 0 ? uiCamera.height-39-insets.bottom : largeInsetTop, uiCamera.width - insets.left - insets.right, 0 );
|
||||||
add(status);
|
add(status);
|
||||||
|
|
||||||
if (uiSize < 2 && insets.top > 0) {
|
if (uiSize < 2 && largeInsetTop != 0) {
|
||||||
SkinnedBlock bar = new SkinnedBlock(uiCamera.width, insets.top, TextureCache.createSolid(0xFF1C1E18));
|
SkinnedBlock bar = new SkinnedBlock(uiCamera.width, largeInsetTop, TextureCache.createSolid(0xFF1C1E18));
|
||||||
bar.camera = uiCamera;
|
bar.camera = uiCamera;
|
||||||
add(bar);
|
add(bar);
|
||||||
|
|
||||||
PointerArea blocker = new PointerArea(0, 0, uiCamera.width, insets.top);
|
PointerArea blocker = new PointerArea(0, 0, uiCamera.width, largeInsetTop);
|
||||||
blocker.camera = uiCamera;
|
blocker.camera = uiCamera;
|
||||||
add(blocker);
|
add(blocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
boss = new BossHealthBar();
|
boss = new BossHealthBar();
|
||||||
boss.camera = uiCamera;
|
boss.camera = uiCamera;
|
||||||
boss.setPos( insets.left + 6 + (uiCamera.width - insets.left - insets.right - boss.width())/2, insets.top + 21);
|
boss.setPos( insets.left + 6 + (uiCamera.width - insets.left - insets.right - boss.width())/2, largeInsetTop + 21 + mediumCutoutOffset);
|
||||||
add(boss);
|
add(boss);
|
||||||
|
|
||||||
resume = new ResumeIndicator();
|
resume = new ResumeIndicator();
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ public class StatusPane extends Component {
|
|||||||
|
|
||||||
private boolean large;
|
private boolean large;
|
||||||
|
|
||||||
|
//lower the buff indicator to avoid larger cutouts (e.g. iPhone dynamic island)
|
||||||
|
public static float cutoutOffset;
|
||||||
|
|
||||||
public StatusPane( boolean large ){
|
public StatusPane( boolean large ){
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -229,7 +232,7 @@ public class StatusPane extends Component {
|
|||||||
|
|
||||||
heroInfoOnBar.setRect(heroInfo.right(), y, 50, 9);
|
heroInfoOnBar.setRect(heroInfo.right(), y, 50, 9);
|
||||||
|
|
||||||
buffs.setRect( x + 31, y + 7, 50, 8 );
|
buffs.setRect( x + 31, y + 7 + cutoutOffset, 50, 8 );
|
||||||
|
|
||||||
busy.x = x + 1;
|
busy.x = x + 1;
|
||||||
busy.y = y + 37;
|
busy.y = y + 37;
|
||||||
|
|||||||
Reference in New Issue
Block a user