mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
8 Commits
a05b0cd0ef
...
integer-ne
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7ceaf07418 | ||
![]() |
7eef5fb722 | ||
![]() |
30c750d498 | ||
![]() |
ecbf73823b | ||
![]() |
1156a8ad75 | ||
![]() |
1438b28cab | ||
![]() |
9e8fbbe287 | ||
![]() |
0b4dadd3d5 |
@@ -374,12 +374,14 @@ class GD_CORE_API Project {
|
||||
void SetVerticalSyncActivatedByDefault(bool enable) { verticalSync = enable; }
|
||||
|
||||
/**
|
||||
* Return the scale mode used by the game (usually "linear" or "nearest").
|
||||
* Return the scale mode used by the game (usually "linear", "magnified" or
|
||||
* "nearest").
|
||||
*/
|
||||
const gd::String& GetScaleMode() const { return scaleMode; }
|
||||
|
||||
/**
|
||||
* Set the scale mode used by the game (usually "linear" or "nearest").
|
||||
* Set the scale mode used by the game (usually "linear", "magnified" or
|
||||
* "nearest").
|
||||
*/
|
||||
void SetScaleMode(const gd::String& scaleMode_) { scaleMode = scaleMode_; }
|
||||
|
||||
|
@@ -211,8 +211,8 @@ namespace gdjs {
|
||||
const isOutsideCanvas =
|
||||
canvasRight < 0 ||
|
||||
canvasBottom < 0 ||
|
||||
canvasLeft > runtimeGame.getGameResolutionWidth() ||
|
||||
canvasTop > runtimeGame.getGameResolutionHeight();
|
||||
canvasLeft > runtimeGame.getRenderingResolutionWidth() ||
|
||||
canvasTop > runtimeGame.getRenderingResolutionHeight();
|
||||
if (isOutsideCanvas) {
|
||||
this._form.style.display = 'none';
|
||||
return;
|
||||
|
@@ -4,6 +4,7 @@ namespace gdjs {
|
||||
_fontManager: any;
|
||||
_text: PIXI.Text;
|
||||
_justCreated: boolean = true;
|
||||
_upscaleRatio: integer = 1;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.TextRuntimeObject,
|
||||
@@ -47,7 +48,7 @@ namespace gdjs {
|
||||
const style = this._text.style;
|
||||
style.fontStyle = this._object._italic ? 'italic' : 'normal';
|
||||
style.fontWeight = this._object._bold ? 'bold' : 'normal';
|
||||
style.fontSize = this._object._characterSize;
|
||||
style.fontSize = this._object._characterSize * this._upscaleRatio;
|
||||
style.fontFamily = fontName;
|
||||
if (this._object._useGradient) {
|
||||
style.fill = this._getGradientHex();
|
||||
@@ -62,7 +63,7 @@ namespace gdjs {
|
||||
// @ts-ignore
|
||||
style.align = this._object._textAlign;
|
||||
style.wordWrap = this._object._wrapping;
|
||||
style.wordWrapWidth = this._object._wrappingWidth;
|
||||
style.wordWrapWidth = this._object._wrappingWidth * this._upscaleRatio;
|
||||
style.breakWords = true;
|
||||
style.stroke = gdjs.rgbToHexNumber(
|
||||
this._object._outlineColor[0],
|
||||
@@ -70,7 +71,7 @@ namespace gdjs {
|
||||
this._object._outlineColor[2]
|
||||
);
|
||||
style.strokeThickness = this._object._isOutlineEnabled
|
||||
? this._object._outlineThickness
|
||||
? this._object._outlineThickness * this._upscaleRatio
|
||||
: 0;
|
||||
style.dropShadow = this._object._shadow;
|
||||
style.dropShadowColor = gdjs.rgbToHexNumber(
|
||||
@@ -79,13 +80,16 @@ namespace gdjs {
|
||||
this._object._shadowColor[2]
|
||||
);
|
||||
style.dropShadowAlpha = this._object._shadowOpacity / 255;
|
||||
style.dropShadowBlur = this._object._shadowBlur;
|
||||
style.dropShadowBlur = this._object._shadowBlur * this._upscaleRatio;
|
||||
style.dropShadowAngle = gdjs.toRad(this._object._shadowAngle);
|
||||
style.dropShadowDistance = this._object._shadowDistance;
|
||||
style.dropShadowDistance =
|
||||
this._object._shadowDistance * this._upscaleRatio;
|
||||
const extraPaddingForShadow = style.dropShadow
|
||||
? style.dropShadowDistance + style.dropShadowBlur
|
||||
? this._object._shadowDistance + this._object._shadowBlur
|
||||
: 0;
|
||||
style.padding = Math.ceil(this._object._padding + extraPaddingForShadow);
|
||||
style.padding =
|
||||
Math.ceil(this._object._padding + extraPaddingForShadow) *
|
||||
this._upscaleRatio;
|
||||
|
||||
// Prevent spikey outlines by adding a miter limit
|
||||
style.miterLimit = 3;
|
||||
@@ -117,7 +121,6 @@ namespace gdjs {
|
||||
this._text.position.x = this._object.x + this._text.width / 2;
|
||||
this._text.anchor.x = 0.5;
|
||||
}
|
||||
this._text.position.y = this._object.y + this._text.height / 2;
|
||||
|
||||
const alignmentY =
|
||||
this._object._verticalTextAlignment === 'bottom'
|
||||
@@ -181,18 +184,30 @@ namespace gdjs {
|
||||
return gradient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text object upscale ratio.
|
||||
* @param upscaleRatio The new upscale ratio for the text object.
|
||||
* @see gdjs.RuntimeGame.getZoomFactor
|
||||
*/
|
||||
setUpscaleRatio(upscaleRatio: integer): void {
|
||||
this._upscaleRatio = upscaleRatio;
|
||||
this._text.scale.x = this._object.getScaleX() / this._upscaleRatio;
|
||||
this._text.scale.y = this._object.getScaleY() / this._upscaleRatio;
|
||||
this.updateStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get x-scale of the text.
|
||||
*/
|
||||
getScaleX(): float {
|
||||
return this._text.scale.x;
|
||||
return this._object.getScaleX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get y-scale of the text.
|
||||
*/
|
||||
getScaleY(): float {
|
||||
return this._text.scale.y;
|
||||
return this._object.getScaleY();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,8 +215,8 @@ namespace gdjs {
|
||||
* @param newScale The new scale for the text object.
|
||||
*/
|
||||
setScale(newScale: float): void {
|
||||
this._text.scale.x = newScale;
|
||||
this._text.scale.y = newScale;
|
||||
this._text.scale.x = newScale / this._upscaleRatio;
|
||||
this._text.scale.y = newScale / this._upscaleRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,7 +224,7 @@ namespace gdjs {
|
||||
* @param newScale The new x-scale for the text object.
|
||||
*/
|
||||
setScaleX(newScale: float): void {
|
||||
this._text.scale.x = newScale;
|
||||
this._text.scale.x = newScale / this._upscaleRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,7 +232,7 @@ namespace gdjs {
|
||||
* @param newScale The new y-scale for the text object.
|
||||
*/
|
||||
setScaleY(newScale: float): void {
|
||||
this._text.scale.y = newScale;
|
||||
this._text.scale.y = newScale / this._upscaleRatio;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
@@ -149,7 +149,7 @@ namespace gdjs {
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
updateFromObjectData(
|
||||
override updateFromObjectData(
|
||||
oldObjectData: TextObjectData,
|
||||
newObjectData: TextObjectData
|
||||
): boolean {
|
||||
@@ -214,7 +214,7 @@ namespace gdjs {
|
||||
return true;
|
||||
}
|
||||
|
||||
getNetworkSyncData(): TextObjectNetworkSyncData {
|
||||
override getNetworkSyncData(): TextObjectNetworkSyncData {
|
||||
return {
|
||||
...super.getNetworkSyncData(),
|
||||
str: this._str,
|
||||
@@ -242,7 +242,7 @@ namespace gdjs {
|
||||
};
|
||||
}
|
||||
|
||||
updateFromNetworkSyncData(
|
||||
override updateFromNetworkSyncData(
|
||||
networkSyncData: TextObjectNetworkSyncData
|
||||
): void {
|
||||
super.updateFromNetworkSyncData(networkSyncData);
|
||||
@@ -317,15 +317,15 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
override getRendererObject() {
|
||||
return this._renderer.getRendererObject();
|
||||
}
|
||||
|
||||
update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
override update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
this._renderer.ensureUpToDate();
|
||||
}
|
||||
|
||||
onDestroyed(): void {
|
||||
override onDestroyed(): void {
|
||||
super.onDestroyed();
|
||||
this._renderer.destroy();
|
||||
}
|
||||
@@ -345,6 +345,12 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
override onGameZoomFactorChanged(): void {
|
||||
this._renderer.setUpscaleRatio(
|
||||
this.getRuntimeScene().getGame().getZoomFactor()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rendered object position.
|
||||
*/
|
||||
@@ -353,27 +359,17 @@ namespace gdjs {
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on X axis.
|
||||
*/
|
||||
setX(x: float): void {
|
||||
override setX(x: float): void {
|
||||
super.setX(x);
|
||||
this._updateTextPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on Y axis.
|
||||
*/
|
||||
setY(y: float): void {
|
||||
override setY(y: float): void {
|
||||
super.setY(y);
|
||||
this._updateTextPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the angle of the object.
|
||||
* @param angle The new angle of the object
|
||||
*/
|
||||
setAngle(angle: float): void {
|
||||
override setAngle(angle: float): void {
|
||||
super.setAngle(angle);
|
||||
this._renderer.updateAngle();
|
||||
}
|
||||
@@ -499,14 +495,14 @@ namespace gdjs {
|
||||
/**
|
||||
* Get width of the text.
|
||||
*/
|
||||
getWidth(): float {
|
||||
override getWidth(): float {
|
||||
return this._wrapping ? this._wrappingWidth : this._renderer.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get height of the text.
|
||||
*/
|
||||
getHeight(): float {
|
||||
override getHeight(): float {
|
||||
return this._renderer.getHeight();
|
||||
}
|
||||
|
||||
@@ -685,11 +681,11 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
setWidth(width: float): void {
|
||||
override setWidth(width: float): void {
|
||||
this.setWrappingWidth(width);
|
||||
}
|
||||
|
||||
getDrawableY(): float {
|
||||
override getDrawableY(): float {
|
||||
return (
|
||||
this.getY() -
|
||||
(this._verticalTextAlignment === 'center'
|
||||
|
@@ -229,6 +229,10 @@ namespace gdjs {
|
||||
*/
|
||||
onDestroy(parent: gdjs.RuntimeInstanceContainer) {}
|
||||
|
||||
override onGameZoomFactorChanged() {
|
||||
this._instanceContainer.onGameZoomFactorChanged();
|
||||
}
|
||||
|
||||
override updatePreRender(parent: gdjs.RuntimeInstanceContainer): void {
|
||||
this._instanceContainer._updateObjectsPreRender();
|
||||
this.getRenderer().ensureUpToDate();
|
||||
|
@@ -547,6 +547,15 @@ namespace gdjs {
|
||||
return this._allInstancesList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game zoom factor is changed to adapt to a new resolution.
|
||||
*/
|
||||
onGameZoomFactorChanged(): void {
|
||||
for (const instance of this.getAdhocListOfAllInstances()) {
|
||||
instance.onGameZoomFactorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the objects before launching the events.
|
||||
*/
|
||||
|
@@ -37,18 +37,10 @@ namespace gdjs {
|
||||
showPointsNames: boolean,
|
||||
showCustomPoints: boolean
|
||||
) {
|
||||
const pixiContainer = this._instanceContainer
|
||||
.getRenderer()
|
||||
.getRendererObject();
|
||||
if (!this._debugDraw || !this._debugDrawContainer) {
|
||||
this._debugDrawContainer = new PIXI.Container();
|
||||
this._debugDraw = new PIXI.Graphics();
|
||||
|
||||
// Add on top of all layers:
|
||||
this._debugDrawContainer.addChild(this._debugDraw);
|
||||
if (pixiContainer) {
|
||||
pixiContainer.addChild(this._debugDrawContainer);
|
||||
}
|
||||
}
|
||||
const debugDraw = this._debugDraw;
|
||||
|
||||
@@ -112,7 +104,8 @@ namespace gdjs {
|
||||
const polygon: float[] = [];
|
||||
polygon.push.apply(
|
||||
polygon,
|
||||
layer.applyLayerTransformation(
|
||||
this.applyLayerTransformation(
|
||||
layer,
|
||||
aabb.min[0],
|
||||
aabb.min[1],
|
||||
0,
|
||||
@@ -121,7 +114,8 @@ namespace gdjs {
|
||||
);
|
||||
polygon.push.apply(
|
||||
polygon,
|
||||
layer.applyLayerTransformation(
|
||||
this.applyLayerTransformation(
|
||||
layer,
|
||||
aabb.max[0],
|
||||
aabb.min[1],
|
||||
0,
|
||||
@@ -130,7 +124,8 @@ namespace gdjs {
|
||||
);
|
||||
polygon.push.apply(
|
||||
polygon,
|
||||
layer.applyLayerTransformation(
|
||||
this.applyLayerTransformation(
|
||||
layer,
|
||||
aabb.max[0],
|
||||
aabb.max[1],
|
||||
0,
|
||||
@@ -139,7 +134,8 @@ namespace gdjs {
|
||||
);
|
||||
polygon.push.apply(
|
||||
polygon,
|
||||
layer.applyLayerTransformation(
|
||||
this.applyLayerTransformation(
|
||||
layer,
|
||||
aabb.min[0],
|
||||
aabb.max[1],
|
||||
0,
|
||||
@@ -185,7 +181,8 @@ namespace gdjs {
|
||||
// as this is for debug draw.
|
||||
const polygon: float[] = [];
|
||||
hitboxes[j].vertices.forEach((point) => {
|
||||
point = layer.applyLayerTransformation(
|
||||
point = this.applyLayerTransformation(
|
||||
layer,
|
||||
point[0],
|
||||
point[1],
|
||||
0,
|
||||
@@ -205,7 +202,8 @@ namespace gdjs {
|
||||
debugDraw.fill.alpha = 0.3;
|
||||
|
||||
// Draw Center point
|
||||
const centerPoint = layer.applyLayerTransformation(
|
||||
const centerPoint = this.applyLayerTransformation(
|
||||
layer,
|
||||
object.getCenterXInScene(),
|
||||
object.getCenterYInScene(),
|
||||
0,
|
||||
@@ -221,7 +219,8 @@ namespace gdjs {
|
||||
);
|
||||
|
||||
// Draw position point
|
||||
const positionPoint = layer.applyLayerTransformation(
|
||||
const positionPoint = this.applyLayerTransformation(
|
||||
layer,
|
||||
object.getX(),
|
||||
object.getY(),
|
||||
0,
|
||||
@@ -245,7 +244,8 @@ namespace gdjs {
|
||||
Math.abs(originPoint[0] - positionPoint[0]) >= 1 ||
|
||||
Math.abs(originPoint[1] - positionPoint[1]) >= 1
|
||||
) {
|
||||
originPoint = layer.applyLayerTransformation(
|
||||
originPoint = this.applyLayerTransformation(
|
||||
layer,
|
||||
originPoint[0],
|
||||
originPoint[1],
|
||||
0,
|
||||
@@ -270,7 +270,8 @@ namespace gdjs {
|
||||
for (const customPointName in animationFrame.points.items) {
|
||||
let customPoint = object.getPointPosition(customPointName);
|
||||
|
||||
customPoint = layer.applyLayerTransformation(
|
||||
customPoint = this.applyLayerTransformation(
|
||||
layer,
|
||||
customPoint[0],
|
||||
customPoint[1],
|
||||
0,
|
||||
@@ -303,6 +304,27 @@ namespace gdjs {
|
||||
debugDraw.endFill();
|
||||
}
|
||||
|
||||
private applyLayerTransformation(
|
||||
layer: gdjs.RuntimeLayer,
|
||||
x: float,
|
||||
y: float,
|
||||
cameraId: integer,
|
||||
result: FloatPoint
|
||||
): FloatPoint {
|
||||
layer.applyLayerTransformation(x, y, cameraId, result);
|
||||
const gamePixiContainer = this._instanceContainer
|
||||
.getRenderer()
|
||||
.getRendererObject();
|
||||
if (!gamePixiContainer) {
|
||||
return result;
|
||||
}
|
||||
// The scale is usually near 1 unless the 'magnified' scale mode is used.
|
||||
// See gdjs.RuntimeGame.getZoomFactor
|
||||
result[0] *= gamePixiContainer.scale.x;
|
||||
result[1] *= gamePixiContainer.scale.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
clearDebugDraw(): void {
|
||||
if (this._debugDraw) {
|
||||
this._debugDraw.clear();
|
||||
|
@@ -262,8 +262,8 @@ namespace gdjs {
|
||||
if (game.getAntialiasingMode() !== 'none') {
|
||||
this._threeEffectComposer.addPass(
|
||||
new THREE_ADDONS.SMAAPass(
|
||||
game.getGameResolutionWidth(),
|
||||
game.getGameResolutionHeight()
|
||||
game.getRenderingResolutionWidth(),
|
||||
game.getRenderingResolutionHeight()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -304,9 +304,12 @@ namespace gdjs {
|
||||
|
||||
this._threePlaneTexture = texture;
|
||||
this._threePlaneTexture.generateMipmaps = false;
|
||||
const scaleMode = this._layer
|
||||
.getRuntimeScene()
|
||||
.getGame()
|
||||
.getScaleMode();
|
||||
const filter =
|
||||
this._layer.getRuntimeScene().getGame().getScaleMode() ===
|
||||
'nearest'
|
||||
scaleMode === 'nearest' || scaleMode === 'magnified'
|
||||
? THREE.NearestFilter
|
||||
: THREE.LinearFilter;
|
||||
this._threePlaneTexture.minFilter = filter;
|
||||
@@ -501,8 +504,8 @@ namespace gdjs {
|
||||
if (this._threeEffectComposer) {
|
||||
const game = this._layer.getRuntimeScene().getGame();
|
||||
this._threeEffectComposer.setSize(
|
||||
game.getGameResolutionWidth(),
|
||||
game.getGameResolutionHeight()
|
||||
game.getRenderingResolutionWidth(),
|
||||
game.getRenderingResolutionHeight()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -100,16 +100,16 @@ namespace gdjs {
|
||||
this._threeRenderer.useLegacyLights = true;
|
||||
this._threeRenderer.autoClear = false;
|
||||
this._threeRenderer.setSize(
|
||||
this._game.getGameResolutionWidth(),
|
||||
this._game.getGameResolutionHeight()
|
||||
this._game.getRenderingResolutionWidth(),
|
||||
this._game.getRenderingResolutionHeight()
|
||||
);
|
||||
|
||||
// Create a PixiJS renderer that use the same GL context as Three.js
|
||||
// so that both can render to the canvas and even have PixiJS rendering
|
||||
// reused in Three.js (by using a RenderTexture and the same internal WebGL texture).
|
||||
this._pixiRenderer = new PIXI.Renderer({
|
||||
width: this._game.getGameResolutionWidth(),
|
||||
height: this._game.getGameResolutionHeight(),
|
||||
width: this._game.getRenderingResolutionWidth(),
|
||||
height: this._game.getRenderingResolutionHeight(),
|
||||
view: gameCanvas,
|
||||
// @ts-ignore - reuse the context from Three.js.
|
||||
context: this._threeRenderer.getContext(),
|
||||
@@ -124,8 +124,8 @@ namespace gdjs {
|
||||
// "preserveDrawingBuffer: true" is needed to avoid flickering
|
||||
// and background issues on some mobile phones (see #585 #572 #566 #463).
|
||||
this._pixiRenderer = PIXI.autoDetectRenderer({
|
||||
width: this._game.getGameResolutionWidth(),
|
||||
height: this._game.getGameResolutionHeight(),
|
||||
width: this._game.getRenderingResolutionWidth(),
|
||||
height: this._game.getRenderingResolutionHeight(),
|
||||
view: gameCanvas,
|
||||
preserveDrawingBuffer: true,
|
||||
antialias: false,
|
||||
@@ -272,20 +272,20 @@ namespace gdjs {
|
||||
// There is no "smart" resizing to be done here: the rendering of the game
|
||||
// should be done with the size set on the game.
|
||||
if (
|
||||
this._pixiRenderer.width !== this._game.getGameResolutionWidth() ||
|
||||
this._pixiRenderer.height !== this._game.getGameResolutionHeight()
|
||||
this._pixiRenderer.width !== this._game.getRenderingResolutionWidth() ||
|
||||
this._pixiRenderer.height !== this._game.getRenderingResolutionHeight()
|
||||
) {
|
||||
// TODO (3D): It might be useful to resize pixi view in 3D depending on FOV value
|
||||
// to enable a mode where pixi always fills the whole screen.
|
||||
this._pixiRenderer.resize(
|
||||
this._game.getGameResolutionWidth(),
|
||||
this._game.getGameResolutionHeight()
|
||||
this._game.getRenderingResolutionWidth(),
|
||||
this._game.getRenderingResolutionHeight()
|
||||
);
|
||||
|
||||
if (this._threeRenderer) {
|
||||
this._threeRenderer.setSize(
|
||||
this._game.getGameResolutionWidth(),
|
||||
this._game.getGameResolutionHeight()
|
||||
this._game.getRenderingResolutionWidth(),
|
||||
this._game.getRenderingResolutionHeight()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -295,8 +295,8 @@ namespace gdjs {
|
||||
// only, so won't create visual artifacts during the rendering.
|
||||
const isFullPage =
|
||||
this._forceFullscreen || this._isFullPage || this._isFullscreen;
|
||||
let canvasWidth = this._game.getGameResolutionWidth();
|
||||
let canvasHeight = this._game.getGameResolutionHeight();
|
||||
let canvasWidth = this._game.getRenderingResolutionWidth();
|
||||
let canvasHeight = this._game.getRenderingResolutionHeight();
|
||||
let maxWidth = window.innerWidth - this._marginLeft - this._marginRight;
|
||||
let maxHeight = window.innerHeight - this._marginTop - this._marginBottom;
|
||||
if (maxWidth < 0) {
|
||||
@@ -523,10 +523,10 @@ namespace gdjs {
|
||||
// Handle the fact that the game is stretched to fill the canvas.
|
||||
pageCoords[0] =
|
||||
(canvasCoords[0] * this._canvasWidth) /
|
||||
this._game.getGameResolutionWidth();
|
||||
this._game.getRenderingResolutionWidth();
|
||||
pageCoords[1] =
|
||||
(canvasCoords[1] * this._canvasHeight) /
|
||||
this._game.getGameResolutionHeight();
|
||||
this._game.getRenderingResolutionHeight();
|
||||
|
||||
return pageCoords;
|
||||
}
|
||||
|
@@ -275,6 +275,12 @@ namespace gdjs {
|
||||
pixiRenderer.render(this._pixiContainer, {
|
||||
clear: this._runtimeScene.getClearCanvas(),
|
||||
});
|
||||
const debugContainer = this._runtimeScene
|
||||
.getDebuggerRenderer()
|
||||
.getRendererObject();
|
||||
if (debugContainer) {
|
||||
pixiRenderer.render(debugContainer, { clear: false });
|
||||
}
|
||||
this._layerRenderingMetrics.rendered2DLayersCount++;
|
||||
}
|
||||
|
||||
|
@@ -141,7 +141,7 @@ namespace gdjs {
|
||||
_originalHeight: float;
|
||||
_resizeMode: 'adaptWidth' | 'adaptHeight' | string;
|
||||
_adaptGameResolutionAtRuntime: boolean;
|
||||
_scaleMode: 'linear' | 'nearest';
|
||||
_scaleMode: ScaleMode;
|
||||
_pixelsRounding: boolean;
|
||||
_antialiasingMode: 'none' | 'MSAA';
|
||||
_isAntialisingEnabledOnMobile: boolean;
|
||||
@@ -158,6 +158,11 @@ namespace gdjs {
|
||||
* When set to true, the scenes are notified that game resolution size changed.
|
||||
*/
|
||||
_notifyScenesForGameResolutionResize: boolean = false;
|
||||
/**
|
||||
* When set to true, the scenes are notified that game zoom factor changed.
|
||||
*/
|
||||
_notifyScenesForGameZoomFactorChange: boolean = false;
|
||||
_zoomFactor: number = 1;
|
||||
|
||||
/**
|
||||
* When paused, the game won't step and will be freezed. Useful for debugging.
|
||||
@@ -551,21 +556,45 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game resolution (the size at which the game is played and rendered) width.
|
||||
* Get the game resolution width for events.
|
||||
* @returns The game resolution width, in pixels.
|
||||
*/
|
||||
getGameResolutionWidth(): float {
|
||||
return this._gameResolutionWidth / this._zoomFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game resolution height for events.
|
||||
* @returns The game resolution height, in pixels.
|
||||
*/
|
||||
getGameResolutionHeight(): float {
|
||||
return this._gameResolutionHeight / this._zoomFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game resolution width (the size at which the game is rendered).
|
||||
* @returns The game resolution width, in pixels.
|
||||
*/
|
||||
getRenderingResolutionWidth(): float {
|
||||
return this._gameResolutionWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game resolution (the size at which the game is played and rendered) height.
|
||||
* Get the game resolution height (the size at which the game is rendered).
|
||||
* @returns The game resolution height, in pixels.
|
||||
*/
|
||||
getGameResolutionHeight(): float {
|
||||
getRenderingResolutionHeight(): float {
|
||||
return this._gameResolutionHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* The scale is usually near 1 unless the 'magnified' scale mode is used.
|
||||
* @returns the factor between game resolution size and rendering resolution size.
|
||||
*/
|
||||
getZoomFactor() {
|
||||
return this._zoomFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the game resolution.
|
||||
*
|
||||
@@ -577,17 +606,16 @@ namespace gdjs {
|
||||
|
||||
this._gameResolutionWidth = width;
|
||||
this._gameResolutionHeight = height;
|
||||
if (this._adaptGameResolutionAtRuntime) {
|
||||
if (
|
||||
gdjs.RuntimeGameRenderer &&
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerWidth &&
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerHeight
|
||||
) {
|
||||
const windowInnerWidth =
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerWidth();
|
||||
const windowInnerHeight =
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerHeight();
|
||||
if (
|
||||
gdjs.RuntimeGameRenderer &&
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerWidth &&
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerHeight
|
||||
) {
|
||||
const windowInnerWidth = gdjs.RuntimeGameRenderer.getWindowInnerWidth();
|
||||
const windowInnerHeight =
|
||||
gdjs.RuntimeGameRenderer.getWindowInnerHeight();
|
||||
|
||||
if (this._adaptGameResolutionAtRuntime) {
|
||||
// Enlarge either the width or the eight to fill the inner window space.
|
||||
if (this._resizeMode === 'adaptWidth') {
|
||||
this._gameResolutionWidth =
|
||||
@@ -614,6 +642,35 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
this._scaleMode === 'magnified' &&
|
||||
this._gameResolutionWidth > 0 &&
|
||||
this._gameResolutionHeight > 0 &&
|
||||
// Fall back on linear if magnified is used on a high resolution game.
|
||||
this._originalWidth <= 960 &&
|
||||
this._originalHeight <= 540
|
||||
) {
|
||||
const pixelSize = Math.max(
|
||||
1,
|
||||
Math.ceil(
|
||||
this._zoomFactor *
|
||||
Math.min(
|
||||
windowInnerWidth / this._gameResolutionWidth,
|
||||
windowInnerHeight / this._gameResolutionHeight
|
||||
)
|
||||
)
|
||||
);
|
||||
this._gameResolutionWidth = Math.round(
|
||||
(this._gameResolutionWidth * pixelSize) / this._zoomFactor
|
||||
);
|
||||
this._gameResolutionHeight = Math.round(
|
||||
(this._gameResolutionHeight * pixelSize) / this._zoomFactor
|
||||
);
|
||||
if (this._zoomFactor !== pixelSize && pixelSize >= 1) {
|
||||
this._zoomFactor = pixelSize;
|
||||
this._notifyScenesForGameZoomFactorChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't alter the game resolution. The renderer
|
||||
@@ -682,9 +739,9 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scale mode of the game ("linear" or "nearest").
|
||||
* Return the scale mode of the game ("linear", "magnified" or "nearest").
|
||||
*/
|
||||
getScaleMode(): 'linear' | 'nearest' {
|
||||
getScaleMode(): ScaleMode {
|
||||
return this._scaleMode;
|
||||
}
|
||||
|
||||
@@ -962,6 +1019,10 @@ namespace gdjs {
|
||||
this._sceneStack.onGameResolutionResized();
|
||||
this._notifyScenesForGameResolutionResize = false;
|
||||
}
|
||||
if (this._notifyScenesForGameZoomFactorChange) {
|
||||
this._sceneStack.onGameZoomFactorChanged();
|
||||
this._notifyScenesForGameZoomFactorChange = false;
|
||||
}
|
||||
|
||||
// Render and step the scene.
|
||||
if (this._sceneStack.step(elapsedTime)) {
|
||||
|
@@ -658,6 +658,11 @@ namespace gdjs {
|
||||
*/
|
||||
onSceneResumed(runtimeScene: gdjs.RuntimeScene): void {}
|
||||
|
||||
/**
|
||||
* Called when the game zoom factor is changed to adapt to a new resolution.
|
||||
*/
|
||||
onGameZoomFactorChanged(): void {}
|
||||
|
||||
//Rendering:
|
||||
/**
|
||||
* @return The internal object for a 2D rendering (PIXI.DisplayObject...)
|
||||
|
@@ -34,6 +34,15 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game zoom factor is changed to adapt to a new resolution.
|
||||
*/
|
||||
onGameZoomFactorChanged(): void {
|
||||
for (let i = 0; i < this._stack.length; ++i) {
|
||||
this._stack[i].onGameZoomFactorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
step(elapsedTime: float): boolean {
|
||||
this._throwIfDisposed();
|
||||
if (this._isNextLayoutLoading || this._stack.length === 0) {
|
||||
|
4
GDJS/Runtime/types/project-data.d.ts
vendored
4
GDJS/Runtime/types/project-data.d.ts
vendored
@@ -329,13 +329,15 @@ declare interface EffectNetworkSyncData {
|
||||
};
|
||||
}
|
||||
|
||||
declare type ScaleMode = 'linear' | 'magnified' | 'nearest';
|
||||
|
||||
declare interface ProjectPropertiesData {
|
||||
adaptGameResolutionAtRuntime: boolean;
|
||||
folderProject: boolean;
|
||||
orientation: string;
|
||||
packageName: string;
|
||||
projectFile: string;
|
||||
scaleMode: 'linear' | 'nearest';
|
||||
scaleMode: ScaleMode;
|
||||
pixelsRounding: boolean;
|
||||
antialiasingMode: 'none' | 'MSAA';
|
||||
antialisingEnabledOnMobile: boolean;
|
||||
|
@@ -129,7 +129,9 @@ export const installResource = (
|
||||
if (newResource.getKind() === 'image') {
|
||||
// $FlowExpectedError[prop-missing] - We know the resource is an ImageResource and has the setSmooth method.
|
||||
newResource.setSmooth(
|
||||
project.getScaleMode() !== 'nearest' && !isPixelArt(asset)
|
||||
project.getScaleMode() !== 'nearest' &&
|
||||
project.getScaleMode() !== 'magnified' &&
|
||||
!isPixelArt(asset)
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -655,7 +655,8 @@ export default class LayerRenderer {
|
||||
|
||||
threePlaneTexture.generateMipmaps = false;
|
||||
const filter =
|
||||
this.project.getScaleMode() === 'nearest'
|
||||
this.project.getScaleMode() === 'nearest' ||
|
||||
this.project.getScaleMode() === 'magnified'
|
||||
? THREE.NearestFilter
|
||||
: THREE.LinearFilter;
|
||||
threePlaneTexture.minFilter = filter;
|
||||
|
@@ -729,11 +729,15 @@ const ProjectPropertiesDialog = (props: Props) => {
|
||||
>
|
||||
<SelectOption
|
||||
value="linear"
|
||||
label={t`Linear (antialiased rendering, good for most games)`}
|
||||
label={t`Linear (smooth, good for most games)`}
|
||||
/>
|
||||
<SelectOption
|
||||
value="magnified"
|
||||
label={t`Magnified (sharp, good for modern pixel-art games)`}
|
||||
/>
|
||||
<SelectOption
|
||||
value="nearest"
|
||||
label={t`Nearest (no antialiasing, good for pixel perfect games)`}
|
||||
label={t`Nearest (aliased, good for pixel perfect games)`}
|
||||
/>
|
||||
</SelectField>
|
||||
<Checkbox
|
||||
@@ -749,7 +753,7 @@ const ProjectPropertiesDialog = (props: Props) => {
|
||||
notifyOfChange();
|
||||
}}
|
||||
/>
|
||||
{scaleMode === 'nearest' && (
|
||||
{(scaleMode === 'nearest' || scaleMode === 'magnified') && (
|
||||
<DismissableAlertMessage
|
||||
identifier="use-non-smoothed-textures"
|
||||
kind="info"
|
||||
|
@@ -154,7 +154,10 @@ export const applyResourceDefaults = (
|
||||
newResource: gdResource
|
||||
) => {
|
||||
if (newResource instanceof gd.ImageResource) {
|
||||
newResource.setSmooth(project.getScaleMode() !== 'nearest');
|
||||
newResource.setSmooth(
|
||||
project.getScaleMode() !== 'nearest' &&
|
||||
project.getScaleMode() !== 'magnified'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user