Skip to content

Commit

Permalink
Merge 445b741 into 31548c9
Browse files Browse the repository at this point in the history
  • Loading branch information
eonarheim committed Mar 10, 2024
2 parents 31548c9 + 445b741 commit 3b97bf2
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/engine/Engine.ts
Expand Up @@ -7,7 +7,7 @@ import { polyfill } from './Polyfill';
polyfill();
import { CanUpdate, CanDraw, CanInitialize } from './Interfaces/LifecycleEvents';
import { Vector } from './Math/vector';
import { Screen, DisplayMode, ScreenDimension, Resolution } from './Screen';
import { Screen, DisplayMode, Resolution, ViewportDimension } from './Screen';
import { ScreenElement } from './ScreenElement';
import { Actor } from './Actor';
import { Timer } from './Timer';
Expand Down Expand Up @@ -121,13 +121,13 @@ export interface EngineOptions<TKnownScenes extends string = any> {
* Optionally configure the width & height of the viewport in css pixels.
* Use `viewport` instead of [[EngineOptions.width]] and [[EngineOptions.height]], or vice versa.
*/
viewport?: ScreenDimension;
viewport?: ViewportDimension;

/**
* Optionally specify the size the logical pixel resolution, if not specified it will be width x height.
* See [[Resolution]] for common presets.
*/
resolution?: ScreenDimension;
resolution?: Resolution;

/**
* Optionally specify antialiasing (smoothing), by default true (smooth pixels)
Expand Down
4 changes: 2 additions & 2 deletions src/engine/Graphics/Context/ExcaliburGraphicsContext.ts
@@ -1,6 +1,6 @@
import { Vector } from '../../Math/vector';
import { Color } from '../../Color';
import { ScreenDimension } from '../../Screen';
import { Resolution } from '../../Screen';
import { PostProcessor } from '../PostProcessor/PostProcessor';
import { AffineMatrix } from '../../Math/affine-matrix';
import { Material, MaterialOptions } from './material';
Expand Down Expand Up @@ -240,7 +240,7 @@ export interface ExcaliburGraphicsContext {
/**
* Update the context with the current viewport dimensions (used in resizing)
*/
updateViewport(resolution: ScreenDimension): void;
updateViewport(resolution: Resolution): void;

/**
* Access the debug drawing api
Expand Down
Expand Up @@ -11,7 +11,7 @@ import { Color } from '../../Color';
import { StateStack } from './state-stack';
import { GraphicsDiagnostics } from '../GraphicsDiagnostics';
import { DebugText } from './debug-text';
import { ScreenDimension } from '../../Screen';
import { Resolution } from '../../Screen';
import { PostProcessor } from '../PostProcessor/PostProcessor';
import { AffineMatrix } from '../../Math/affine-matrix';
import { Material, MaterialOptions } from './material';
Expand Down Expand Up @@ -154,7 +154,7 @@ export class ExcaliburGraphicsContext2DCanvas implements ExcaliburGraphicsContex
this.__ctx.resetTransform();
}

public updateViewport(_resolution: ScreenDimension): void {
public updateViewport(_resolution: Resolution): void {
// pass
}

Expand Down
6 changes: 3 additions & 3 deletions src/engine/Graphics/Context/ExcaliburGraphicsContextWebGL.ts
Expand Up @@ -15,7 +15,7 @@ import { Color } from '../../Color';
import { StateStack } from './state-stack';
import { Logger } from '../../Util/Log';
import { DebugText } from './debug-text';
import { ScreenDimension } from '../../Screen';
import { Resolution } from '../../Screen';
import { RenderTarget } from './render-target';
import { PostProcessor } from '../PostProcessor/PostProcessor';
import { TextureLoader } from './texture-loader';
Expand Down Expand Up @@ -199,7 +199,7 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
* Checks the underlying webgl implementation if the requested internal resolution is supported
* @param dim
*/
public checkIfResolutionSupported(dim: ScreenDimension): boolean {
public checkIfResolutionSupported(dim: Resolution): boolean {
// Slight hack based on this thread https://groups.google.com/g/webgl-dev-list/c/AHONvz3oQTo
let supported = true;
if (dim.width > 4096 || dim.height > 4096) {
Expand Down Expand Up @@ -435,7 +435,7 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
this._transform.current = AffineMatrix.identity();
}

public updateViewport(resolution: ScreenDimension): void {
public updateViewport(resolution: Resolution): void {
const gl = this.__gl;
this._ortho = this._ortho = Matrix.ortho(0, resolution.width, resolution.height, 0, 400, -400);

Expand Down
103 changes: 58 additions & 45 deletions src/engine/Screen.ts
Expand Up @@ -100,53 +100,58 @@ export enum DisplayMode {
*/
export class Resolution {
/* istanbul ignore next */
public static get SVGA(): ScreenDimension {
public static get SVGA(): Resolution {
return { width: 800, height: 600 };
}

/* istanbul ignore next */
public static get Standard(): ScreenDimension {
public static get Standard(): Resolution {
return { width: 1920, height: 1080 };
}

/* istanbul ignore next */
public static get Atari2600(): ScreenDimension {
public static get Atari2600(): Resolution {
return { width: 160, height: 192 };
}

/* istanbul ignore next */
public static get GameBoy(): ScreenDimension {
public static get GameBoy(): Resolution {
return { width: 160, height: 144 };
}

/* istanbul ignore next */
public static get GameBoyAdvance(): ScreenDimension {
public static get GameBoyAdvance(): Resolution {
return { width: 240, height: 160 };
}

/* istanbul ignore next */
public static get NintendoDS(): ScreenDimension {
public static get NintendoDS(): Resolution {
return { width: 256, height: 192 };
}

/* istanbul ignore next */
public static get NES(): ScreenDimension {
public static get NES(): Resolution {
return { width: 256, height: 224 };
}

/* istanbul ignore next */
public static get SNES(): ScreenDimension {
public static get SNES(): Resolution {
return { width: 256, height: 244 };
}
}

export type ScreenUnit = 'pixel' | 'percent';
export type ViewportUnit = 'pixel' | 'percent';

export interface ScreenDimension {
export interface Resolution {
width: number;
height: number;
}

export interface ViewportDimension {
widthUnit?: ViewportUnit;
heightUnit?: ViewportUnit;
width: number;
height: number;
widthUnit?: ScreenUnit;
heightUnit?: ScreenUnit;
}

export interface ScreenOptions {
Expand Down Expand Up @@ -182,11 +187,11 @@ export interface ScreenOptions {
* resolution will be the same as the viewport. Resolution will be overridden by [[DisplayMode.FillContainer]] and
* [[DisplayMode.FillScreen]].
*/
resolution?: ScreenDimension;
resolution?: Resolution;
/**
* Visual viewport size in css pixel, if resolution is not specified it will be the same as the viewport
*/
viewport: ScreenDimension;
viewport: ViewportDimension;
/**
* Set the display mode of the screen, by default DisplayMode.Fixed.
*/
Expand All @@ -200,11 +205,11 @@ export interface ScreenResizeEvent {
/**
* Current viewport in css pixels of the screen
*/
viewport: ScreenDimension;
viewport: ViewportDimension;
/**
* Current resolution in world pixels of the screen
*/
resolution: ScreenDimension;
resolution: Resolution;
}

/**
Expand Down Expand Up @@ -263,13 +268,13 @@ export class Screen {
private _canvas: HTMLCanvasElement;
private _antialiasing: boolean = true;
private _canvasImageRendering: 'auto' | 'pixelated' = 'auto';
private _contentResolution: ScreenDimension;
private _contentResolution: Resolution;
private _browser: BrowserEvents;
private _camera: Camera;
private _resolution: ScreenDimension;
private _resolutionStack: ScreenDimension[] = [];
private _viewport: ScreenDimension;
private _viewportStack: ScreenDimension[] = [];
private _resolution: Resolution;
private _resolutionStack: Resolution[] = [];
private _viewport: ViewportDimension;
private _viewportStack: ViewportDimension[] = [];
private _pixelRatioOverride: number | null = null;
private _displayMode: DisplayMode;
private _isFullScreen = false;
Expand Down Expand Up @@ -435,28 +440,25 @@ export class Screen {
}
}

public get resolution(): ScreenDimension {
public get resolution(): Resolution {
return this._resolution;
}

public set resolution(resolution: ScreenDimension) {
if (resolution.heightUnit === 'percent' || resolution.widthUnit === 'percent') {
throw Error('Screen resolution only supports pixels not percentage sizes');
}
public set resolution(resolution: Resolution) {
this._resolution = resolution;
}

/**
* Returns screen dimensions in pixels or percentage
*/
public get viewport(): ScreenDimension {
public get viewport(): ViewportDimension {
if (this._viewport) {
return this._viewport;
}
return this._resolution;
}

public set viewport(viewport: ScreenDimension) {
public set viewport(viewport: ViewportDimension) {
this._viewport = viewport;
}

Expand Down Expand Up @@ -484,11 +486,11 @@ export class Screen {
this.viewport = { ...this.viewport };
}

public peekViewport(): ScreenDimension {
public peekViewport(): ViewportDimension {
return this._viewportStack[this._viewportStack.length - 1];
}

public peekResolution(): ScreenDimension {
public peekResolution(): Resolution {
return this._resolutionStack[this._resolutionStack.length - 1];
}

Expand Down Expand Up @@ -608,6 +610,13 @@ export class Screen {
return document.exitFullscreen();
}

private _viewportToPixels(viewport: ViewportDimension) {
return {
width: viewport.widthUnit === 'percent' ? this.canvas.offsetWidth : viewport.width,
height: viewport.heightUnit === 'percent' ? this.canvas.offsetHeight : viewport.height
} satisfies ViewportDimension;
}

/**
* Takes a coordinate in normal html page space, for example from a pointer move event, and translates it to
* Excalibur screen space.
Expand All @@ -626,24 +635,26 @@ export class Screen {
newY -= getPosition(this._canvas).y;
}

const viewport = this._viewportToPixels(this.viewport);

// if fullscreen api on it centers with black bars
// we need to adjust the screen to world coordinates in this case
if (this._isFullScreen) {
if (window.innerWidth / this.aspectRatio < window.innerHeight) {
const screenHeight = window.innerWidth / this.aspectRatio;
const screenMarginY = (window.innerHeight - screenHeight) / 2;
newY = ((newY - screenMarginY) / screenHeight) * this.viewport.height;
newX = (newX / window.innerWidth) * this.viewport.width;
newY = ((newY - screenMarginY) / screenHeight) * viewport.height;
newX = (newX / window.innerWidth) * viewport.width;
} else {
const screenWidth = window.innerHeight * this.aspectRatio;
const screenMarginX = (window.innerWidth - screenWidth) / 2;
newX = ((newX - screenMarginX) / screenWidth) * this.viewport.width;
newY = (newY / window.innerHeight) * this.viewport.height;
newX = ((newX - screenMarginX) / screenWidth) * viewport.width;
newY = (newY / window.innerHeight) * viewport.height;
}
}

newX = (newX / this.viewport.width) * this.resolution.width;
newY = (newY / this.viewport.height) * this.resolution.height;
newX = (newX / viewport.width) * this.resolution.width;
newY = (newY / viewport.height) * this.resolution.height;

// offset by content area
newX = newX - this.contentArea.left;
Expand All @@ -666,20 +677,22 @@ export class Screen {

// no need to offset by content area, drawing is already offset by this

newX = (newX / this.resolution.width) * this.viewport.width;
newY = (newY / this.resolution.height) * this.viewport.height;
const viewport = this._viewportToPixels(this.viewport);

newX = (newX / this.resolution.width) * viewport.width;
newY = (newY / this.resolution.height) * viewport.height;

if (this._isFullScreen) {
if (window.innerWidth / this.aspectRatio < window.innerHeight) {
const screenHeight = window.innerWidth / this.aspectRatio;
const screenMarginY = (window.innerHeight - screenHeight) / 2;
newY = (newY / this.viewport.height) * screenHeight + screenMarginY;
newX = (newX / this.viewport.width) * window.innerWidth;
newY = (newY / viewport.height) * screenHeight + screenMarginY;
newX = (newX / viewport.width) * window.innerWidth;
} else {
const screenWidth = window.innerHeight * this.aspectRatio;
const screenMarginX = (window.innerWidth - screenWidth) / 2;
newX = (newX / this.viewport.width) * screenWidth + screenMarginX;
newY = (newY / this.viewport.height) * window.innerHeight;
newX = (newX / viewport.width) * screenWidth + screenMarginX;
newY = (newY / viewport.height) * window.innerHeight;
}
}

Expand Down Expand Up @@ -908,7 +921,7 @@ export class Screen {
} satisfies ScreenResizeEvent);
}

private _computeFitAndFill(vw: number, vh: number, viewport?: ScreenDimension) {
private _computeFitAndFill(vw: number, vh: number, viewport?: ViewportDimension) {
this.viewport = viewport ?? {
width: vw,
height: vh
Expand Down Expand Up @@ -1046,8 +1059,8 @@ export class Screen {
const aspect = this.aspectRatio;
let adjustedWidth = 0;
let adjustedHeight = 0;
let widthUnit: ScreenUnit = 'pixel';
let heightUnit: ScreenUnit = 'pixel';
let widthUnit: ViewportUnit = 'pixel';
let heightUnit: ViewportUnit = 'pixel';
const parent = this.canvas.parentElement;
if (parent.clientWidth / aspect < parent.clientHeight) {
this.canvas.style.width = '100%';
Expand Down

0 comments on commit 3b97bf2

Please sign in to comment.