From 4f24e0ea1c2f345bb302943242ce9b9808be0434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Davy=20H=C3=A9lard?= Date: Tue, 17 Sep 2024 18:51:27 +0200 Subject: [PATCH 1/4] Fix anchor behavior when objects has custom origin --- .../AnchorBehavior/anchorruntimebehavior.ts | 18 ++++-- .../tests/anchorruntimebehavior.spec.js | 63 +++++++++++++++++++ .../Extensions/testspriteruntimeobject.js | 8 +++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/Extensions/AnchorBehavior/anchorruntimebehavior.ts b/Extensions/AnchorBehavior/anchorruntimebehavior.ts index 6a92332a5811..60a0dc6d761b 100644 --- a/Extensions/AnchorBehavior/anchorruntimebehavior.ts +++ b/Extensions/AnchorBehavior/anchorruntimebehavior.ts @@ -270,8 +270,13 @@ namespace gdjs { this._rightEdgeAnchor !== HorizontalAnchor.None && this._leftEdgeAnchor !== HorizontalAnchor.None ) { - this.owner.setWidth(right - left); - this.owner.setX(left); + const width = right - left; + this.owner.setX( + left + + ((this.owner.getX() - this.owner.getDrawableX()) * width) / + this.owner.getWidth() + ); + this.owner.setWidth(width); } else { if (this._leftEdgeAnchor !== HorizontalAnchor.None) { this.owner.setX( @@ -292,8 +297,13 @@ namespace gdjs { this._bottomEdgeAnchor !== VerticalAnchor.None && this._topEdgeAnchor !== VerticalAnchor.None ) { - this.owner.setHeight(bottom - top); - this.owner.setY(top); + const height = bottom - top; + this.owner.setY( + top + + ((this.owner.getY() - this.owner.getDrawableY()) * height) / + this.owner.getHeight() + ); + this.owner.setHeight(height); } else { if (this._topEdgeAnchor !== VerticalAnchor.None) { this.owner.setY( diff --git a/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js b/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js index 3a8b4a836a7a..f04975aa1156 100644 --- a/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js +++ b/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js @@ -70,6 +70,50 @@ describe('gdjs.AnchorRuntimeBehavior', function () { return object; } + const createSpriteWithOriginAtCenter = (behaviorProperties) => { + const object = new gdjs.TestSpriteRuntimeObject(runtimeScene, { + name: 'obj1', + type: '', + behaviors: [ + { + name: anchorBehaviorName, + type: 'AnchorBehavior::AnchorBehavior', + // @ts-ignore - properties are not typed + rightEdgeAnchor: 0, + leftEdgeAnchor: 0, + topEdgeAnchor: 0, + bottomEdgeAnchor: 0, + relativeToOriginalWindowSize: true, + useLegacyBottomAndRightAnchors: false, + ...behaviorProperties, + }, + ], + effects: [], + animations: [ + { + name: 'animation', + directions: [ + { + sprites: [ + { + originPoint: { x: 50, y: 50 }, + centerPoint: { x: 50, y: 50 }, + points: [], + hasCustomCollisionMask: false, + customCollisionMask: [], + }, + ], + }, + ], + }, + ], + }); + object.setUnscaledWidthAndHeight(100, 100); + object.setCustomWidthAndHeight(10, 10); + runtimeScene.addObject(object); + return object; + }; + describe('(anchor horizontal edge)', function () { ['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => { it(`anchors the ${objectEdge} edge of object to window left (fixed)`, function () { @@ -200,5 +244,24 @@ describe('gdjs.AnchorRuntimeBehavior', function () { expect(object.getY()).to.equal(1000); expect(object.getWidth()).to.equal(10); }); + + it('can fill the screen with an object (with custom origin)', function () { + const object = createSpriteWithOriginAtCenter({ + leftEdgeAnchor: 1, + topEdgeAnchor: 1, + rightEdgeAnchor: 2, + bottomEdgeAnchor: 2, + }); + object.setCustomWidthAndHeight(1000, 1000); + object.setPosition(500, 500); + runtimeScene.renderAndStep(1000 / 60); + + setGameResolutionSizeAndStep(2000, 2000); + + expect(object.getX()).to.equal(1000); + expect(object.getY()).to.equal(1000); + expect(object.getWidth()).to.equal(2000); + expect(object.getHeight()).to.equal(2000); + }); }); }); diff --git a/GDJS/tests/tests/Extensions/testspriteruntimeobject.js b/GDJS/tests/tests/Extensions/testspriteruntimeobject.js index 4376a38140a7..6ac96a44290e 100644 --- a/GDJS/tests/tests/Extensions/testspriteruntimeobject.js +++ b/GDJS/tests/tests/Extensions/testspriteruntimeobject.js @@ -62,6 +62,14 @@ return this._customHeight; } + setWidth(width) { + this._customWidth = width; + } + + setHeight(height) { + return this._customHeight = height; + } + getCenterX() { if (this._customCenterX === null) return super.getCenterX(); return this._customCenterX; From ddb6c94f98df0c8209aec9c8028013eb8c3bab38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Davy=20H=C3=A9lard?= Date: Tue, 17 Sep 2024 19:05:37 +0200 Subject: [PATCH 2/4] Optimize a bit. --- .../AnchorBehavior/anchorruntimebehavior.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Extensions/AnchorBehavior/anchorruntimebehavior.ts b/Extensions/AnchorBehavior/anchorruntimebehavior.ts index 60a0dc6d761b..eba11c0b47c6 100644 --- a/Extensions/AnchorBehavior/anchorruntimebehavior.ts +++ b/Extensions/AnchorBehavior/anchorruntimebehavior.ts @@ -272,9 +272,11 @@ namespace gdjs { ) { const width = right - left; this.owner.setX( - left + - ((this.owner.getX() - this.owner.getDrawableX()) * width) / - this.owner.getWidth() + this.owner.getX() === this.owner.getDrawableX() + ? left + : left + + ((this.owner.getX() - this.owner.getDrawableX()) * width) / + this.owner.getWidth() ); this.owner.setWidth(width); } else { @@ -299,9 +301,11 @@ namespace gdjs { ) { const height = bottom - top; this.owner.setY( - top + - ((this.owner.getY() - this.owner.getDrawableY()) * height) / - this.owner.getHeight() + this.owner.getY() === this.owner.getDrawableY() + ? top + : top + + ((this.owner.getY() - this.owner.getDrawableY()) * height) / + this.owner.getHeight() ); this.owner.setHeight(height); } else { From 73787b0bc8212c17981d414c023e1452e6af9ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Davy=20H=C3=A9lard?= Date: Tue, 17 Sep 2024 19:20:11 +0200 Subject: [PATCH 3/4] Stronger test. --- .../tests/anchorruntimebehavior.spec.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js b/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js index f04975aa1156..9c7c47724681 100644 --- a/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js +++ b/Extensions/AnchorBehavior/tests/anchorruntimebehavior.spec.js @@ -83,7 +83,7 @@ describe('gdjs.AnchorRuntimeBehavior', function () { leftEdgeAnchor: 0, topEdgeAnchor: 0, bottomEdgeAnchor: 0, - relativeToOriginalWindowSize: true, + relativeToOriginalWindowSize: false, useLegacyBottomAndRightAnchors: false, ...behaviorProperties, }, @@ -246,22 +246,24 @@ describe('gdjs.AnchorRuntimeBehavior', function () { }); it('can fill the screen with an object (with custom origin)', function () { + setGameResolutionSizeAndStep(1000, 500); + const object = createSpriteWithOriginAtCenter({ leftEdgeAnchor: 1, topEdgeAnchor: 1, rightEdgeAnchor: 2, bottomEdgeAnchor: 2, }); - object.setCustomWidthAndHeight(1000, 1000); - object.setPosition(500, 500); + object.setCustomWidthAndHeight(1000, 500); + object.setPosition(500, 250); runtimeScene.renderAndStep(1000 / 60); - setGameResolutionSizeAndStep(2000, 2000); + setGameResolutionSizeAndStep(2000, 3000); expect(object.getX()).to.equal(1000); - expect(object.getY()).to.equal(1000); + expect(object.getY()).to.equal(1500); expect(object.getWidth()).to.equal(2000); - expect(object.getHeight()).to.equal(2000); + expect(object.getHeight()).to.equal(3000); }); }); }); From 900e010c6cfe713ba81548d276e27dd497382d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Davy=20H=C3=A9lard?= Date: Wed, 18 Sep 2024 13:24:12 +0200 Subject: [PATCH 4/4] Review change: remove useless return. --- GDJS/tests/tests/Extensions/testspriteruntimeobject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GDJS/tests/tests/Extensions/testspriteruntimeobject.js b/GDJS/tests/tests/Extensions/testspriteruntimeobject.js index 6ac96a44290e..4be8e0da3a9a 100644 --- a/GDJS/tests/tests/Extensions/testspriteruntimeobject.js +++ b/GDJS/tests/tests/Extensions/testspriteruntimeobject.js @@ -67,7 +67,7 @@ } setHeight(height) { - return this._customHeight = height; + this._customHeight = height; } getCenterX() {