sprite.mjs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*!
  2. * @pixi/sprite - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/sprite is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. import { BLEND_MODES } from '@pixi/constants';
  9. import { Texture } from '@pixi/core';
  10. import { Bounds, Container } from '@pixi/display';
  11. import { Point, Rectangle, ObservablePoint } from '@pixi/math';
  12. import { settings } from '@pixi/settings';
  13. import { sign } from '@pixi/utils';
  14. /*! *****************************************************************************
  15. Copyright (c) Microsoft Corporation.
  16. Permission to use, copy, modify, and/or distribute this software for any
  17. purpose with or without fee is hereby granted.
  18. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  19. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  20. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  21. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  22. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  24. PERFORMANCE OF THIS SOFTWARE.
  25. ***************************************************************************** */
  26. /* global Reflect, Promise */
  27. var extendStatics = function(d, b) {
  28. extendStatics = Object.setPrototypeOf ||
  29. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  30. function (d, b) { for (var p in b) { if (b.hasOwnProperty(p)) { d[p] = b[p]; } } };
  31. return extendStatics(d, b);
  32. };
  33. function __extends(d, b) {
  34. extendStatics(d, b);
  35. function __() { this.constructor = d; }
  36. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  37. }
  38. var tempPoint = new Point();
  39. var indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
  40. /**
  41. * The Sprite object is the base for all textured objects that are rendered to the screen
  42. *
  43. * A sprite can be created directly from an image like this:
  44. *
  45. * ```js
  46. * let sprite = PIXI.Sprite.from('assets/image.png');
  47. * ```
  48. *
  49. * The more efficient way to create sprites is using a {@link PIXI.Spritesheet},
  50. * as swapping base textures when rendering to the screen is inefficient.
  51. *
  52. * ```js
  53. * PIXI.Loader.shared.add("assets/spritesheet.json").load(setup);
  54. *
  55. * function setup() {
  56. * let sheet = PIXI.Loader.shared.resources["assets/spritesheet.json"].spritesheet;
  57. * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
  58. * ...
  59. * }
  60. * ```
  61. * @memberof PIXI
  62. */
  63. var Sprite = /** @class */ (function (_super) {
  64. __extends(Sprite, _super);
  65. /** @param texture - The texture for this sprite. */
  66. function Sprite(texture) {
  67. var _this = _super.call(this) || this;
  68. _this._anchor = new ObservablePoint(_this._onAnchorUpdate, _this, (texture ? texture.defaultAnchor.x : 0), (texture ? texture.defaultAnchor.y : 0));
  69. _this._texture = null;
  70. _this._width = 0;
  71. _this._height = 0;
  72. _this._tint = null;
  73. _this._tintRGB = null;
  74. _this.tint = 0xFFFFFF;
  75. _this.blendMode = BLEND_MODES.NORMAL;
  76. _this._cachedTint = 0xFFFFFF;
  77. _this.uvs = null;
  78. // call texture setter
  79. _this.texture = texture || Texture.EMPTY;
  80. _this.vertexData = new Float32Array(8);
  81. _this.vertexTrimmedData = null;
  82. _this._transformID = -1;
  83. _this._textureID = -1;
  84. _this._transformTrimmedID = -1;
  85. _this._textureTrimmedID = -1;
  86. // Batchable stuff..
  87. // TODO could make this a mixin?
  88. _this.indices = indices;
  89. _this.pluginName = 'batch';
  90. /**
  91. * Used to fast check if a sprite is.. a sprite!
  92. * @member {boolean}
  93. */
  94. _this.isSprite = true;
  95. _this._roundPixels = settings.ROUND_PIXELS;
  96. return _this;
  97. }
  98. /** When the texture is updated, this event will fire to update the scale and frame. */
  99. Sprite.prototype._onTextureUpdate = function () {
  100. this._textureID = -1;
  101. this._textureTrimmedID = -1;
  102. this._cachedTint = 0xFFFFFF;
  103. // so if _width is 0 then width was not set..
  104. if (this._width) {
  105. this.scale.x = sign(this.scale.x) * this._width / this._texture.orig.width;
  106. }
  107. if (this._height) {
  108. this.scale.y = sign(this.scale.y) * this._height / this._texture.orig.height;
  109. }
  110. };
  111. /** Called when the anchor position updates. */
  112. Sprite.prototype._onAnchorUpdate = function () {
  113. this._transformID = -1;
  114. this._transformTrimmedID = -1;
  115. };
  116. /** Calculates worldTransform * vertices, store it in vertexData. */
  117. Sprite.prototype.calculateVertices = function () {
  118. var texture = this._texture;
  119. if (this._transformID === this.transform._worldID && this._textureID === texture._updateID) {
  120. return;
  121. }
  122. // update texture UV here, because base texture can be changed without calling `_onTextureUpdate`
  123. if (this._textureID !== texture._updateID) {
  124. this.uvs = this._texture._uvs.uvsFloat32;
  125. }
  126. this._transformID = this.transform._worldID;
  127. this._textureID = texture._updateID;
  128. // set the vertex data
  129. var wt = this.transform.worldTransform;
  130. var a = wt.a;
  131. var b = wt.b;
  132. var c = wt.c;
  133. var d = wt.d;
  134. var tx = wt.tx;
  135. var ty = wt.ty;
  136. var vertexData = this.vertexData;
  137. var trim = texture.trim;
  138. var orig = texture.orig;
  139. var anchor = this._anchor;
  140. var w0 = 0;
  141. var w1 = 0;
  142. var h0 = 0;
  143. var h1 = 0;
  144. if (trim) {
  145. // if the sprite is trimmed and is not a tilingsprite then we need to add the extra
  146. // space before transforming the sprite coords.
  147. w1 = trim.x - (anchor._x * orig.width);
  148. w0 = w1 + trim.width;
  149. h1 = trim.y - (anchor._y * orig.height);
  150. h0 = h1 + trim.height;
  151. }
  152. else {
  153. w1 = -anchor._x * orig.width;
  154. w0 = w1 + orig.width;
  155. h1 = -anchor._y * orig.height;
  156. h0 = h1 + orig.height;
  157. }
  158. // xy
  159. vertexData[0] = (a * w1) + (c * h1) + tx;
  160. vertexData[1] = (d * h1) + (b * w1) + ty;
  161. // xy
  162. vertexData[2] = (a * w0) + (c * h1) + tx;
  163. vertexData[3] = (d * h1) + (b * w0) + ty;
  164. // xy
  165. vertexData[4] = (a * w0) + (c * h0) + tx;
  166. vertexData[5] = (d * h0) + (b * w0) + ty;
  167. // xy
  168. vertexData[6] = (a * w1) + (c * h0) + tx;
  169. vertexData[7] = (d * h0) + (b * w1) + ty;
  170. if (this._roundPixels) {
  171. var resolution = settings.RESOLUTION;
  172. for (var i = 0; i < vertexData.length; ++i) {
  173. vertexData[i] = Math.round((vertexData[i] * resolution | 0) / resolution);
  174. }
  175. }
  176. };
  177. /**
  178. * Calculates worldTransform * vertices for a non texture with a trim. store it in vertexTrimmedData.
  179. *
  180. * This is used to ensure that the true width and height of a trimmed texture is respected.
  181. */
  182. Sprite.prototype.calculateTrimmedVertices = function () {
  183. if (!this.vertexTrimmedData) {
  184. this.vertexTrimmedData = new Float32Array(8);
  185. }
  186. else if (this._transformTrimmedID === this.transform._worldID && this._textureTrimmedID === this._texture._updateID) {
  187. return;
  188. }
  189. this._transformTrimmedID = this.transform._worldID;
  190. this._textureTrimmedID = this._texture._updateID;
  191. // lets do some special trim code!
  192. var texture = this._texture;
  193. var vertexData = this.vertexTrimmedData;
  194. var orig = texture.orig;
  195. var anchor = this._anchor;
  196. // lets calculate the new untrimmed bounds..
  197. var wt = this.transform.worldTransform;
  198. var a = wt.a;
  199. var b = wt.b;
  200. var c = wt.c;
  201. var d = wt.d;
  202. var tx = wt.tx;
  203. var ty = wt.ty;
  204. var w1 = -anchor._x * orig.width;
  205. var w0 = w1 + orig.width;
  206. var h1 = -anchor._y * orig.height;
  207. var h0 = h1 + orig.height;
  208. // xy
  209. vertexData[0] = (a * w1) + (c * h1) + tx;
  210. vertexData[1] = (d * h1) + (b * w1) + ty;
  211. // xy
  212. vertexData[2] = (a * w0) + (c * h1) + tx;
  213. vertexData[3] = (d * h1) + (b * w0) + ty;
  214. // xy
  215. vertexData[4] = (a * w0) + (c * h0) + tx;
  216. vertexData[5] = (d * h0) + (b * w0) + ty;
  217. // xy
  218. vertexData[6] = (a * w1) + (c * h0) + tx;
  219. vertexData[7] = (d * h0) + (b * w1) + ty;
  220. };
  221. /**
  222. *
  223. * Renders the object using the WebGL renderer
  224. * @param renderer - The webgl renderer to use.
  225. */
  226. Sprite.prototype._render = function (renderer) {
  227. this.calculateVertices();
  228. renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
  229. renderer.plugins[this.pluginName].render(this);
  230. };
  231. /** Updates the bounds of the sprite. */
  232. Sprite.prototype._calculateBounds = function () {
  233. var trim = this._texture.trim;
  234. var orig = this._texture.orig;
  235. // First lets check to see if the current texture has a trim..
  236. if (!trim || (trim.width === orig.width && trim.height === orig.height)) {
  237. // no trim! lets use the usual calculations..
  238. this.calculateVertices();
  239. this._bounds.addQuad(this.vertexData);
  240. }
  241. else {
  242. // lets calculate a special trimmed bounds...
  243. this.calculateTrimmedVertices();
  244. this._bounds.addQuad(this.vertexTrimmedData);
  245. }
  246. };
  247. /**
  248. * Gets the local bounds of the sprite object.
  249. * @param rect - Optional output rectangle.
  250. * @returns The bounds.
  251. */
  252. Sprite.prototype.getLocalBounds = function (rect) {
  253. // we can do a fast local bounds if the sprite has no children!
  254. if (this.children.length === 0) {
  255. if (!this._localBounds) {
  256. this._localBounds = new Bounds();
  257. }
  258. this._localBounds.minX = this._texture.orig.width * -this._anchor._x;
  259. this._localBounds.minY = this._texture.orig.height * -this._anchor._y;
  260. this._localBounds.maxX = this._texture.orig.width * (1 - this._anchor._x);
  261. this._localBounds.maxY = this._texture.orig.height * (1 - this._anchor._y);
  262. if (!rect) {
  263. if (!this._localBoundsRect) {
  264. this._localBoundsRect = new Rectangle();
  265. }
  266. rect = this._localBoundsRect;
  267. }
  268. return this._localBounds.getRectangle(rect);
  269. }
  270. return _super.prototype.getLocalBounds.call(this, rect);
  271. };
  272. /**
  273. * Tests if a point is inside this sprite
  274. * @param point - the point to test
  275. * @returns The result of the test
  276. */
  277. Sprite.prototype.containsPoint = function (point) {
  278. this.worldTransform.applyInverse(point, tempPoint);
  279. var width = this._texture.orig.width;
  280. var height = this._texture.orig.height;
  281. var x1 = -width * this.anchor.x;
  282. var y1 = 0;
  283. if (tempPoint.x >= x1 && tempPoint.x < x1 + width) {
  284. y1 = -height * this.anchor.y;
  285. if (tempPoint.y >= y1 && tempPoint.y < y1 + height) {
  286. return true;
  287. }
  288. }
  289. return false;
  290. };
  291. /**
  292. * Destroys this sprite and optionally its texture and children.
  293. * @param options - Options parameter. A boolean will act as if all options
  294. * have been set to that value
  295. * @param [options.children=false] - if set to true, all the children will have their destroy
  296. * method called as well. 'options' will be passed on to those calls.
  297. * @param [options.texture=false] - Should it destroy the current texture of the sprite as well
  298. * @param [options.baseTexture=false] - Should it destroy the base texture of the sprite as well
  299. */
  300. Sprite.prototype.destroy = function (options) {
  301. _super.prototype.destroy.call(this, options);
  302. this._texture.off('update', this._onTextureUpdate, this);
  303. this._anchor = null;
  304. var destroyTexture = typeof options === 'boolean' ? options : options && options.texture;
  305. if (destroyTexture) {
  306. var destroyBaseTexture = typeof options === 'boolean' ? options : options && options.baseTexture;
  307. this._texture.destroy(!!destroyBaseTexture);
  308. }
  309. this._texture = null;
  310. };
  311. // some helper functions..
  312. /**
  313. * Helper function that creates a new sprite based on the source you provide.
  314. * The source can be - frame id, image url, video url, canvas element, video element, base texture
  315. * @param {string|PIXI.Texture|HTMLCanvasElement|HTMLVideoElement} source - Source to create texture from
  316. * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options.
  317. * @returns The newly created sprite
  318. */
  319. Sprite.from = function (source, options) {
  320. var texture = (source instanceof Texture)
  321. ? source
  322. : Texture.from(source, options);
  323. return new Sprite(texture);
  324. };
  325. Object.defineProperty(Sprite.prototype, "roundPixels", {
  326. get: function () {
  327. return this._roundPixels;
  328. },
  329. /**
  330. * If true PixiJS will Math.floor() x/y values when rendering, stopping pixel interpolation.
  331. *
  332. * Advantages can include sharper image quality (like text) and faster rendering on canvas.
  333. * The main disadvantage is movement of objects may appear less smooth.
  334. *
  335. * To set the global default, change {@link PIXI.settings.ROUND_PIXELS}.
  336. * @default false
  337. */
  338. set: function (value) {
  339. if (this._roundPixels !== value) {
  340. this._transformID = -1;
  341. }
  342. this._roundPixels = value;
  343. },
  344. enumerable: false,
  345. configurable: true
  346. });
  347. Object.defineProperty(Sprite.prototype, "width", {
  348. /** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
  349. get: function () {
  350. return Math.abs(this.scale.x) * this._texture.orig.width;
  351. },
  352. set: function (value) {
  353. var s = sign(this.scale.x) || 1;
  354. this.scale.x = s * value / this._texture.orig.width;
  355. this._width = value;
  356. },
  357. enumerable: false,
  358. configurable: true
  359. });
  360. Object.defineProperty(Sprite.prototype, "height", {
  361. /** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
  362. get: function () {
  363. return Math.abs(this.scale.y) * this._texture.orig.height;
  364. },
  365. set: function (value) {
  366. var s = sign(this.scale.y) || 1;
  367. this.scale.y = s * value / this._texture.orig.height;
  368. this._height = value;
  369. },
  370. enumerable: false,
  371. configurable: true
  372. });
  373. Object.defineProperty(Sprite.prototype, "anchor", {
  374. /**
  375. * The anchor sets the origin point of the sprite. The default value is taken from the {@link PIXI.Texture|Texture}
  376. * and passed to the constructor.
  377. *
  378. * The default is `(0,0)`, this means the sprite's origin is the top left.
  379. *
  380. * Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
  381. *
  382. * Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
  383. *
  384. * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
  385. * @example
  386. * const sprite = new PIXI.Sprite(texture);
  387. * sprite.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
  388. */
  389. get: function () {
  390. return this._anchor;
  391. },
  392. set: function (value) {
  393. this._anchor.copyFrom(value);
  394. },
  395. enumerable: false,
  396. configurable: true
  397. });
  398. Object.defineProperty(Sprite.prototype, "tint", {
  399. /**
  400. * The tint applied to the sprite. This is a hex value.
  401. *
  402. * A value of 0xFFFFFF will remove any tint effect.
  403. * @default 0xFFFFFF
  404. */
  405. get: function () {
  406. return this._tint;
  407. },
  408. set: function (value) {
  409. this._tint = value;
  410. this._tintRGB = (value >> 16) + (value & 0xff00) + ((value & 0xff) << 16);
  411. },
  412. enumerable: false,
  413. configurable: true
  414. });
  415. Object.defineProperty(Sprite.prototype, "texture", {
  416. /** The texture that the sprite is using. */
  417. get: function () {
  418. return this._texture;
  419. },
  420. set: function (value) {
  421. if (this._texture === value) {
  422. return;
  423. }
  424. if (this._texture) {
  425. this._texture.off('update', this._onTextureUpdate, this);
  426. }
  427. this._texture = value || Texture.EMPTY;
  428. this._cachedTint = 0xFFFFFF;
  429. this._textureID = -1;
  430. this._textureTrimmedID = -1;
  431. if (value) {
  432. // wait for the texture to load
  433. if (value.baseTexture.valid) {
  434. this._onTextureUpdate();
  435. }
  436. else {
  437. value.once('update', this._onTextureUpdate, this);
  438. }
  439. }
  440. },
  441. enumerable: false,
  442. configurable: true
  443. });
  444. return Sprite;
  445. }(Container));
  446. export { Sprite };
  447. //# sourceMappingURL=sprite.mjs.map