diff --git a/README.md b/README.md index 4d496847..ce08fcb7 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Significant API changes: * PixiPatch no longer needed, all features that it patched are now native in Pixi :) * Removed: Sprite.offset, center, topLeft, topRight, bottomRight, bottomLeft and bounds as no longer needed internally. Use Sprite.getBounds() to derive them. * Button now extends Phaser.Image not Phaser.Sprite, all the same functionality as before remains, just no animations or physics body. +* Text.content has been replaced with Text.text. New features: @@ -80,6 +81,10 @@ New features: * You can now use the hitArea property on Sprites and Image objects. hitArea can be a geometry object (Rectangle, Circle, Polygon, Ellipse) and is used in pointerOver checks. * InputManager.getLocalPosition(displayObject, pointer, output) will return the local coordinates of the specified displayObject and pointer. * InputManager.hitTest will test for pointer hits against a Sprite/Image, its hitArea (if set) or any of its children. +* Text has lots of new methods to help style it: Text.fill, Text.align, Text.stroke, etc. +* Text now works happily with font names with spaces in them. +* Text.setShadow applies a drop shadow to the Text being rendered. Control the x, y, color and blur. +* Text.lineSpacing allows you to control the spacing between each line that is rendered. New Examples: diff --git a/examples/wip/destroy.js b/examples/wip/destroy.js new file mode 100644 index 00000000..698e0a4b --- /dev/null +++ b/examples/wip/destroy.js @@ -0,0 +1,49 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }, false); + +function preload() { + + game.load.image('pic', 'assets/pics/backscroll.png'); + +} + +var sprite; +var sprite2; +var g; +var p; + +function create() { + + game.stage.backgroundColor = '#ff5500'; + + game.renderer.useFillRect = false; + + sprite = game.add.sprite(0.5, 0, 'pic'); + sprite2 = game.add.sprite(0, 300, 'pic'); + + game.input.onDown.add(tint, this); + + // game.add.tween(sprite).to({y: 500}, 3000, Phaser.Easing.Linear.None, true); + + // p = new PIXI.Point(43, 45); + +} + +function tint() { + + sprite.destroy(); + // sprite.tint = Math.random() * 0xFFFFFF; + // sprite2.tint = Math.random() * 0xFFFFFF; + +} + +function update() { + + +} + +function render() { + + // game.debug.renderText(sprite.position.y, 32, 32); + +} diff --git a/examples/wip/pixi1.js b/examples/wip/pixi1.js index a426e891..46403d4e 100644 --- a/examples/wip/pixi1.js +++ b/examples/wip/pixi1.js @@ -14,7 +14,9 @@ var p; function create() { - // game.stage.backgroundColor = '#ff5500'; + game.stage.backgroundColor = '#ff5500'; + + game.renderer.useFillRect = false; sprite = game.add.sprite(0.5, 0, 'pic'); @@ -29,7 +31,7 @@ function create() { // game.input.onDown.add(tint, this); - // game.add.tween(sprite).to({y: 500}, 3000, Phaser.Easing.Linear.None, true); + game.add.tween(sprite).to({y: 500}, 3000, Phaser.Easing.Linear.None, true); p = new PIXI.Point(43, 45); diff --git a/examples/wip/text.js b/examples/wip/text.js new file mode 100644 index 00000000..c5597b35 --- /dev/null +++ b/examples/wip/text.js @@ -0,0 +1,60 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }, false); +// var game = new Phaser.Game(800, 600, Phaser.WEBGL, 'phaser-example', { preload: preload, create: create, update: update, render: render }, false); + +function preload() { + + game.load.image('pic', 'assets/pics/backscroll.png'); + +} + +var text; + +function create() { + + game.stage.backgroundColor = '#c48844'; + + text = game.add.text(game.world.centerX, game.world.centerY, "- phaser -\nwith a sprinkle of\npixi dust"); + + text.anchor.setTo(0.5); + + text.font = 'Art of Fighting 2'; + // text.font = 'Arial'; + text.fontSize = 40; + // text.fontWeight = 'bold italic'; + + // x0, y0 - x1, y1 + var grd = text.context.createLinearGradient(0, 0, 0, text.canvas.height); + + grd.addColorStop(0, '#8ED6FF'); + grd.addColorStop(1, '#004CB3'); + + // text.fill = '#ff0044'; + // text.lineSpacing = 16; + text.fill = grd; + text.align = 'center'; + text.stroke = '#ff00ff'; + text.strokeThickness = 2; + + text.setShadow(5, 5, 'rgba(0,0,0,0.5)', 5); + + game.input.onDown.add(change, this); + +} + +function change() { + + text.tint = Math.random() * 0xFFFFFF; + +} + +function update() { + + +} + +function render() { + + // game.debug.renderText(sprite.position.y, 32, 32); + +} diff --git a/src/core/World.js b/src/core/World.js index 943d1f99..e6ec490c 100644 --- a/src/core/World.js +++ b/src/core/World.js @@ -64,7 +64,7 @@ Phaser.World.prototype.boot = function () { /** * This is called automatically after the plugins preUpdate and before the State.update. -* Most objects have preUpdate methods and it's where initial movement, drawing and calculations are done. +* Most objects have preUpdate methods and it's where initial movement and positioning is done. * * @method Phaser.World#preUpdate */ diff --git a/src/gameobjects/Text.js b/src/gameobjects/Text.js index fbd1b6bd..41b7724f 100644 --- a/src/gameobjects/Text.js +++ b/src/gameobjects/Text.js @@ -32,17 +32,6 @@ Phaser.Text = function (game, x, y, text, style) { */ this.exists = true; - /** - * @property {boolean} alive - This is a handy little var your game can use to determine if an object is alive or not, it doesn't effect rendering. - * @default - */ - this.alive = true; - - /** - * @property {Phaser.Group} group - The parent Group of this Text object. - */ - this.group = null; - /** * @property {string} name - The user defined name given to this object. * @default @@ -56,39 +45,9 @@ Phaser.Text = function (game, x, y, text, style) { this.type = Phaser.TEXT; /** - * @property {string} _text - Internal value. - * @private + * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container. */ - this._text = text; - - /** - * @property {string} _style - Internal value. - * @private - */ - this._style = style; - - PIXI.Text.call(this, text, style); - - /** - * @property {Phaser.Point} position - The position of this Text object in world space. - */ - this.position.x = this.x = x; - this.position.y = this.y = y; - - /** - * The anchor sets the origin point of the texture. - * The default is 0,0 this means the textures origin is the top left - * Setting than anchor to 0.5,0.5 means the textures origin is centered - * Setting the anchor to 1,1 would mean the textures origin points will be the bottom right - * - * @property {Phaser.Point} anchor - The anchor around which rotation and scaling takes place. - */ - this.anchor = new Phaser.Point(); - - /** - * @property {Phaser.Point} scale - The scale of the object when rendered. By default it's set to 1 (no scale). You can modify it via scale.x or scale.y or scale.setTo(x, y). A value of 1 means no change to the scale, 0.5 means "half the size", 2 means "twice the size", etc. - */ - this.scale = new Phaser.Point(1, 1); + this.world = new Phaser.Point(x, y); /** * An object that is fixed to the camera ignores the position of any ancestors in the display list and uses its x/y coordinates as offsets from the top left of the camera. @@ -98,44 +57,38 @@ Phaser.Text = function (game, x, y, text, style) { this.fixedToCamera = false; /** - * @property {Phaser.Point} cameraOffset - If this object is fixed to the camera then use this Point to specify how far away from the Camera x/y it's rendered. - */ - this.cameraOffset = new Phaser.Point(x, y); - - /** - * @property {object} _cache - A mini cache for storing all of the calculated values. + * @property {string} _text - Internal cache var. * @private */ - this._cache = { - - dirty: false, - - // Transform cache - a00: 1, - a01: 0, - a02: x, - a10: 0, - a11: 1, - a12: y, - id: 1, - - // The previous calculated position - x: -1, - y: -1, - - // The actual scale values based on the worldTransform - scaleX: 1, - scaleY: 1 - - }; - - this._cache.x = this.x; - this._cache.y = this.y; + this._text = text; /** - * @property {boolean} renderable - A renderable object will be rendered to the context each frame. + * @property {string} _font - Internal cache var. + * @private */ - this.renderable = true; + this._font = ''; + + /** + * @property {number} _fontSize - Internal cache var. + * @private + */ + this._fontSize = 32; + + /** + * @property {string} _fontWeight - Internal cache var. + * @private + */ + this._fontWeight = 'normal'; + + /** + * @property {number} lineSpacing - Additional spacing (in pixels) between each line of text if multi-line. + * @private + */ + this._lineSpacing = 0; + + PIXI.Text.call(this, text, style); + + this.position.set(x, y); }; @@ -143,34 +96,35 @@ Phaser.Text.prototype = Object.create(PIXI.Text.prototype); Phaser.Text.prototype.constructor = Phaser.Text; /** -* Automatically called by World.update. -* @method Phaser.Text.prototype.update +* Automatically called by World.preUpdate. +* @method Phaser.Text.prototype.preUpdate */ -Phaser.Text.prototype.update = function() { +Phaser.Text.prototype.preUpdate = function() { - if (!this.exists) + if (!this.exists || !this.parent.exists) { - return; + // Reset the renderOrderID + return false; } - if (this.fixedToCamera) + this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty); + +} + +/** +* Automatically called by World.postUpdate. +* @method Phaser.Text.prototype.postUpdate +*/ +Phaser.Text.prototype.postUpdate = function() { + + if (this.exists) { - this.x = this.game.camera.view.x + this.cameraOffset.x; - this.y = this.game.camera.view.y + this.cameraOffset.y; + if (this.fixedToCamera) + { + // this.position.x = this.game.camera.view.x + this.x; + // this.position.y = this.game.camera.view.y + this.y; + } } - - this._cache.dirty = false; - - this._cache.x = this.x; - this._cache.y = this.y; - - if (this.position.x != this._cache.x || this.position.y != this._cache.y) - { - this.position.x = this._cache.x; - this.position.y = this._cache.y; - this._cache.dirty = true; - } - } /** @@ -178,11 +132,18 @@ Phaser.Text.prototype.update = function() { */ Phaser.Text.prototype.destroy = function() { - if (this.group) + if (this.filters) { - this.group.remove(this); + this.filters = null; } + if (this.parent) + { + this.parent.remove(this); + } + + this.texture.destroy(); + if (this.canvas.parentNode) { this.canvas.parentNode.removeChild(this.canvas); @@ -194,11 +155,186 @@ Phaser.Text.prototype.destroy = function() { } this.exists = false; + this.visible = false; - this.group = null; + this.game = null; } +/** +* @method Phaser.Text.prototype.setShadow +* @param {number} [x=0] - The shadowOffsetX value in pixels. This is how far offset horizontally the shadow effect will be. +* @param {number} [y=0] - The shadowOffsetY value in pixels. This is how far offset vertically the shadow effect will be. +* @param {string} [color='rgba(0,0,0,0)'] - The color of the shadow, as given in CSS rgba format. Set the alpha component to 0 to disable the shadow. +* @param {number} [blur=0] - The shadowBlur value. Make the shadow softer by applying a Gaussian blur to it. A number from 0 (no blur) up to approx. 10 (depending on scene). +*/ +Phaser.Text.prototype.setShadow = function(x, y, color, blur) { + + this.style.shadowOffsetX = x || 0; + this.style.shadowOffsetY = y || 0; + this.style.shadowColor = color || 'rgba(0,0,0,0)'; + this.style.shadowBlur = blur || 0; + this.dirty = true; + +} + +/** +* Set the style of the text by passing a single style object to it. +* +* @method Phaser.Text.prototype.setStyle +* @param [style] {Object} The style parameters +* @param [style.font='bold 20pt Arial'] {String} The style and size of the font +* @param [style.fill='black'] {Object} A canvas fillstyle that will be used on the text eg 'red', '#00FF00' +* @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text +* @param [style.stroke='black'] {String} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00' +* @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) +* @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used +* @param [style.wordWrapWidth=100] {Number} The width at which text will wrap +*/ +Phaser.Text.prototype.setStyle = function(style) { + + style = style || {}; + style.font = style.font || 'bold 20pt Arial'; + style.fill = style.fill || 'black'; + style.align = style.align || 'left'; + style.stroke = style.stroke || 'black'; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 + style.strokeThickness = style.strokeThickness || 0; + style.wordWrap = style.wordWrap || false; + style.wordWrapWidth = style.wordWrapWidth || 100; + style.shadowOffsetX = style.shadowOffsetX || 0; + style.shadowOffsetY = style.shadowOffsetY || 0; + style.shadowColor = style.shadowColor || 'rgba(0,0,0,0)'; + style.shadowBlur = style.shadowBlur || 0; + + this.style = style; + this.dirty = true; + +}; + +/** +* Renders text. This replaces the Pixi.Text.updateText function as we need a few extra bits in here. +* +* @method Phaser.Text.prototype.updateText +* @private +*/ +Phaser.Text.prototype.updateText = function() { + + this.context.font = this.style.font; + + var outputText = this.text; + + // word wrap + // preserve original text + if(this.style.wordWrap)outputText = this.runWordWrap(this.text); + + //split text into lines + var lines = outputText.split(/(?:\r\n|\r|\n)/); + + //calculate text width + var lineWidths = []; + var maxLineWidth = 0; + for (var i = 0; i < lines.length; i++) + { + var lineWidth = this.context.measureText(lines[i]).width; + lineWidths[i] = lineWidth; + maxLineWidth = Math.max(maxLineWidth, lineWidth); + } + this.canvas.width = maxLineWidth + this.style.strokeThickness; + + //calculate text height + var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness + this._lineSpacing + this.style.shadowOffsetY; + this.canvas.height = lineHeight * lines.length; + + if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height); + + //set canvas text styles + this.context.fillStyle = this.style.fill; + this.context.font = this.style.font; + + this.context.strokeStyle = this.style.stroke; + this.context.lineWidth = this.style.strokeThickness; + + this.context.shadowOffsetX = this.style.shadowOffsetX; + this.context.shadowOffsetY = this.style.shadowOffsetY; + this.context.shadowColor = this.style.shadowColor; + this.context.shadowBlur = this.style.shadowBlur; + + this.context.textBaseline = 'top'; + + //draw lines line by line + for (i = 0; i < lines.length; i++) + { + var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); + + if(this.style.align === 'right') + { + linePosition.x += maxLineWidth - lineWidths[i]; + } + else if(this.style.align === 'center') + { + linePosition.x += (maxLineWidth - lineWidths[i]) / 2; + } + + linePosition.y += this._lineSpacing; + + if(this.style.stroke && this.style.strokeThickness) + { + this.context.strokeText(lines[i], linePosition.x, linePosition.y); + } + + if(this.style.fill) + { + this.context.fillText(lines[i], linePosition.x, linePosition.y); + } + } + + this.updateTexture(); +}; + +/** +* Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal bounds. +* +* @method Phaser.Text.prototype.runWordWrap +* @private +*/ +Phaser.Text.prototype.runWordWrap = function(text) { + + var result = ''; + var lines = text.split('\n'); + + for (var i = 0; i < lines.length; i++) + { + var spaceLeft = this.style.wordWrapWidth; + var words = lines[i].split(' '); + + for (var j = 0; j < words.length; j++) + { + var wordWidth = this.context.measureText(words[j]).width; + var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width; + + if (wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is greater than the word wrap width. + if (j > 0) + { + result += '\n'; + } + result += words[j] + ' '; + spaceLeft = this.style.wordWrapWidth - wordWidth; + } + else + { + spaceLeft -= wordWidthWithSpace; + result += words[j] + ' '; + } + } + result += '\n'; + } + + return result; + +}; + /** * Indicates the rotation of the Text, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90. @@ -219,45 +355,11 @@ Object.defineProperty(Phaser.Text.prototype, 'angle', { }); /** -* The x coordinate of this object in world space. -* @name Phaser.Text#x -* @property {number} x - The x coordinate of this object in world space. +* The text string to be displayed by this Text object, taking into account the style settings. +* @name Phaser.Text#text +* @property {string} text - The text string to be displayed by this Text object, taking into account the style settings. */ -Object.defineProperty(Phaser.Text.prototype, 'x', { - - get: function() { - return this.position.x; - }, - - set: function(value) { - this.position.x = value; - } - -}); - -/** -* The y coordinate of this object in world space. -* @name Phaser.Text#y -* @property {number} y - The y coordinate of this object in world space. -*/ -Object.defineProperty(Phaser.Text.prototype, 'y', { - - get: function() { - return this.position.y; - }, - - set: function(value) { - this.position.y = value; - } - -}); - -/** -* The string to be rendered by this Text object. -* @name Phaser.Text#content -* @property {string} content - The string to be rendered by this Text object. -*/ -Object.defineProperty(Phaser.Text.prototype, 'content', { +Object.defineProperty(Phaser.Text.prototype, 'text', { get: function() { return this._text; @@ -265,11 +367,10 @@ Object.defineProperty(Phaser.Text.prototype, 'content', { set: function(value) { - // Let's not update unless needed, this way we can safely update the text in a core loop without constant re-draws if (value !== this._text) { - this._text = value; - this.setText(value); + this._text = value.toString() || ' '; + this.dirty = true; } } @@ -277,23 +378,312 @@ Object.defineProperty(Phaser.Text.prototype, 'content', { }); /** -* The font the text will be rendered in. * @name Phaser.Text#font -* @property {string} font - The font the text will be rendered in. +* @property {string} font - The font the text will be rendered in, i.e. 'Arial'. Must be loaded in the browser before use. */ Object.defineProperty(Phaser.Text.prototype, 'font', { get: function() { - return this._style; + return this._font; }, set: function(value) { - // Let's not update unless needed, this way we can safely update the text in a core loop without constant re-draws - if (value !== this._style) + if (value !== this._font) { - this._style = value; - this.setStyle(value); + this._font = value.trim(); + this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'"; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#fontSize +* @property {number} fontSize - The size of the font in pixels. +*/ +Object.defineProperty(Phaser.Text.prototype, 'fontSize', { + + get: function() { + return this._fontSize; + }, + + set: function(value) { + + value = parseInt(value); + + if (value !== this._fontSize) + { + this._fontSize = value; + this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'"; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#fontWeight +* @property {number} fontWeight - The weight of the font: 'normal', 'bold', 'italic'. You can combine settings too, such as 'bold italic'. +*/ +Object.defineProperty(Phaser.Text.prototype, 'fontWeight', { + + get: function() { + return this._fontWeight; + }, + + set: function(value) { + + if (value !== this._fontWeight) + { + this._fontWeight = value; + this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'"; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#fill +* @property {object} fill - A canvas fillstyle that will be used on the text eg 'red', '#00FF00'. +*/ +Object.defineProperty(Phaser.Text.prototype, 'fill', { + + get: function() { + return this.style.fill; + }, + + set: function(value) { + + if (value !== this.style.fill) + { + this.style.fill = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#align +* @property {string} align - Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text. +*/ +Object.defineProperty(Phaser.Text.prototype, 'align', { + + get: function() { + return this.style.align; + }, + + set: function(value) { + + if (value !== this.style.align) + { + this.style.align = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#stroke +* @property {string} stroke - A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'. +*/ +Object.defineProperty(Phaser.Text.prototype, 'stroke', { + + get: function() { + return this.style.stroke; + }, + + set: function(value) { + + if (value !== this.style.stroke) + { + this.style.stroke = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#strokeThickness +* @property {number} strokeThickness - A number that represents the thickness of the stroke. Default is 0 (no stroke) +*/ +Object.defineProperty(Phaser.Text.prototype, 'strokeThickness', { + + get: function() { + return this.style.strokeThickness; + }, + + set: function(value) { + + if (value !== this.style.strokeThickness) + { + this.style.strokeThickness = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#wordWrap +* @property {boolean} wordWrap - Indicates if word wrap should be used. +*/ +Object.defineProperty(Phaser.Text.prototype, 'wordWrap', { + + get: function() { + return this.style.wordWrap; + }, + + set: function(value) { + + if (value !== this.style.wordWrap) + { + this.style.wordWrap = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#wordWrapWidth +* @property {number} wordWrapWidth - The width at which text will wrap. +*/ +Object.defineProperty(Phaser.Text.prototype, 'wordWrapWidth', { + + get: function() { + return this.style.wordWrapWidth; + }, + + set: function(value) { + + if (value !== this.style.wordWrapWidth) + { + this.style.wordWrapWidth = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#lineSpacing +* @property {number} lineSpacing - Additional spacing (in pixels) between each line of text if multi-line. +*/ +Object.defineProperty(Phaser.Text.prototype, 'lineSpacing', { + + get: function() { + return this._lineSpacing; + }, + + set: function(value) { + + if (value !== this._lineSpacing) + { + this._lineSpacing = parseFloat(value); + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#shadowOffsetX +* @property {number} shadowOffsetX - The shadowOffsetX value in pixels. This is how far offset horizontally the shadow effect will be. +*/ +Object.defineProperty(Phaser.Text.prototype, 'shadowOffsetX', { + + get: function() { + return this.style.shadowOffsetX; + }, + + set: function(value) { + + if (value !== this.style.shadowOffsetX) + { + this.style.shadowOffsetX = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#shadowOffsetY +* @property {number} shadowOffsetY - The shadowOffsetY value in pixels. This is how far offset vertically the shadow effect will be. +*/ +Object.defineProperty(Phaser.Text.prototype, 'shadowOffsetY', { + + get: function() { + return this.style.shadowOffsetY; + }, + + set: function(value) { + + if (value !== this.style.shadowOffsetY) + { + this.style.shadowOffsetY = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#shadowColor +* @property {string} shadowColor - The color of the shadow, as given in CSS rgba format. Set the alpha component to 0 to disable the shadow. +*/ +Object.defineProperty(Phaser.Text.prototype, 'shadowColor', { + + get: function() { + return this.style.shadowColor; + }, + + set: function(value) { + + if (value !== this.style.shadowColor) + { + this.style.shadowColor = value; + this.dirty = true; + } + + } + +}); + +/** +* @name Phaser.Text#shadowBlur +* @property {number} shadowBlur - The shadowBlur value. Make the shadow softer by applying a Gaussian blur to it. A number from 0 (no blur) up to approx. 10 (depending on scene). +*/ +Object.defineProperty(Phaser.Text.prototype, 'shadowBlur', { + + get: function() { + return this.style.shadowBlur; + }, + + set: function(value) { + + if (value !== this.style.shadowBlur) + { + this.style.shadowBlur = value; + this.dirty = true; } } diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 79b8c715..768ef4e4 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -41,21 +41,6 @@ PIXI.scaleModes = { NEAREST:1 }; -// Canvas specific controls -PIXI.canvas = { - - // If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. - // Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. - FILL_RECT: true, - - // If the Stage is transparent Pixi will use clearRect to clear the canvas every frame. - // Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. - CLEAR_RECT: true, - - // If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation. Handy for crisp pixel art and speed on legacy devices. - PX_ROUND: false -} - // interaction frequency PIXI.INTERACTION_FREQUENCY = 30; PIXI.AUTO_PREVENT_DEFAULT = true; \ No newline at end of file diff --git a/src/pixi/display/Sprite.js b/src/pixi/display/Sprite.js index 1d065377..c95e1277 100644 --- a/src/pixi/display/Sprite.js +++ b/src/pixi/display/Sprite.js @@ -345,7 +345,7 @@ PIXI.Sprite.prototype._renderCanvas = function(renderSession) // allow for trimming - if (PIXI.canvas.PX_ROUND) + if (renderSession.roundPixels) { context.setTransform(transform.a, transform.c, transform.b, transform.d, Math.floor(transform.tx), Math.floor(transform.ty)); } diff --git a/src/pixi/display/SpriteBatch.js b/src/pixi/display/SpriteBatch.js index ed3b9211..d23013f2 100644 --- a/src/pixi/display/SpriteBatch.js +++ b/src/pixi/display/SpriteBatch.js @@ -91,7 +91,7 @@ PIXI.SpriteBatch.prototype._renderCanvas = function(renderSession) // alow for trimming - if (PIXI.canvas.PX_ROUND) + if (renderSession.roundPixels) { context.setTransform(transform.a, transform.c, transform.b, transform.d, Math.floor(transform.tx), Math.floor(transform.ty)); } diff --git a/src/pixi/renderers/canvas/CanvasRenderer.js b/src/pixi/renderers/canvas/CanvasRenderer.js index 9c93ee6f..d2e64d91 100644 --- a/src/pixi/renderers/canvas/CanvasRenderer.js +++ b/src/pixi/renderers/canvas/CanvasRenderer.js @@ -19,6 +19,27 @@ PIXI.CanvasRenderer = function(width, height, view, transparent) this.type = PIXI.CANVAS_RENDERER; + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. + * If the Stage is transparent Pixi will use clearRect to clear the canvas every frame. + * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. + * + * @property clearBeforeRender + * @type Boolean + * @default + */ + this.clearBeforeRender = true; + + /** + * If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation. + * Handy for crisp pixel art and speed on legacy devices. + * + * @property roundPixels + * @type Boolean + * @default + */ + this.roundPixels = false; /** * Whether the render view is transparent @@ -165,12 +186,12 @@ PIXI.CanvasRenderer.prototype.render = function(stage) this.context.setTransform(1,0,0,1,0,0); this.context.globalAlpha = 1; - if (!this.transparent && PIXI.canvas.FILL_RECT) + if (!this.transparent && this.clearBeforeRender) { this.context.fillStyle = stage.backgroundColorString; this.context.fillRect(0, 0, this.width, this.height); } - else if (this.transparent && PIXI.canvas.CLEAR_RECT) + else if (this.transparent && this.clearBeforeRender) { this.context.clearRect(0, 0, this.width, this.height); }