package com.github.czyzby.kiwi.util.gdx.viewport;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.github.czyzby.kiwi.util.common.UtilitiesClass;
import com.github.czyzby.kiwi.util.gdx.GdxUtilities;
/** Utilities for LibGDX {@link com.badlogic.gdx.utils.viewport.Viewport viewports}.
*
* @author MJ
* @see LetterboxingViewport */
public class Viewports extends UtilitiesClass {
private Viewports() {
}
/** {@link ScreenViewport} is tempting to use - especially for GUIs - as it seems to never scale the assets up or
* down, preserving the desired look. However, as it quickly turns out, it usually does not work so well on mobile
* platforms. Fortunately, it provides {@link ScreenViewport#setUnitsPerPixel(float)} method, which allows to apply
* the appropriate scaling thanks to {@link com.badlogic.gdx.Graphics#getDensity() density} usage. This method tries
* to choose the correct scaling, depending on the platform.
*
* @return a new {@link ScreenViewport} with its unit per pixel ratio adjusted. */
public static ScreenViewport getDensityAwareViewport() {
return setDensityAware(new ScreenViewport());
}
/** {@link ScreenViewport} is tempting to use - especially for GUIs - as it seems to never scale the assets up or
* down, preserving the desired look. However, as it quickly turns out, it usually does not work so well on mobile
* platforms. Fortunately, it provides {@link ScreenViewport#setUnitsPerPixel(float)} method, which allows to apply
* the appropriate scaling thanks to {@link com.badlogic.gdx.Graphics#getDensity() density} usage. This method tries
* to choose the correct scaling, depending on the platform.
*
* @param viewport its unit per pixel ratio will be adjusted.
* @return passed viewport (for chaining). */
public static ScreenViewport setDensityAware(final ScreenViewport viewport) {
final float density = Gdx.graphics.getDensity();
final float unitsPerPixel = GdxUtilities.isMobile() ? 1f / density : 96f / 160f / density;
viewport.setUnitsPerPixel(unitsPerPixel);
return viewport;
}
/** @param stage its viewport will be updated according to current screen size. */
public static void update(final Stage stage) {
final Viewport viewport = stage.getViewport();
update(stage, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),
viewport instanceof ScreenViewport || viewport instanceof LetterboxingViewport);
}
/** @param stage its viewport will be updated according to passed screen size.
* @param width current screen width.
* @param height current screen height. */
public static void update(final Stage stage, final int width, final int height) {
final Viewport viewport = stage.getViewport();
update(stage, width, height, viewport instanceof ScreenViewport || viewport instanceof LetterboxingViewport);
}
/** @param stage its viewport will be updated according to passed screen size.
* @param width current screen width.
* @param height current screen height.
* @param centerCamera whether to center camera or not. As a rule of thumb, if the viewport resizes its world size
* according to the new screen size ({@link ScreenViewport}, {@link LetterboxingViewport}), its camera
* should be centered. Otherwise, pass false. */
public static void update(final Stage stage, final int width, final int height, final boolean centerCamera) {
stage.getViewport().update(width, height, centerCamera);
}
/** @param stage its viewport camera will be extracted.
* @return projection matrix, which can be applied to a batch. */
public static Matrix4 getProjectionMatrix(final Stage stage) {
return getProjectionMatrix(stage.getViewport());
}
/** @param viewport its camera will be extracted.
* @return projection matrix, which can be applied to a batch. */
private static Matrix4 getProjectionMatrix(final Viewport viewport) {
return viewport.getCamera().combined;
}
}