Skip to content

Commit 05922d6

Browse files
committed
Lots of fixes to the Image class to restore texture loading and fix cropping so it works exactly the same as the Sprite now.
1 parent 6fbaa36 commit 05922d6

2 files changed

Lines changed: 176 additions & 56 deletions

File tree

src/gameobjects/Image.js

Lines changed: 170 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,8 @@ Phaser.Image = function (game, x, y, key, frame) {
6262
*/
6363
this.key = key;
6464

65-
/**
66-
* @property {number} _frame - Internal cache var.
67-
* @private
68-
*/
69-
this._frame = 0;
70-
71-
/**
72-
* @property {string} _frameName - Internal cache var.
73-
* @private
74-
*/
75-
this._frameName = '';
76-
7765
PIXI.Sprite.call(this, PIXI.TextureCache['__default']);
7866

79-
this.loadTexture(key, frame);
80-
8167
this.position.set(x, y);
8268

8369
/**
@@ -100,11 +86,23 @@ Phaser.Image = function (game, x, y, key, frame) {
10086
*/
10187
this.input = null;
10288

89+
/**
90+
* @property {boolean} debug - Handy flag to use with Game.enableStep
91+
* @default
92+
*/
93+
this.debug = false;
94+
10395
/**
10496
* @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
10597
*/
10698
this.cameraOffset = new Phaser.Point();
10799

100+
/**
101+
* @property {Phaser.Rectangle} cropRect - The Rectangle used to crop the texture. Set this via Sprite.crop. Any time you modify this property directly you must call Sprite.updateCrop.
102+
* @default
103+
*/
104+
this.cropRect = null;
105+
108106
/**
109107
* A small internal cache:
110108
* 0 = previous position.x
@@ -121,6 +119,26 @@ Phaser.Image = function (game, x, y, key, frame) {
121119
*/
122120
this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0, 0 ];
123121

122+
/**
123+
* @property {Phaser.Rectangle} _crop - Internal cache var.
124+
* @private
125+
*/
126+
this._crop = null;
127+
128+
/**
129+
* @property {Phaser.Rectangle} _frame - Internal cache var.
130+
* @private
131+
*/
132+
this._frame = null;
133+
134+
/**
135+
* @property {Phaser.Rectangle} _bounds - Internal cache var.
136+
* @private
137+
*/
138+
this._bounds = new Phaser.Rectangle();
139+
140+
this.loadTexture(key, frame);
141+
124142
};
125143

126144
Phaser.Image.prototype = Object.create(PIXI.Sprite.prototype);
@@ -146,8 +164,10 @@ Phaser.Image.prototype.preUpdate = function() {
146164

147165
if (this.autoCull)
148166
{
167+
this._bounds.copyFrom(this.getBounds());
168+
149169
// Won't get rendered but will still get its transform updated
150-
this.renderable = this.game.world.camera.screenView.intersects(this.getBounds());
170+
this.renderable = this.game.world.camera.screenView.intersects(this._bounds);
151171
}
152172

153173
this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty);
@@ -218,55 +238,118 @@ Phaser.Image.prototype.loadTexture = function (key, frame) {
218238

219239
frame = frame || 0;
220240

241+
this.key = key;
242+
243+
var smoothed = this.smoothed;
244+
221245
if (key instanceof Phaser.RenderTexture)
222246
{
223247
this.key = key.key;
224248
this.setTexture(key);
225-
return;
226249
}
227250
else if (key instanceof Phaser.BitmapData)
228251
{
229-
this.key = key;
230252
this.setTexture(key.texture);
231-
return;
232253
}
233254
else if (key instanceof PIXI.Texture)
234255
{
235-
this.key = key;
236256
this.setTexture(key);
237-
return;
238257
}
239258
else
240259
{
241260
if (key === null || typeof key === 'undefined')
242261
{
243262
this.key = '__default';
244263
this.setTexture(PIXI.TextureCache[this.key]);
245-
return;
246264
}
247265
else if (typeof key === 'string' && !this.game.cache.checkImageKey(key))
248266
{
267+
console.warn("Texture with key '" + key + "' not found.");
249268
this.key = '__missing';
250269
this.setTexture(PIXI.TextureCache[this.key]);
251-
return;
252270
}
271+
else
272+
{
273+
this.setTexture(new PIXI.Texture(PIXI.BaseTextureCache[key]));
274+
}
275+
}
276+
277+
this._frame = Phaser.Rectangle.clone(this.texture.frame);
278+
279+
if (!smoothed)
280+
{
281+
this.smoothed = false;
282+
}
283+
284+
};
285+
286+
/**
287+
* Sets the Texture frame the Sprite uses for rendering.
288+
* This is primarily an internal method used by Sprite.loadTexture, although you may call it directly.
289+
*
290+
* @method Phaser.Sprite#setFrame
291+
* @memberof Phaser.Sprite
292+
* @param {Phaser.Frame} frame - The Frame to be used by the Sprite texture.
293+
*/
294+
Phaser.Image.prototype.setFrame = function(frame) {
295+
296+
this._frame = frame;
253297

254-
this.key = key;
298+
this.texture.frame.x = frame.x;
299+
this.texture.frame.y = frame.y;
300+
this.texture.frame.width = frame.width;
301+
this.texture.frame.height = frame.height;
255302

256-
var frameData = this.game.cache.getFrameData(key);
303+
this.texture.crop.x = frame.x;
304+
this.texture.crop.y = frame.y;
305+
this.texture.crop.width = frame.width;
306+
this.texture.crop.height = frame.height;
257307

258-
if (typeof frame === 'string')
308+
if (frame.trimmed)
309+
{
310+
if (this.texture.trim)
259311
{
260-
this._frame = 0;
261-
this._frameName = frame;
262-
this.setTexture(PIXI.TextureCache[frameData.getFrameByName(frame).uuid]);
312+
this.texture.trim.x = frame.spriteSourceSizeX;
313+
this.texture.trim.y = frame.spriteSourceSizeY;
314+
this.texture.trim.width = frame.sourceSizeW;
315+
this.texture.trim.height = frame.sourceSizeH;
263316
}
264317
else
265318
{
266-
this._frame = frame;
267-
this._frameName = '';
268-
this.setTexture(PIXI.TextureCache[frameData.getFrame(frame).uuid]);
319+
this.texture.trim = { x: frame.spriteSourceSizeX, y: frame.spriteSourceSizeY, width: frame.sourceSizeW, height: frame.sourceSizeH };
269320
}
321+
322+
this.texture.width = frame.sourceSizeW;
323+
this.texture.height = frame.sourceSizeH;
324+
this.texture.frame.width = frame.sourceSizeW;
325+
this.texture.frame.height = frame.sourceSizeH;
326+
}
327+
328+
if (this.cropRect)
329+
{
330+
this.updateCrop();
331+
}
332+
else
333+
{
334+
if (this.game.renderType === Phaser.WEBGL)
335+
{
336+
PIXI.WebGLRenderer.updateTextureFrame(this.texture);
337+
}
338+
}
339+
340+
};
341+
342+
/**
343+
* Resets the Texture frame dimensions that the Sprite uses for rendering.
344+
*
345+
* @method Phaser.Sprite#resetFrame
346+
* @memberof Phaser.Sprite
347+
*/
348+
Phaser.Image.prototype.resetFrame = function() {
349+
350+
if (this._frame)
351+
{
352+
this.setFrame(this._frame);
270353
}
271354

272355
};
@@ -284,39 +367,72 @@ Phaser.Image.prototype.loadTexture = function (key, frame) {
284367
*/
285368
Phaser.Image.prototype.crop = function(rect) {
286369

287-
if (typeof rect === 'undefined' || rect === null)
370+
if (typeof copy === 'undefined') { copy = false; }
371+
372+
if (rect)
288373
{
289-
// Clear any crop that may be set
290-
if (this.texture.hasOwnProperty('sourceWidth'))
374+
if (copy && this.cropRect !== null)
375+
{
376+
this.cropRect.setTo(rect.x, rect.y, rect.width, rect.height);
377+
}
378+
else if (copy && this.cropRect === null)
379+
{
380+
this.cropRect = new Phaser.Rectangle(rect.x, rect.y, rect.width, rect.height);
381+
}
382+
else
291383
{
292-
this.texture.setFrame(new Phaser.Rectangle(0, 0, this.texture.sourceWidth, this.texture.sourceHeight));
384+
this.cropRect = rect;
293385
}
386+
387+
this.updateCrop();
294388
}
295389
else
296390
{
297-
// Do we need to clone the PIXI.Texture object?
298-
if (this.texture instanceof PIXI.Texture)
299-
{
300-
// Yup, let's rock it ...
301-
var local = {};
391+
this._crop = null;
392+
this.cropRect = null;
302393

303-
Phaser.Utils.extend(true, local, this.texture);
394+
this.resetFrame();
395+
}
304396

305-
local.sourceWidth = local.width;
306-
local.sourceHeight = local.height;
307-
local.frame = rect;
308-
local.width = rect.width;
309-
local.height = rect.height;
397+
};
310398

311-
this.texture = local;
399+
/**
400+
* If you have set a crop rectangle on this Sprite via Sprite.crop and since modified the Sprite.cropRect property (or the rectangle it references)
401+
* then you need to update the crop frame by calling this method.
402+
*
403+
* @method Phaser.Sprite#updateCrop
404+
* @memberof Phaser.Sprite
405+
*/
406+
Phaser.Image.prototype.updateCrop = function() {
312407

313-
this.texture.updateFrame = true;
314-
PIXI.Texture.frameUpdates.push(this.texture);
315-
}
316-
else
317-
{
318-
this.texture.setFrame(rect);
319-
}
408+
if (!this.cropRect)
409+
{
410+
return;
411+
}
412+
413+
this._crop = Phaser.Rectangle.clone(this.cropRect, this._crop);
414+
this._crop.x += this._frame.x;
415+
this._crop.y += this._frame.y;
416+
417+
var cx = Math.max(this._frame.x, this._crop.x);
418+
var cy = Math.max(this._frame.y, this._crop.y);
419+
var cw = Math.min(this._frame.right, this._crop.right) - cx;
420+
var ch = Math.min(this._frame.bottom, this._crop.bottom) - cy;
421+
422+
this.texture.crop.x = cx;
423+
this.texture.crop.y = cy;
424+
this.texture.crop.width = cw;
425+
this.texture.crop.height = ch;
426+
427+
this.texture.frame.width = Math.min(cw, this.cropRect.width);
428+
this.texture.frame.height = Math.min(ch, this.cropRect.height);
429+
430+
this.texture.width = this.texture.frame.width;
431+
this.texture.height = this.texture.frame.height;
432+
433+
if (this.game.renderType === Phaser.WEBGL)
434+
{
435+
PIXI.WebGLRenderer.updateTextureFrame(this.texture);
320436
}
321437

322438
};

src/loader/Cache.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,10 @@ Phaser.Cache.prototype = {
359359
var img = new Image();
360360
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAABVJREFUeF7NwIEAAAAAgKD9qdeocAMAoAABm3DkcAAAAABJRU5ErkJggg==";
361361

362-
this._images['__default'] = { url: null, data: img, spriteSheet: false };
362+
this._images['__default'] = { url: null, data: img };
363363
this._images['__default'].frame = new Phaser.Frame(0, 0, 0, 32, 32, '', '');
364+
this._images['__default'].frameData = new Phaser.FrameData();
365+
this._images['__default'].frameData.addFrame(new Phaser.Frame(0, 0, 0, 32, 32, null, this.game.rnd.uuid()));
364366

365367
PIXI.BaseTextureCache['__default'] = new PIXI.BaseTexture(img);
366368
PIXI.TextureCache['__default'] = new PIXI.Texture(PIXI.BaseTextureCache['__default']);
@@ -378,8 +380,10 @@ Phaser.Cache.prototype = {
378380
var img = new Image();
379381
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJ9JREFUeNq01ssOwyAMRFG46v//Mt1ESmgh+DFmE2GPOBARKb2NVjo+17PXLD8a1+pl5+A+wSgFygymWYHBb0FtsKhJDdZlncG2IzJ4ayoMDv20wTmSMzClEgbWYNTAkQ0Z+OJ+A/eWnAaR9+oxCF4Os0H8htsMUp+pwcgBBiMNnAwF8GqIgL2hAzaGFFgZauDPKABmowZ4GL369/0rwACp2yA/ttmvsQAAAABJRU5ErkJggg==";
380382

381-
this._images['__missing'] = { url: null, data: img, spriteSheet: false };
383+
this._images['__missing'] = { url: null, data: img };
382384
this._images['__missing'].frame = new Phaser.Frame(0, 0, 0, 32, 32, '', '');
385+
this._images['__missing'].frameData = new Phaser.FrameData();
386+
this._images['__missing'].frameData.addFrame(new Phaser.Frame(0, 0, 0, 32, 32, null, this.game.rnd.uuid()));
383387

384388
PIXI.BaseTextureCache['__missing'] = new PIXI.BaseTexture(img);
385389
PIXI.TextureCache['__missing'] = new PIXI.Texture(PIXI.BaseTextureCache['__missing']);

0 commit comments

Comments
 (0)