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(){
|
||||
return null;
|
||||
return new RectF();
|
||||
}
|
||||
|
||||
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
|
||||
public RectF getSafeInsets( int level ) {
|
||||
RectF insets = new RectF();
|
||||
@@ -90,6 +119,7 @@ public class AndroidPlatformSupport extends PlatformSupport {
|
||||
boolean largeCutout = false;
|
||||
int screenSize = Game.width * Game.height;
|
||||
for (Rect r : cutout.getBoundingRects()){
|
||||
//use abs as some cutouts can apparently be returned inverted
|
||||
int cutoutSize = Math.abs(r.height() * r.width());
|
||||
//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
|
||||
|
||||
@@ -140,6 +140,7 @@ import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
import com.watabou.noosa.tweeners.Tweener;
|
||||
import com.watabou.utils.Callback;
|
||||
import com.watabou.utils.DeviceCompat;
|
||||
import com.watabou.utils.GameMath;
|
||||
import com.watabou.utils.PlatformSupport;
|
||||
import com.watabou.utils.Point;
|
||||
@@ -234,7 +235,8 @@ public class GameScene extends PixelScene {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -368,32 +370,52 @@ public class GameScene extends PixelScene {
|
||||
|
||||
menu = new MenuPane();
|
||||
menu.camera = uiCamera;
|
||||
menu.setPos( uiCamera.width-MenuPane.WIDTH-insets.right, insets.top);
|
||||
menu.setPos( uiCamera.width-MenuPane.WIDTH-insets.right, largeInsetTop);
|
||||
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?
|
||||
|
||||
//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.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);
|
||||
|
||||
if (uiSize < 2 && insets.top > 0) {
|
||||
SkinnedBlock bar = new SkinnedBlock(uiCamera.width, insets.top, TextureCache.createSolid(0xFF1C1E18));
|
||||
if (uiSize < 2 && largeInsetTop != 0) {
|
||||
SkinnedBlock bar = new SkinnedBlock(uiCamera.width, largeInsetTop, TextureCache.createSolid(0xFF1C1E18));
|
||||
bar.camera = uiCamera;
|
||||
add(bar);
|
||||
|
||||
PointerArea blocker = new PointerArea(0, 0, uiCamera.width, insets.top);
|
||||
PointerArea blocker = new PointerArea(0, 0, uiCamera.width, largeInsetTop);
|
||||
blocker.camera = uiCamera;
|
||||
add(blocker);
|
||||
}
|
||||
|
||||
boss = new BossHealthBar();
|
||||
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);
|
||||
|
||||
resume = new ResumeIndicator();
|
||||
|
||||
@@ -78,6 +78,9 @@ public class StatusPane extends Component {
|
||||
|
||||
private boolean large;
|
||||
|
||||
//lower the buff indicator to avoid larger cutouts (e.g. iPhone dynamic island)
|
||||
public static float cutoutOffset;
|
||||
|
||||
public StatusPane( boolean large ){
|
||||
super();
|
||||
|
||||
@@ -229,7 +232,7 @@ public class StatusPane extends Component {
|
||||
|
||||
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.y = y + 37;
|
||||
|
||||
Reference in New Issue
Block a user