diff --git a/src/gameobjects/nineslice/NineSlice.js b/src/gameobjects/nineslice/NineSlice.js index 2ff1d5b061..db7ff6bcdd 100644 --- a/src/gameobjects/nineslice/NineSlice.js +++ b/src/gameobjects/nineslice/NineSlice.js @@ -1191,6 +1191,32 @@ var NineSlice = new Class({ return this.updateDisplayOrigin(); }, + /** + * Sets the texture frame and refreshes the UV coordinates of this Nine Slice. + * + * The UV coordinates are updated even when `updateSize` is `false`. + * + * @method Phaser.GameObjects.NineSlice#setFrame + * @since 3.60.0 + * + * @param {(string|number|Phaser.Textures.Frame)} frame - The name or index of the frame within the Texture, or a Frame instance. + * @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object? + * @param {boolean} [updateOrigin=true] - Should this call adjust the origin of the Game Object? + * + * @return {this} This Game Object instance. + */ + setFrame: function (frame, updateSize, updateOrigin) + { + Components.Texture.setFrame.call(this, frame, updateSize, updateOrigin); + + if (updateSize === false) + { + this.updateUVs(); + } + + return this; + }, + /** * Resets the size of this Nine Slice Game Object to match the current texture frame. * diff --git a/tests/gameobjects/nineslice/NineSlice.test.js b/tests/gameobjects/nineslice/NineSlice.test.js new file mode 100644 index 0000000000..ca62b375ae --- /dev/null +++ b/tests/gameobjects/nineslice/NineSlice.test.js @@ -0,0 +1,124 @@ +var NineSlice = require('../../../src/gameobjects/nineslice/NineSlice'); +var Frame = require('../../../src/textures/Frame'); + +function createNineSlice (is3Slice) +{ + var frames = {}; + var texture = { + key: 'atlas', + source: [ { width: 256, height: 256 } ], + get: function (name) { return frames[name]; } + }; + + frames.first = new Frame(texture, 'first', 0, 0, 0, 64, 32); + frames.second = new Frame(texture, 'second', 0, 128, 64, 64, 64); + + var textures = { + get: function () { return texture; }, + getFrame: function (key, name) { return frames[name]; } + }; + var scene = { + textures: textures, + sys: { + textures: textures, + queueDepthSort: function () {} + } + }; + + return new NineSlice(scene, 0, 0, 'atlas', 'first', 128, 96, 8, 8, is3Slice ? 0 : 8, is3Slice ? 0 : 8); +} + +describe('NineSlice', function () +{ + [ true, false ].forEach(function (is3Slice) + { + describe(is3Slice ? '3-slice setFrame' : '9-slice setFrame', function () + { + [ true, false ].forEach(function (updateOrigin) + { + it('should refresh UVs without resizing when updateOrigin is ' + updateOrigin, function () + { + var slice = createNineSlice(is3Slice); + var width = slice.width; + var height = slice.height; + var positions = slice.vertices.map(function (vertex) + { + return [ vertex.vx, vertex.vy ]; + }); + + expect(slice.vertices[0].u).toBe(0); + expect(slice.vertices[0].v).toBe(1); + + var result = slice.setFrame('second', false, updateOrigin); + + expect(result).toBe(slice); + expect(slice.frame.name).toBe('second'); + expect(slice.vertices[0].u).toBe(0.5); + expect(slice.vertices[0].v).toBe(0.75); + expect(slice.vertices[2].u).toBe(0.53125); + expect(slice.width).toBe(width); + expect(slice.height).toBe(height); + expect(slice.vertices.map(function (vertex) + { + return [ vertex.vx, vertex.vy ]; + })).toEqual(positions); + }); + }); + + it('should refresh UVs when passed a Frame instance without resizing', function () + { + var slice = createNineSlice(is3Slice); + var frame = slice.texture.get('second'); + var height = slice.height; + + slice.setFrame(frame, false, false); + + expect(slice.frame).toBe(frame); + expect(slice.vertices[0].u).toBe(0.5); + expect(slice.vertices[0].v).toBe(0.75); + expect(slice.height).toBe(height); + }); + + it('should preserve the default size update behavior', function () + { + var slice = createNineSlice(is3Slice); + + slice.setFrame('second'); + + expect(slice.vertices[0].u).toBe(0.5); + expect(slice.vertices[0].v).toBe(0.75); + expect(slice.width).toBe(128); + expect(slice.height).toBe(is3Slice ? 64 : 96); + }); + + it('should refresh UVs through setTexture without changing size or origin', function () + { + var slice = createNineSlice(is3Slice); + var frame = slice.texture.get('second'); + frame.customPivot = true; + frame.pivotX = 0.1; + frame.pivotY = 0.2; + slice.setOrigin(0.25, 0.75); + + var height = slice.height; + var positions = slice.vertices.map(function (vertex) + { + return [ vertex.vx, vertex.vy ]; + }); + + slice.setTexture('atlas', 'second', false, false); + + expect(slice.vertices[0].u).toBe(0.5); + expect(slice.vertices[0].v).toBe(0.75); + expect(slice.width).toBe(128); + expect(slice.height).toBe(height); + expect(slice.originX).toBe(0.25); + expect(slice.originY).toBe(0.75); + expect(slice.vertices.map(function (vertex) + { + return [ vertex.vx, vertex.vy ]; + })).toEqual(positions); + }); + }); + }); +});