merged master

This commit is contained in:
Svipal 2020-09-08 22:17:04 +02:00
commit 1994185d6f
255 changed files with 348046 additions and 69463 deletions

View file

@ -2,11 +2,44 @@
## Version 3.50.0 - Subaru - in development
### WebGL Pipeline Updates
If you use a custom WebGL Pipeline in your game, you must update your code in order to use Phaser 3.50.
Due to the huge amount of work that has taken place in this area, all of the pipelines have been renamed. If you extend any of these pipelines or use them in your game code (referenced by name), then please update accordingly. The name changes are:
* `TextureTintPipeline` is now called the `MultiPipeline`.
* `TextureTintStripPipeline` is now called the `RopePipeline`.
* `ForwardDiffuseLightPipeline` is now called the `LightPipeline`.
To match the new pipeline names, the shader source code has also been renamed.
* `ForwardDiffuse.frag` is now called `Light.frag`.
* `TextureTint.frag` is now called `Multi.frag`.
* `TextureTint.vert` is now called `Multi.vert`.
Other pipeline changes are as follows:
* `Types.Renderer.WebGL.WebGLPipelineConfig` is a new TypeDef that helps you easily configure your own Custom Pipeline when using TypeScript and also provides better JSDocs.
* `Types.Renderer.WebGL.WebGLPipelineAttributesConfig` is a new TypeDef that helps you easily configure the attributes for your own Custom Pipelines when using TypeScript and also provides better JSDocs.
* All pipelines will now work out the `renderer` property automatically, so it's no longer required in the config.
* All pipelines will now work out the `gl` property automatically, so it's no longer required in the config.
* All pipelines will now extract the `name` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexCapacity` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexSize` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexData` property from the config, allowing you to set it externally.
* All pipelines will now extract the `attributes` property from the config, allowing you to set it externally.
* All pipelines will now extract the `topology` property from the config, allowing you to set it externally.
#### Single Pipeline
There is also a new pipeline called `SinglePipeline`, created to emulate the old `TextureTintPipeline`. This special pipeline uses just a single texture and makes things a lot easier if you wish to create a custom pipeline, but not have to recode your shaders to work with multiple textures. Instead, just extend `SinglePipeline`, where-as before you extended the `TextureTintPipeline` and you won't have to change any of your shader code. However, if you can, you should update it to make it perform faster, but that choice is left up to you.
### WebGL Multi-Texture Rendering
The Texture Tint Pipeline has had its core flow rewritten to eliminate the need for constantly creating `batch` objects. Instead, it now supports the new multi-texture shader, vastly increasing rendering performance, especially on drawcall-bound systems.
The Multi Pipeline (previously the Texture Tint Pipeline) has had its core flow rewritten to eliminate the need for constantly creating `batch` objects. Instead, it now supports the new multi-texture shader, vastly increasing rendering performance, especially on draw-call bound systems.
All of the internal functions, such as `batchQuad` and `batchSprite` have been updated to use the new method of texture setting. The method signatures all remain the same, unless indicated below.
All of the internal functions, such as `batchQuad` and `batchSprite` have been updated to use the new method of texture setting. The method signatures all remain the same unless indicated below.
* `Config.render.maxTextures` is a new game config setting that allows you to control how many texture units will be used in WebGL.
* `WebGL.Utils.checkShaderMax` is a new function, used internally by the renderer, to determine the maximum number of texture units the GPU + browser supports.
@ -38,22 +71,23 @@ All of the internal functions, such as `batchQuad` and `batchSprite` have been u
* `WebGLRenderer.setTextureSource` is a new method, used by pipelines and Game Objects, that will assign a texture unit to the given Texture Source.
* The `WebGLRenderer.setTexture2D` method has been updated to use the new texture unit assignment. It no longer takes the `textureUnit` or `flush` parameters and these have been removed from its method signature.
* `WebGLRenderer.setTextureZero` is a new method that activates texture zero and binds the given texture to it. Useful for fbo backed game objects.
* `WebGLRenderer.clearTextureZero` is a new method that clears the texture tha was bound to unit zero.
* `WebGLRenderer.clearTextureZero` is a new method that clears the texture that was bound to unit zero.
* `WebGLRenderer.textureZero` is a new property that holds the currently bound unit zero texture.
* `WebGLRenderer.normalTexture` is a new property that holds the currently bound normal map (texture unit one).
* `WebGLRenderer.setNormalMap` is a new method that sets the current normal map texture.
* `WebGLRenderer.clearNormalMap` is a new method that clears the current normal map texture.
* `WebGLRenderer.resetTextures` is a new method that flushes the pipeline, resets all textures back to the temporary ones and resets the active texture counter.
* `WebGLRenderer.resetTextures` is a new method that flushes the pipeline, resets all textures back to the temporary ones, and resets the active texture counter.
* `WebGLPipeline.boot` will now check all of the attributes and store the pointer location within the attribute entry.
* `WebGLPipeline.bind` no longer looks-up and enables every attribute, every frame. Instead it uses the cached pointer location stored in the attribute entry, cutting down on redundant WebGL operations.
* `WebGLPipeline.bind` no longer looks-up and enables every attribute, every frame. Instead, it uses the cached pointer location stored in the attribute entry, cutting down on redundant WebGL operations.
* `WebGLRenderer.isNewNormalMap` is a new method that returns a boolean if the given parameters are not currently used.
* `WebGLPipeline.forceZero` is a new property that informs Game Objects if the pipeline requires a zero bound texture unit.
* `WebGLPipeline.setAttribPointers` is a new method that will set the vertex attribute pointers for the pipeline.
* `WebGLRenderer.unbindTextures` is a new method that will activate and then null bind all WebGL textures.
* `Renderer.WebGL.Utils.parseFragmentShaderMaxTextures` is a new function that will take fragment shader source and search it for `%count%` and `%forloop%` declarations, replacing them with the required GLSL for multi-texture support, returning the modified source.
### Forward Diffuse Light Pipeline API Changes
### Light Pipeline Changes
This Light2D pipeline, which is responsible for rendering lights under WebGL, has been rewritten to work with the new Texture Tint Pipeline functions. Lots of redundant code has been removed and the following changes and improvements took place:
The Light Pipeline (previously called the Forward Diffuse Light Pipeline), which is responsible for rendering lights under WebGL, has been rewritten to work with the new Multi Pipeline features. Lots of redundant code has been removed and the following changes and improvements took place:
* The pipeline now works with Game Objects that do not have a normal map. They will be rendered using the new default normal map, which allows for a flat light effect to pass over them and merge with their diffuse map colors.
* Fixed a bug in the way lights were handled that caused Tilemaps to render one tile at a time, causing massive slow down. They're now batched properly, making a combination of lights and tilemaps possible again.
@ -113,11 +147,11 @@ If you used any of them in your code, please update to the new function names be
### BitmapText New Features, Updates and API Changes
* `BitmapText.setCharacterTint` is a new method that allows you to set a tint color (either additive, or fill) on a specific range of characters within a static Bitmap Text. You can specify the start and length offsets and a per-corner tint color.
* `BitmapText.setWordTint` is a new method that allows you to set a tint color (either additive, or fill) on all matching words within a static Bitmap Text. You can specify the word by string, or numeric offset, and the number of replacements to tint.
* `BitmapText.setCharacterTint` is a new method that allows you to set a tint color (either additive or fill) on a specific range of characters within a static Bitmap Text. You can specify the start and length offsets and per-corner tint colors.
* `BitmapText.setWordTint` is a new method that allows you to set a tint color (either additive or fill) on all matching words within a static Bitmap Text. You can specify the word by string, or numeric offset, and the number of replacements to tint.
* `BitmapText.setDropShadow` is a new method that allows you to apply a drop shadow effect to a Bitmap Text object. You can set the horizontal and vertical offset of the shadow, as well as the color and alpha levels. Call this method with no parameters to clear a shadow.
* `BitmapTextWebGLRenderer` has been rewritten from scratch to make use of the new pre-cached WebGL uv texture and character location data generated by `GetBitmapTextSize`. This has reduced the number of calculations made in the function dramatically, as it no longer has work out glyph advancing or offsets during render, but only when the text content updates.
* `BitmapText.getCharacterAt` is a new method that will return the character data from the BitmapText at the given `x` and `y` corodinates. The character data includes the code, position, dimensions and glyph information.
* `BitmapText.getCharacterAt` is a new method that will return the character data from the BitmapText at the given `x` and `y` coordinates. The character data includes the code, position, dimensions, and glyph information.
* The `BitmapTextSize` object returned by `BitmapText.getTextBounds` has a new property called `characters` which is an array that contains the scaled position coordinates of each character in the BitmapText, which you could use for tasks such as determining which character in the BitmapText was clicked.
* `ParseXMLBitmapFont` will now calculate the WebGL uv data for the glyphs during parsing. This avoids it having to be done during rendering, saving CPU cycles on an operation that never changes.
* `ParseXMLBitmapFont` will now create a Frame object for each glyph. This means you could, for example, create a Sprite using the BitmapText texture and the glyph as the frame key, i.e.: `this.add.sprite(x, y, fontName, 'A')`.
@ -137,22 +171,183 @@ If you used any of them in your code, please update to the new function names be
* If you apply `setSize` to the Dynamic BitmapText the scissor is now calculated based on the parent transforms, not just the local ones, meaning you can crop Bitmap Text objects that exist within Containers. Fix #4653 (thanks @lgibson02)
* `ParseXMLBitmapFont` has a new optional parameter `texture`. If defined, this Texture is populated with Frame data, one frame per glyph. This happens automatically when loading Bitmap Text data in Phaser.
### Update List Changes
The way in which Game Objects add themselves to the Scene Update List has changed. Instead of being added by the Factory methods, they will now add and remove themselves based on the new `ADDED_TO_SCENE` and `REMOVED_FROM_SCENE` events. This means, you can now add Sprites directly to a Container, or Group, and they'll animate properly without first having to be part of the Display List. The full set of changes and new features relating to this follow:
* `GameObjects.Events.ADDED_TO_SCENE` is a new event, emitted by a Game Object, when it is added to a Scene, or a Container that is part of the Scene.
* `GameObjects.Events.REMOVED_FROM_SCENE` is a new event, emitted by a Game Object, when it is removed from a Scene, or a Container that is part of the Scene.
* `Scenes.Events.ADDED_TO_SCENE` is a new event, emitted by a Scene, when a new Game Object is added to the display list in the Scene, or a Container that is on the display list.
* `Scenes.Events.REMOVED_FROM_SCENE` is a new event, emitted by a Scene, when it a Game Object is removed from the display list in the Scene, or a Container that is on the display list.
* `GameObject.addedToScene` is a new method that custom Game Objects can use to perform additional set-up when a Game Object is added to a Scene. For example, Sprite uses this to add itself to the Update List.
* `GameObject.removedFromScene` is a new method that custom Game Objects can use to perform additional tear-down when a Game Object is removed from a Scene. For example, Sprite uses this to remove themselves from the Update List.
* Game Objects no longer automatically remove themselves from the Update List during `preDestroy`. This should be handled directly in the `removedFromScene` method now.
* The `Container` will now test to see if any Game Object added to it is already on the display list, or not, and emit its ADDED and REMOVED events accordingly. Fix #5267 #3876 (thanks @halgorithm @mbpictures)
* `DisplayList.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `DisplayList.addChildCallback` is a new method that overrides the List callback and fires the new ADDED events.
* `DisplayList.removeChildCallback` is a new method that overrides the List callback and fires the new REMOVED events.
* `GameObjectCreator.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `GameObjectFactory.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `ProcessQueue.checkQueue` is a new boolean property that will make sure only unique objects are added to the Process Queue.
* The `Update List` now uses the new `checkQueue` property to ensure no duplicate objects are on the active list.
* `DOMElementFactory`, `ExternFactory`, `ParticleManagerFactor`, `RopeFactory` and `SpriteFactory` all no longer add the objects to the Update List, this is now handled by the ADDED events instead.
* `Sprite`, `Rope`, `ParticleEmitterManager`, `Extern` and `DOMElement` now all override the `addedToScene` and `removedFromScene` callbacks to handle further set-up tasks.
### Spine Plugin Updates
* The Spine Runtimes have been updated to 3.8.95, which are the most recent non-beta versions. Please note, you will _need_ to re-export your animations if you're working in a version of Spine lower than 3.8.20.
* `SpineContainer` is a new Game Object available via `this.add.spineContainer` to which you can add Spine Game Objects only. It uses a special rendering function to retain batching, even across multiple container or Spine Game Object instances, resulting in dramatically improved performance over using regular Containers.
* A Spine Game Object with `setVisible(false)` will no longer still cause internal gl commands and is now properly skipped, retaining any current batch in the process. Fix #5174 (thanks @Kitsee)
* The Spine Game Object WebGL Renderer will no longer clear the type if invisible and will only end the batch if the next type doesn't match.
* The Spine Game Object WebGL Renderer will no longer rebind the pipeline if it was the final object on the display list, saving lots of gl commands.
* The Webpack build scripts have all been updated for Webpack 4.44.x. Fix #5243 (thanks @RollinSafary)
* There is a new npm script `npm run plugin.spine.runtimes` which will build all of the Spine runtimes, for ingestion by the plugin. Note: You will need to check-out the Esoteric Spine Runtimes repo into `plugins/spine/` in order for this to work.
* Spine Game Objects can now be rendered to Render Textures. Fix #5184 (thanks @Kitsee)
* Using > 128 Spine objects in a Container would cause a `WebGL: INVALID_OPERATION: vertexAttribPointer: no ARRAY_BUFFER is bound and offset is non-zero` error if you added any subsequent Spine objects to the Scene. There is now no limit. Fix #5246 (thanks @d7561985)
* The Spine Plugin will now work in HEADLESS mode without crashing. Fix #4988 (thanks @raimon-segura)
* Spine Game Objects now use -1 as their default blend mode, which means 'skip setting it'.
* The Spine TypeScript defs have been updated for the latest version of the plugin and to add SpineContainers.
* The `SpineGameObject.setAnimation` method will now use the `trackIndex` parameter if `ignoreIfPlaying` is set and run the check against this track index. Fix #4842 (thanks @vinerz)
* The `SpineFile` will no longer throw a warning if adding a texture into the Texture Manager that already exists. This allows you to have multiple Spine JSON use the same texture file, however, it also means you now get no warning if you accidentally load a texture that exists, so be careful with your keys! Fix #4947 (thanks @Nomy1)
* The Spine Plugin `destroy` method will now no longer remove the Game Objects from the Game Object Factory, or dispose of the Scene Renderer. This means when a Scene is destroyed, it will keep the Game Objects in the factory for other Scene's to use. Fix #5279 (thanks @Racoonacoon)
* `SpinePlugin.gameDestroy` is a new method that is called if the Game instance emits a `destroy` event. It removes the Spine Game Objects from the factory and disposes of the Spine scene renderer.
### Animation API New Features and Updates
If you use Animations in your game, please read the following important API changes in 3.50:
The Animation API has had a significant overhaul to improve playback handling. Instead of just playing an animation based on its global key, you can now supply a new `PlayAnimationConfig` object instead, which allows you to override any of the default animation settings, such as `duration`, `delay` and `yoyo` (see below for the full list). This means you no longer have to create lots of duplicate animations just to change properties such as `duration`, and can now set them dynamically at run-time as well.
* The `Animation` class no longer extends `EventEmitter`, as it no longer emits any events directly. This means you cannot now listen for events directly from an Animation instance. All of the events are now dispatched by the Game Objects instead.
* All of the `SPRITE_ANIMATION_KEY` events have been removed. Instead, please use the new events which all carry the `frameKey` parameter, which can be used to handle frame specific events.
* `ANIMATION_UPDATE_EVENT` is a new event that is emitted from a Sprite when an animation updates, i.e. its frame changes.
* `ANIMATION_STOP_EVENT` is a new event that is emitted from a Sprite when its current animation is stopped. This can happen if any of the `stop` methods are called, or a new animation is played prior to this one reaching completion. Fix #4894 (thanks @scott20145)
* The Game Object `Component.Animation` component has been renamed to `AnimationState` and has moved namespace. It's now in `Phaser.Animations` instead of `GameObjects.Components` to help differentiate it from the `Animation` class when browsing the documentation.
* The `play`, `playReverse`, `playAfterDelay`, `playAfterRepeat` and `chain` Sprite and Animation Component methods can now all take a `Phaser.Types.Animations.PlayAnimationConfig` configuration object, as well as a string, as the `key` parameter. This allows you to override any default animation setting with those defined in the config, giving you far greater control over animations on a Game Object level, without needing to globally duplicate them.
* `AnimationState.create` is a new method that allows you to create animations directly on a Sprite. These are not global and never enter the Animation Manager, instead risiding within the Sprite itself. This allows you to use the same keys across both local and global animations and set-up Sprite specific local animations.
* All playback methods: `play`, `playReverse`, `playAfterDelay` and `playAfterRepeat` will now check to see if the given animation key exists locally on the Sprite first. If it does, it's used, otherwise it then checks the global Animation Manager for the key instead.
* `AnimationState.skipMissedFrames` is now used when playing an animation, allowing you to create animations that run at frame rates far exceeding the refresh rate, or that will update to the correct frame should the game lag. Feature #4232 (thanks @colorcube)
* `AnimationManager.addMix` is a new method that allows you to create mixes between two animations. Mixing allows you to specify a unique delay between a pairing of animations. When playing Animation A on a Game Object, if you then play Animation B, and a mix exists, it will wait for the specified delay to be over before playing Animation B. This allows you to customise smoothing between different types of animation, such as blending between an idle and a walk state, or a running and a firing state.
* `AnimationManager.getMix` is a new method that will return the mix duration between the two given animations.
* `AnimationManager.removeMix` is a new method that will remove the mixture between either two animations, or all mixtures for the given animation.
* `AnimationState.remove` is a new method that will remove a locally stored Animation instance from a Sprite.
* `AnimationState.get` is a new method that will return a locally stored Animation instance from the Sprite.
* `AnimationState.exists` is a new method that will check if a locally stored Animation exists on the Sprite.
* The internal `AnimationState.remove` method has been renamed to `globalRemove`.
* `AnimationState.textureManager` is a new property that references the global Texture Manager.
* `AnimationState.anims` is a new property that contains locally created Animations in a Custom Map.
* `AnimationState.play` and `Sprite.play` no longer accept a `startFrame` parameter. Please set it via the `PlayAnimationConfig` instead.
* `AnimationState.playReverse` and `Sprite.playReverse` no longer accept a `startFrame` parameter. Please set it via the `PlayAnimationConfig` instead.
* The `AnimationState.delayedPlay` method has been renamed to `playAfterDelay`. The parameter order has also changed, so the key now comes first instead of the duration.
* The `AnimationState.stopOnRepeat` method has been renamed to `stopAfterRepeat`
* The `AnimationState.getCurrentKey` method has been renamed to `getName`.
* `AnimationState.getFrameName` is a new method that will return the key of the current Animation Frame, if an animation has been loaded.
* `AnimationState.playAfterDelay` and `Sprite.playAfterDelay` are new methods that will play the given animation after the delay in ms expires.
* `AnimationState.playAfterRepeat` and `Sprite.playAfterRepeat` are new methods that will play the given animation after the current animation finishes repeating. You can also specify the number of repeats allowed left to run.
* The `AnimationState.chain` method is now available on the Sprite class.
* The `AnimationState.stopAfterDelay` method is now available on the Sprite class.
* The `AnimationState.stopAfterRepeat` method is now available on the Sprite class.
* The `AnimationState.stopOnFrame` method is now available on the Sprite class.
* `AnimationManager.createFromAseprite` is a new method that allows you to use animations created in the Aseprite editor directly in Phaser. Please see the comprehensive documentation for this method for full details on how to do this.
* `AnimationState` now handles all of the loading of the animation. It no longer has to make calls out to the Animation Manager or Animation instance itself and will load the animation data directly, replacing as required from the optional `PlayAnimationConfig`. This improves performance and massively reduces CPU calls in animation heavy games.
* The `PlayAnimationConfig.frameRate` property lets you optionally override the animation frame rate.
* The `PlayAnimationConfig.duration` property lets you optionally override the animation duration.
* The `PlayAnimationConfig.delay` property lets you optionally override the animation delay.
* The `PlayAnimationConfig.repeat` property lets you optionally override the animation repeat counter.
* The `PlayAnimationConfig.repeatDelay` property lets you optionally override the animation repeat delay value.
* The `PlayAnimationConfig.yoyo` property lets you optionally override the animation yoyo boolean.
* The `PlayAnimationConfig.showOnStart` property lets you optionally override the animation show on start value.
* The `PlayAnimationConfig.hideOnComplete` property lets you optionally override the animation hide on complete value.
* The `PlayAnimationConfig.startFrame` property lets you optionally set the animation frame to start on.
* The `PlayAnimationConfig.timeScale` property lets you optionally set the animation time scale factor.
* `AnimationState.delayCounter` is a new property that allows you to control the delay before an animation will start playing. Only once this delay has expired, will the animation `START` events fire. Fix #4426 (thanks @bdaenen)
* `AnimationState.hasStarted` is a new boolean property that allows you to tell if the current animation has started playing, or is still waiting for a delay to expire.
* `AnimationState.showOnStart` is a new boolean property that controls if the Game Object should have `setVisible(true)` called on it when the animation starts.
* `AnimationState.hideOnComplete` is a new boolean property that controls if the Game Object should have `setVisible(false)` called on it when the animation completes.
* The `AnimationState.chain` method docs said it would remove all pending animations if called with no parameters. However, it didn't - and now does!
* The `AnimationState.setDelay` method has been removed. It never actually worked and you can now perform the same thing by calling either `playAfterDelay` or setting the `delay` property in the play config.
* The `AnimationState.getDelay` method has been removed. You can now read the `delay` property directly.
* The `AnimationState.setRepeat` method has been removed. You can achieve the same thing by setting the `repeat` property in the play config, or adjusting the public `repeatCounter` property if the animation has started.
* `AnimationState.handleStart` is a new internal private method that handles the animation start process.
* `AnimationState.handleRepeat` is a new internal private method that handles the animation repeat process.
* `AnimationState.handleStop` is a new internal private method that handles the animation stop process.
* `AnimationState.handleComplete` is a new internal private method that handles the animation complete process.
* `AnimationState.emitEvents` is a new internal private method that emits animation events, cutting down on duplicate code.
* The `AnimationState.restart` method has a new optional boolean parameter `resetRepeats` which controls if you want to reset the repeat counter during the restart, or not.
* `Animation.getTotalFrames` is a new method that will return the total number of frames in the animation. You can access it via `this.anims.currentAnim.getTotalFrames` from a Sprite.
* `Animation.calculateDuration` is a new method that calculates the duration, frameRate and msPerFrame for a given animation target.
* The `BuildGameObjectAnimation` function now uses the `PlayAnimationConfig` object to set the values.
* `Sprite.playReverse` is a new method that allows you to play the given animation in reverse on the Sprite.
* `Sprite.playAfterDelay` is a new method that allows you to play the given animation on the Sprite after a delay.
* `Sprite.stop` is a new method that allows you to stop the current animation on the Sprite.
* `AnimationManager.load` has been removed as it's no longer required.
* `AnimationManager.staggerPlay` has been fixed so you can now pass in negative stagger values.
* `AnimationManager.staggerPlay` has a new optional boolean parameter `staggerFirst`, which allows you to either include or exclude the first child in the stagger calculations.
* The `Animation.completeAnimation` method has been removed as it's no longer required.
* The `Animation.load` method has been removed as it's no longer required.
* The `Animation.setFrame` method has been removed as it's no longer required.
* The `Animation.getFirstTick` method has no longer needs the `includeDelay` parameter, as it's handled by `AnimationState` now.
* The `Animation.getFrames` method has a new optional boolean parameter `sortFrames` which will run a numeric sort on the frame names after constructing them, if a string-based frame is given.
* `Types.Animations.Animation` has a new boolean property `sortFrames`, which lets Phaser numerically sort the generated frames.
* `AnimationState.timeScale` is a new public property that replaces the old private `_timeScale` property.
* `AnimationState.delay` is a new public property that replaces the old private `_delay` property.
* `AnimationState.repeat` is a new public property that replaces the old private `_repeat` property.
* `AnimationState.repeatDelay` is a new public property that replaces the old private `_repeatDelay` property.
* `AnimationState.yoyo` is a new public property that replaces the old private `_yoyo` property.
* `AnimationState.inReverse` is a new public property that replaces the old private `_reverse` property.
* `AnimationState.startAnimation` is a new public method that replaces the old private `_startAnimation` method.
* The `AnimationState.getProgress` method has been fixed so it will return correctly if the animation is playing in reverse.
* The `AnimationState.globalRemove` method will now always be called when an animation is removed from the global Animation Manager, not just once.
* The `AnimationState.getRepeat` method has now been removed. You can get the value from the `repeat` property.
* The `AnimationState.setRepeatDelay` method has now been removed. You can set the value using the `repeatDelay` config property, or changing it at run-time.
* `AnimationState.complete` is a new method that handles the completion in animation playback.
* The `AnimationState.setTimeScale` method has now been removed. You can set the value using the `timeScale` config property, or changing it at run-time.
* The `AnimationState.getTimeScale` method has now been removed. You can read the value using the `timeScale` property.
* The `AnimationState.getTotalFrames` method has been fixed and won't error if called when no animation is loaded.
* The `AnimationState.setYoyo` method has now been removed. You can set the value using the `yoyo` config property, or changing it at run-time.
* The `AnimationState.getYoyo` method has now been removed. You can read the value using the `yoyo` property.
* The `AnimationState.stopAfterRepeat` method now has an optional parameter `repeatCount`, so you can tell the animation to stop after a specified number of repeats, not just 1.
* When playing an animation in reverse, if it reached the first frame and had to repeat, it would then jump to the frame before the final frame and carry on, skipping out the final frame.
* The `AnimationState.updateFrame` method has now been removed. Everything is handled by `setCurrentFrame` instead, which removes one extra step out of the update process.
* `GenerateFrameNames` will now `console.warn` if the generated frame isn't present in the texture, which should help with debugging animation creation massively.
* `GenerateFrameNumbers` will now `console.warn` if the generated frame isn't present in the texture, which should help with debugging animation creation massively.
* `GenerateFrameNumbers` would include the __BASE frame by mistake in its calculations. This didn't end up in the final animation, but did cause a cache miss when building the animation.
* `GenerateFrameNumbers` can now accept the `start` and `end` parameters in reverse order, meaning you can now do `{ start: 10, end: 1 }` to create the animation in reverse.
* `GenerateFrameNames` can now accept the `start` and `end` parameters in reverse order, meaning you can now do `{ start: 10, end: 1 }` to create the animation in reverse.
### New Features
* `WebGLRenderer.setInt1iv` will allow you to look-up and set a 1iv uniform on the given shader.
* `Geom.Intersects.GetLineToLine` is a new function that will return a Vector3 containing the point of intersection between 2 line segments, with the `z` property holding the distance value.
* `Geom.Intersects.GetLineToPolygon` is a new function that checks for the closest point of intersection between a line segment and an array of polygons.
* `Geom.Intersects.GetLineToPoints` is a new function that checks for the closest point of intersection between a line segment and an array of points, where each pair of points form a line segment.
* `Geom.Intersects.GetRaysFromPointToPolygon` is a new function that emits rays out from the given point and detects for intersection against all given polygons, returning the points of intersection in the results array.
* `Geom.Polygon.Translate` is a new function that allows you to translate all the points of a polygon by the given values.
* `Geom.Polygon.Simplify` is a new function that takes a polygon and simplifies the points by running them through a combination of Douglas-Peucker and Radial Distance algorithms, potentially dramatically reducing the number of points while retaining its shape.
* `WebGLRenderer.setInt1iv` will allow you to look-up and set a 1iv uniform on the given shader.
* `Phaser.Types.Math.Vector3Like` is a new data type representing as Vector 3 like object.
* `Phaser.Types.Math.Vector4Like` is a new data type representing as Vector 4 like object.
* `Transform.getLocalPoint` is a new method, available on all Game Objects, that takes an `x` / `y` pair and translates them into the local space of the Game Object, factoring in parent transforms and display origins.
* The `KeyboardPlugin` will now track the key code and timestamp of the previous key pressed and compare it to the current event. If they match, it will skip the event. On some systems if you were to type quickly, you would sometimes get duplicate key events firing (the exact same event firing more than once). This is now prevented from happening.
* The `KeyboardPlugin` will now track the key code and timestamp of the previous key pressed and compare it to the current event. If they match, it will skip the event. On some systems, if you were to type quickly, you would sometimes get duplicate key events firing (the exact same event firing more than once). This is now prevented from happening.
* `Display.Color.GetColorFromValue` is a new function that will take a hex color value and return it as an integer, for use in WebGL. This is now used internally by the Tint component and other classes.
* `Utils.String.RemoveAt` is a new function that will remove a character from the given index in a string and return the new string.
* `Frame.setUVs` is a new method that allows you to directly set the canvas and UV data for a frame. Use this if you need to override the values set automatically during frame creation.
* `TweenManager.getTweensOf` has a new parameter `includePending`. If set, it will also check the pending tweens for the given targets and return those in the results as well. Fix #5260 (thanks @pcharest2000)
* `WebGLPipeline.hasBooted` is a new boolean property that tracks if the pipeline has been booted or not, which is now far more important in 3.5 than in previous versions. This is checked in the `WebGLRenderer.addPipeline` method, and if not set, the pipeline is booted. Fix #5251 #5255 (thanks @telinc1 @rexrainbow)
* The WebGL Renderer will now add the pipelines during the `boot` method, instead of `init`.
* You can now use `this.renderer` from within a Scene, as it's now a Scene-level property and part of the Injection Map.
* `Clock.addEvent` can now take an existing `TimerEvent` object, as well as a config object. If a `TimerEvent` is given it will be removed from the Clock, reset and then added. This allows you to pool TimerEvents rather than constantly create and delete them. Fix #4115 (thanks @jcyuan)
* `Clock.removeEvent` is a new method that allows you to remove a `TimerEvent`, or an array of them, from all internal lists of the current Clock.
* `Group.getMatching` is a new method that will return any members of the Group that match the given criteria, such as `getMatching('visible', true)` (thanks @atursams)
* `ArcadePhysics.disableUpdate` is a new method that will prevent the Arcade Physics World `update` method from being called when the Scene updates. By disabling it, you're free to call the update method yourself, passing in your own delta and time values.
* `ArcadePhysics.enableUpdate` is a new method that will make the Arcade Physics World update in time with the Scene update. This is the default, so only call this if you have specifically disabled it previously.
* `ArcadeWorldConfig.customUpdate` is a new boolean property you can set in the Arcade Physics config object, either in the Scene or in the Game Config. If `true` the World update will never be called, allowing you to call it yourself from your own component. Close #5190 (thanks @cfortuner)
* `Utils.Array.SortByDigits` is a new function that takes the given array of strings and runs a numeric sort on it, ignoring any non-digits.
* `GroupCreateConfig`, which is used when calling `Group.createMultiple` or `Group.createFromConfig`, can now accept the following new properties: `setOrigin: { x, y, stepX, stepY }` which are applied to the items created by the Group.
### Updates and API Changes
* Earcut, used for polygon triangulation, has been updated from 2.1.4 to 2.2.2.
* Earcut has now been exposed and is available via `Geom.Polygon.Earcut` and is fully documented.
* `Config.batchSize` has been increased from 2000 to 4096.
* Removed the Deferred Diffuse fragment and vertex shaders from the project, as they're not used.
* `StaticTilemapLayer.upload` will now set the vertex attributes and buffer the data, and handles internal checks more efficiently.
@ -164,20 +359,78 @@ If you used any of them in your code, please update to the new function names be
* The `KeyboardPlugin` no longer emits `keydown_` events. These were replaced with `keydown-` events in v3.15. The previous event string was deprecated in v3.20.
* The `KeyboardPlugin` no longer emits `keyup_` events. These were replaced with `keyup-` events in v3.15. The previous event string was deprecated in v3.20.
* The `ScaleManager.updateBounds` method is now called every time the browser fires a 'resize' or 'orientationchange' event. This will update the offset of the canvas element Phaser is rendering to, which is responsible for keeping input positions correct. However, if you change the canvas position, or visibility, via any other method (i.e. via an Angular route) you should call the `updateBounds` method directly, yourself.
* The constant `Phaser.Renderer.WebGL.BYTE` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.SHORT` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.UNSIGNED_BYTE` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.UNSIGNED_SHORT` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.FLOAT` value has been removed as it wasn't used internally.
* `global.Phaser = Phaser` has been removed, as it's no longer required by the UMD loader, which should make importing in Angular 10 easier. Fix #5212 (thanks @blackyale)
* `Pointer.downTime` now stores the event timestamp of when the first button on the input device was pressed down, not just when button 1 was pressed down.
* `Pointer.upTime` now stores the event timestamp of when the final depressed button on the input device was released, not just when button 1 was released.
* The `Pointer.getDuration` method now uses the new Pointer `downTime` and `upTime` values, meaning it will accurately report the duration of when any button is being held down, not just the primary one. Fix #5112 (thanks @veleek)
* The `BaseShader` default vertex shader now includes the `outTexCoord` vec2 varying, mapped to be the same as that found in the pipeline shaders. Fix #5120 (@pavel-shirobok)
* When using the `GameObjectCreator` for `Containers` you can now specify the `children` property in the configuration object.
* `WebGLRenderer.finalType` is a new boolean property that signifies if the current Game Object being rendered is the final one in the list.
* The `WebGLRenderer.updateCanvasTexture` method will now set `gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL` to true, which should stop issues where you update a Text Game Object, having added a Render Texture or Spine Game Object to the Scene after it, which switches the PMA setting. Fix #5064 #5155 (thanks @hugoruscitti @immangrove-supertree)
* `Textures.Parsers.JSONHash` will now perform a `hasOwnProperty` check when iterating the frames, skipping anything that isn't a direct property. This should allow you to use generated atlas data that comes from `JSON.parse`. Fix #4768 (thanks @RollinSafary)
* The `Camera3D` Plugin has been rebuilt for Phaser 3.50 and the webpack config updated. This plugin is now considered deprecated and will not be updated beyond this release.
* `Tween.seek` will no longer issue a console warning for `'Tween.seek duration too long'`, it's now up to you to check on the performance of tween seeking.
* `WebGLRenderer.previousPipeline` is a new property that is set during a call to `clearPipeline` and used during calls to `rebindPipeline`, allowing the renderer to rebind any previous pipeline, not just the Multi Pipeline.
* The `WebGLRenderer.rebindPipeline` method has been changed slightly. Previously, you had to specify the `pipelineInstance`, but this is now optional. If you don't, it will use the new `previousPipeline` property instead. If not set, or none given, it will now return without throwing gl errors as well.
* If `inputWindowEvents` is set in the Game Config, then the `MouseManager` will now listen for the events on `window.top` instead of just `window`, which should help in situations where the pointer is released outside of an embedded iframe. Fix #4824 (thanks @rexrainbow)
* `Types.GameObjects.Text.GetTextSizeObject` is a new type def for the GetTextSize function results.
* The `Arcade.Body.resetFlags` method has a new optional boolean parameter `clear`. If set, it clears the `wasTouching` flags on the Body. This happens automatically when `Body.reset` is called. Previous to this, the flags were not reset until the next physics step (thanks @samme)
* `Utils.Array.StableSort` has been recoded. It's now based on Two-Screens stable sort 0.1.8 and has been updated to fit into Phaser better and no longer create any window bound objects. The `inplace` function has been removed, just call `StableSort(array)` directly now. All classes that used `StableSort.inplace` have been updated to call it directly.
* If a Scene is paused, or sent to sleep, it will automatically call `Keyboard.resetKeys`. This means that if you hold a key down, then sleep or pause a Scene, then release the key and resume or wake the Scene, it will no longer think it is still being held down (thanks @samme)
* `Actions.setOrigin` will now call `updateDisplayOrigin` on the items array, otherwise the effects can't be seen when rendering.
* You can now set the `ArcadeWorld.fixedStep` property via the `ArcadeWorldConfig` object (thanks @samme)
* `Utils.Array.NumerArray` can now accept the `start` and `end` parameters in reverse order, i.e. `10, 1` will generate a number array running from 10 to 1. Internally it has also been optimized to skip string based returns.
### Namespace Updates
* The `Phaser.Curves.MoveTo` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.DOM.GetInnerHeight` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.Bob` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.LightsManager` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.LightsPlugin` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.Particles.EmitterOp` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.GetTextSize` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.MeasureText` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.TextStyle` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Input.CreatePixelPerfectHandler` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Components.OverlapCirc` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Components.OverlapRect` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Tilemap` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.Components` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.Events` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.MatterGameObject` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.PointerConstraint` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Scenes.GetPhysicsPlugins` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Scenes.GetScenePlugins` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Structs.Events` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Tilemaps.Parsers.Tiled` function has now been exposed on the Phaser namespace (thanks @samme)
* Every single `Tilemap.Component` function has now been made public. This means you can call the Component functions directly, should you need to, outside of the Tilemap system.
### Bug Fixes
* `RenderTexture.resize` (which is called from `setSize`) wouldn't correctly set the `TextureSource.glTexture` property, leading to `bindTexture: attempt to use a deleted object` errors under WebGL.
* `RenderTexture.fill` would fail to fill the correct area under WebGL if the RenderTexture wasn't the same size as the Canvas. It now fills the given region properly.
* The `MatterAttractors` plugin, which enables attractors between bodies, has been fixed. The original plugin only worked if the body with the attractor was _first_ in the world bodies list. It can now attract any body, no matter where in the world list it is. Fix #5160 (thanks @strahius)
* The `KeyboardManager` and `KeyboardPlugin` were both still checking for the `InputManager.useQueue` property, which was removed several versions ago.
* In Arcade Physics, Dynamic bodies would no longer hit walls when riding on horizontally moving platforms. The horizontal (and vertical) friction is now re-applied correctly in these edge-cases. Fix #5210 (thanks @Dercetech @samme)
* Calling `Rectangle.setSize()` wouldn't change the underlying geometry of the Shape Game Object, causing any stroke to be incorrectly rendered after a size change.
* The `ProcessQueue` was emitting the wrong events internally. It now emits 'add' and 'remove' correctly (thanks @halilcakar)
* The `GridAlign` action didn't work if only the `height` parameter was set. Fix #5019 (thanks @halilcakar)
* The `Color.HSVToRGB` function has been rewritten to use the HSL and HSV formula from Wikipedia, giving much better results. Fix #5089 (thanks @DiamondeX)
* Previously, the `easeParams` array within a Tweens `props` object, or a multi-object tween, were ignored and it was only used if set on the root Tween object. It will now work correctly set at any depth. Fix #4292 (thanks @willblackmore)
* When using `Camera.setRenderToTexture` its `zoom` and `rotation` values would be applied twice. Fix #4221 #4924 #4713 (thanks @wayfu @DanMcgraw @pavel-shirobok)
* `GameObjects.Shape.Grid` would render a white fill even if you passed `undefined` as the fill color in the constructor. It now doesn't render cells if no fill color is given.
### Examples, Documentation and TypeScript
My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs:
My thanks to the following for helping with the Phaser 3 Examples, Docs, and TypeScript definitions, either by reporting errors, fixing them, or helping author the docs:
@samme @16patsle @scott20145
@samme @16patsle @scott20145 @khasanovbi @mk360 @volkans80 @jaabberwocky @maikthomas @atursams @LearningCode2023 @DylanC @BenjaminDRichards

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

203022
dist/phaser-facebook-instant-games.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

40711
dist/phaser.js vendored

File diff suppressed because it is too large Load diff

2
dist/phaser.min.js vendored

File diff suppressed because one or more lines are too long

348
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "phaser",
"version": "3.25.0",
"version": "3.50.0-beta.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -44,11 +44,43 @@
}
},
"@babel/parser": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
"integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
"version": "7.11.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
"integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==",
"dev": true
},
"@eslint/eslintrc": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
"integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.1.1",
"espree": "^7.3.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.2.1",
"js-yaml": "^3.13.1",
"lodash": "^4.17.19",
"minimatch": "^3.0.4",
"strip-json-comments": "^3.1.1"
},
"dependencies": {
"ajv": {
"version": "6.12.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
}
}
},
"@sindresorhus/df": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-2.1.0.tgz",
@ -109,6 +141,15 @@
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
"dev": true
},
"@types/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LrnsgZIfJaysFkv9rRJp4/uAyqw87oVed3s1hhF83nwbo9c7MG9g5DqR0seHP+lkX4ldmMrVolPjQSe2ZfD0yA==",
"dev": true,
"requires": {
"source-map": "*"
}
},
"@types/tapable": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
@ -122,6 +163,14 @@
"dev": true,
"requires": {
"source-map": "^0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"@types/webpack": {
@ -136,6 +185,14 @@
"@types/uglify-js": "*",
"@types/webpack-sources": "*",
"source-map": "^0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"@types/webpack-sources": {
@ -345,9 +402,9 @@
"dev": true
},
"acorn": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
},
"acorn-jsx": {
@ -431,7 +488,7 @@
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
@ -483,14 +540,15 @@
"dev": true
},
"asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
"integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"dev": true,
"requires": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0"
"minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
},
"dependencies": {
"bn.js": {
@ -638,6 +696,16 @@
"dev": true,
"optional": true
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@ -645,15 +713,15 @@
"dev": true
},
"bn.js": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
"integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
@ -751,16 +819,16 @@
}
},
"browserify-sign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
"integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
"integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"dev": true,
"requires": {
"bn.js": "^5.1.1",
"browserify-rsa": "^4.0.1",
"create-hash": "^1.2.0",
"create-hmac": "^1.1.7",
"elliptic": "^6.5.2",
"elliptic": "^6.5.3",
"inherits": "^2.0.4",
"parse-asn1": "^5.1.5",
"readable-stream": "^3.6.0",
@ -944,9 +1012,9 @@
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
@ -955,9 +1023,9 @@
}
},
"chokidar": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
"integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
"integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
"dev": true,
"optional": true,
"requires": {
@ -1154,7 +1222,7 @@
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
@ -1233,13 +1301,13 @@
}
},
"create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
"integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
"integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
"elliptic": "^6.0.0"
"elliptic": "^6.5.3"
},
"dependencies": {
"bn.js": {
@ -1591,12 +1659,13 @@
"dev": true
},
"eslint": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz",
"integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==",
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.8.1.tgz",
"integrity": "sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@eslint/eslintrc": "^0.1.3",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@ -1604,9 +1673,9 @@
"doctrine": "^3.0.0",
"enquirer": "^2.3.5",
"eslint-scope": "^5.1.0",
"eslint-utils": "^2.0.0",
"eslint-visitor-keys": "^1.2.0",
"espree": "^7.1.0",
"eslint-utils": "^2.1.0",
"eslint-visitor-keys": "^1.3.0",
"espree": "^7.3.0",
"esquery": "^1.2.0",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
@ -1620,7 +1689,7 @@
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash": "^4.17.14",
"lodash": "^4.17.19",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
@ -1666,14 +1735,14 @@
"dev": true
},
"espree": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
"integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
"integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
"dev": true,
"requires": {
"acorn": "^7.2.0",
"acorn": "^7.4.0",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.2.0"
"eslint-visitor-keys": "^1.3.0"
}
},
"esprima": {
@ -1692,9 +1761,9 @@
},
"dependencies": {
"estraverse": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
"integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
}
}
@ -1702,7 +1771,7 @@
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
"integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
"dev": true,
"requires": {
"estraverse": "^4.1.0"
@ -1721,14 +1790,14 @@
"dev": true
},
"eventemitter3": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"events": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
"integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
"integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
"dev": true
},
"evp_bytestokey": {
@ -1866,6 +1935,11 @@
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
@ -1987,6 +2061,13 @@
"flat-cache": "^2.0.1"
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@ -2480,6 +2561,11 @@
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
@ -2739,9 +2825,9 @@
}
},
"jsdoc": {
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.4.tgz",
"integrity": "sha512-3G9d37VHv7MFdheviDCjUfQoIjdv4TC5zTTf5G9VODLtOnVS6La1eoYBDlbWfsRT3/Xo+j2MIqki2EV12BZfwA==",
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz",
"integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==",
"dev": true,
"requires": {
"@babel/parser": "^7.9.4",
@ -2878,9 +2964,9 @@
}
},
"lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"lru-cache": {
@ -3031,7 +3117,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
@ -3147,6 +3233,13 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"nan": {
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
"dev": true,
"optional": true
},
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@ -3443,14 +3536,13 @@
}
},
"parse-asn1": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
"integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
"integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"dev": true,
"requires": {
"asn1.js": "^4.0.0",
"asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0",
"create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1"
@ -3800,6 +3892,14 @@
"@types/uglify-js": "*",
"@types/webpack-sources": "*",
"source-map": "^0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
}
}
@ -3945,6 +4045,12 @@
"ret": "~0.1.10"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"schema-utils": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@ -4180,9 +4286,10 @@
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true
},
"source-map-resolve": {
"version": "0.5.3",
@ -4205,6 +4312,14 @@
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"source-map-url": {
@ -4410,19 +4525,27 @@
"commander": "^2.20.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.12"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"terser-webpack-plugin": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
"integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
"integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"dev": true,
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
"serialize-javascript": "^3.1.0",
"serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
@ -4430,13 +4553,19 @@
},
"dependencies": {
"serialize-javascript": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
"integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
@ -4607,9 +4736,9 @@
"dev": true
},
"typescript": {
"version": "3.9.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
"integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
"integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
"dev": true
},
"uc.micro": {
@ -4639,6 +4768,14 @@
"uglify-js": "^3.6.0",
"webpack-sources": "^1.4.0",
"worker-farm": "^1.7.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"underscore": {
@ -4816,12 +4953,12 @@
"dev": true
},
"watchpack": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
"integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==",
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
"integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
"dev": true,
"requires": {
"chokidar": "^3.4.0",
"chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
"neo-async": "^2.5.0",
"watchpack-chokidar2": "^2.0.0"
@ -4893,7 +5030,11 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
"glob-parent": {
"version": "3.1.0",
@ -4943,9 +5084,9 @@
}
},
"webpack": {
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
"integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
"version": "4.44.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz",
"integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.9.0",
@ -4956,7 +5097,7 @@
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^4.1.0",
"enhanced-resolve": "^4.3.0",
"eslint-scope": "^4.0.3",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^2.4.0",
@ -4969,7 +5110,7 @@
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.1",
"watchpack": "^1.7.4",
"webpack-sources": "^1.4.1"
},
"dependencies": {
@ -4979,6 +5120,29 @@
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true
},
"enhanced-resolve": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
"integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.5.0",
"tapable": "^1.0.0"
},
"dependencies": {
"memory-fs": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
"integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
"dev": true,
"requires": {
"errno": "^0.1.3",
"readable-stream": "^2.0.1"
}
}
}
},
"eslint-scope": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
@ -5146,6 +5310,14 @@
"requires": {
"source-list-map": "^2.0.0",
"source-map": "~0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"which": {

View file

@ -1,6 +1,6 @@
{
"name": "phaser",
"version": "3.50.0-beta.1",
"version": "3.50.0-beta.4",
"release": "Subaru",
"description": "A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers.",
"author": "Richard Davey <rich@photonstorm.com> (http://www.photonstorm.com)",
@ -30,6 +30,7 @@
"plugin.spine.dist": "webpack --config plugins/spine/webpack.auto.dist.config.js",
"plugin.spine.watch": "webpack --config plugins/spine/webpack.auto.config.js --watch --display-modules",
"plugin.spine.dev": "webpack --config plugins/spine/webpack.auto.config.js",
"plugin.spine.runtimes": "cd plugins/spine && tsc -p tsconfig.both.json && tsc -p tsconfig.canvas.json && tsc -p tsconfig.webgl.json",
"plugin.spine.canvas.dist": "webpack --config plugins/spine/webpack.canvas.dist.config.js",
"plugin.spine.canvas.watch": "webpack --config plugins/spine/webpack.canvas.config.js --watch --display-modules",
"plugin.spine.canvas.dev": "webpack --config plugins/spine/webpack.canvas.config.js",
@ -61,23 +62,24 @@
"web audio"
],
"devDependencies": {
"@types/source-map": "^0.5.7",
"clean-webpack-plugin": "^3.0.0",
"dts-dom": "^3.6.0",
"eslint": "^7.4.0",
"eslint": "^7.8.1",
"eslint-plugin-es5": "^1.5.0",
"fs-extra": "^9.0.1",
"jsdoc": "^3.6.4",
"jsdoc": "^3.6.5",
"node-sloc": "^0.1.12",
"remove-files-webpack-plugin": "^1.4.3",
"typescript": "^3.9.6",
"typescript": "^4.0.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"vivid-cli": "^1.1.2",
"webpack": "^4.43.0",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-shell-plugin": "^0.5.0"
},
"dependencies": {
"eventemitter3": "^4.0.4",
"eventemitter3": "^4.0.7",
"exports-loader": "^1.1.0",
"imports-loader": "^1.1.0",
"path": "^0.12.7"

View file

@ -0,0 +1,13 @@
var fs = require('fs-extra');
var source = './plugins/camera3d/dist/';
var dest = '../phaser3-examples/public/plugins/';
if (fs.existsSync(dest))
{
fs.copySync(source, dest, { overwrite: true });
}
else
{
console.log('Copy-to-Examples failed: Phaser 3 Examples not present at ../phaser3-examples');
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,8 @@
Phaser 3 Camera 3D Plugin
=========================
Note: As of 26th August 2020 this plugin is now considered deprecated and will not be supported any further. It has been fixed to work with the Phaser 3.50 release, but will not be updated beyond this. You're free to use it as you see fit, but please do not open issues about it on GitHub, thank you.
In Phaser 3.12 Camera 3D support was moved to its own external plugin.
There are two ways to use this in your games:

View file

@ -18,7 +18,7 @@ var Vector4 = require('../../../../src/math/Vector4');
* it to be rendered by a 3D Camera. The Sprite can be positioned anywhere within 3D space.
*
* @class Sprite3D
* @extends Phaser.GameObjects.GameObject
* @extends Phaser.GameObjects.Sprite
* @memberOf Phaser.GameObjects
* @constructor
* @since 3.0.0

View file

@ -2,7 +2,8 @@
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
@ -42,6 +43,21 @@ module.exports = {
},
plugins: [
new CleanWebpackPlugin([ 'dist' ])
new RemovePlugin({
before: {
root: './plugins/camera3d/dist/',
include: [ 'camera3d.js', 'camera3d.min.js' ]
}
}),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/camera3d/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};

View file

@ -1,7 +1,7 @@
var fs = require('fs-extra');
var source = './plugins/spine/dist/';
var dest = '../phaser3-examples/public/plugins/3.8/';
var dest = '../phaser3-examples/public/plugins/3.8.95/';
if (fs.existsSync(dest))
{

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -211,6 +211,7 @@ var SpineFile = new Class({
var atlasKey = '';
var combinedAtlasData = '';
var preMultipliedAlpha = (this.config.preMultipliedAlpha) ? true : false;
var textureManager = this.loader.textureManager;
for (var i = 1; i < this.files.length; i++)
{
@ -218,7 +219,7 @@ var SpineFile = new Class({
if (file.type === 'text')
{
atlasKey = file.key.replace(/_[\d]$/, "");
atlasKey = file.key.replace(/_[\d]$/, '');
atlasCache = file.cache;
@ -230,7 +231,10 @@ var SpineFile = new Class({
var pos = src.indexOf('_');
var key = src.substr(pos + 1);
this.loader.textureManager.addImage(key, file.data);
if (!textureManager.exists(key))
{
textureManager.addImage(key, file.data);
}
}
file.pendingDestroy();

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
@ -12,17 +12,22 @@ var ScenePlugin = require('../../../src/plugins/ScenePlugin');
var Spine = require('Spine');
var SpineFile = require('./SpineFile');
var SpineGameObject = require('./gameobject/SpineGameObject');
var SpineContainer = require('./container/SpineContainer');
var NOOP = require('../../../src/utils/NOOP');
/**
* @classdesc
* The Spine Plugin is a Scene based plugin that handles the creation and rendering of Spine Game Objects.
*
* Find more details about Spine itself at http://esotericsoftware.com/.
*
* All rendering and object creation is handled via the official Spine Runtimes. This version of the plugin
* uses the Spine 3.8.72 runtimes. Please note that due to the way the Spine runtimes use semver, you will
* uses the Spine 3.8.95 runtimes. Please note that due to the way the Spine runtimes use semver, you will
* get breaking changes in point-releases. Therefore, files created in a different version of Spine may not
* work as a result, without you first updating the runtimes and rebuilding the plugin.
*
* You can find more details about Spine at http://esotericsoftware.com/.
* Esoteric themselves recommend that you freeze your Spine editor version against the runtime versions.
* You can find more information about this here: http://esotericsoftware.com/spine-settings#Version
*
* Please note that you require a Spine license in order to use Spine Runtimes in your games.
*
@ -71,10 +76,15 @@ var SpineGameObject = require('./gameobject/SpineGameObject');
* this.load.spine('stretchyman', 'stretchyman-pro.json', [ 'stretchyman-pma.atlas' ], true);
* ```
*
* It also installs a Game Object Factory method, allowing you to create Spine Game Objects:
* It also installs two Game Object Factory methods, allowing you to create Spine Game Objects
* and Spine Containers:
*
* ```javascript
* this.add.spine(512, 650, 'stretchyman')
* const man = this.add.spine(512, 650, 'stretchyman');
*
* const container = this.add.spineContainer();
*
* container.add(man);
* ```
*
* The first argument is the key which you used when importing the Spine data. There are lots of
@ -92,6 +102,13 @@ var SpineGameObject = require('./gameobject/SpineGameObject');
* stored in their own caches, which are global, meaning they're accessible from any Scene in your
* game, regardless if the Scene loaded the Spine data or not.
*
* When destroying a Phaser Game instance, if you need to re-create it again on the same page without
* reloading, you must remember to remove the Spine Plugin as part of your tear-down process:
*
* ```javascript
* this.plugins.removeScenePlugin('SpinePlugin');
* ```
*
* For details about the Spine Runtime API see http://esotericsoftware.com/spine-api-reference
*
* @class SpinePlugin
@ -275,6 +292,19 @@ var SpinePlugin = new Class({
this.getAtlas = this.getAtlasCanvas;
}
// Headless mode?
if (!this.renderer)
{
this.renderer = {
width: game.scale.width,
height: game.scale.height,
preRender: NOOP,
postRender: NOOP,
render: NOOP,
destroy: NOOP
};
}
var _this = this;
var add = function (x, y, key, animationName, loop)
@ -323,8 +353,38 @@ var SpinePlugin = new Class({
return spineGO.refresh();
};
var addContainer = function (x, y, children)
{
var spineGO = new SpineContainer(this.scene, _this, x, y, children);
this.displayList.add(spineGO);
return spineGO;
};
var makeContainer = function (config, addToScene)
{
if (config === undefined) { config = {}; }
var x = GetValue(config, 'x', 0);
var y = GetValue(config, 'y', 0);
var children = GetValue(config, 'children', null);
var container = new SpineContainer(this.scene, _this, x, y, children);
if (addToScene !== undefined)
{
config.add = addToScene;
}
BuildGameObject(this.scene, container, config);
return container;
};
pluginManager.registerFileType('spine', this.spineFileCallback, scene);
pluginManager.registerGameObject('spine', add, make);
pluginManager.registerGameObject('spineContainer', addContainer, makeContainer);
},
/**
@ -351,6 +411,8 @@ var SpinePlugin = new Class({
eventEmitter.once('shutdown', this.shutdown, this);
eventEmitter.once('destroy', this.destroy, this);
this.game.events.once('destroy', this.gameDestroy, this);
},
/**
@ -376,7 +438,7 @@ var SpinePlugin = new Class({
{
this.sceneRenderer = new Spine.webgl.SceneRenderer(this.renderer.canvas, this.gl, true);
// Monkeypatch the Spine setBlendMode functions, or batching is destroyed
// Monkeypatch the Spine setBlendMode functions, or batching is destroyed!
var setBlendMode = function (srcBlend, dstBlend)
{
@ -1035,14 +1097,6 @@ var SpinePlugin = new Class({
{
this.shutdown();
if (this.sceneRenderer)
{
this.sceneRenderer.dispose();
}
this.pluginManager.removeGameObject('spine', true, true);
this.pluginManager = null;
this.game = null;
this.scene = null;
this.systems = null;
@ -1051,13 +1105,40 @@ var SpinePlugin = new Class({
this.spineTextures = null;
this.json = null;
this.textures = null;
this.sceneRenderer = null;
this.skeletonRenderer = null;
this.gl = null;
},
/**
* The Game that owns this plugin is being destroyed.
*
* Dispose of the Scene Renderer and remove the Game Objects.
*
* @method SpinePlugin#gameDestroy
* @private
* @since 3.50.0
*/
gameDestroy: function ()
{
this.destroy();
if (this.sceneRenderer)
{
this.sceneRenderer.dispose();
}
this.sceneRenderer = null;
this.pluginManager = null;
this.pluginManager.removeGameObject('spine', true, true);
this.pluginManager.removeGameObject('spineContainer', true, true);
}
});
SpinePlugin.SpineGameObject = SpineGameObject;
SpinePlugin.SpineContainer = SpineContainer;
/**
* Creates a new Spine Game Object and adds it to the Scene.
*

View file

@ -0,0 +1,92 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../../src/utils/Class');
var Container = require('../../../../src/gameobjects/container/Container');
var SpineContainerRender = require('./SpineContainerRender');
/**
* @classdesc
* A Spine Container is a special kind of Container created specifically for Spine Game Objects.
*
* You have all of the same features of a standard Container, but the rendering functions are optimized specifically
* for Spine Game Objects. You must only add ever Spine Game Objects to this type of Container. Although Phaser will
* not prevent you from adding other types, they will not render and are likely to throw runtime errors.
*
* To create one in a Scene, use the factory methods:
*
* ```javascript
* this.add.spinecontainer();
* ```
*
* or
*
* ```javascript
* this.make.spinecontainer();
* ```
*
* See the Container documentation for further details about what Containers can do.
*
* @class SpineContainer
* @extends Phaser.GameObjects.Container
* @constructor
* @since 3.50.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that this Game Object belongs to.
* @param {SpinePlugin} pluginManager - A reference to the Phaser Spine Plugin.
* @param {number} x - The horizontal position of this Game Object in the world.
* @param {number} y - The vertical position of this Game Object in the world.
* @param {SpineGameObject[]} [children] - An optional array of Spine Game Objects to add to this Container.
*/
var SpineContainer = new Class({
Extends: Container,
Mixins: [
SpineContainerRender
],
initialize:
function SpineContainer (scene, plugin, x, y, children)
{
Container.call(this, scene, x, y, children);
// Same as SpineGameObject, to prevent the renderer from mis-typing it when batching
this.type = 'Spine';
/**
* A reference to the Spine Plugin.
*
* @name SpineContainer#plugin
* @type {SpinePlugin}
* @since 3.50.0
*/
this.plugin = plugin;
},
/**
* Internal destroy handler, called as part of the destroy process.
*
* @method SpineContainer#preDestroy
* @protected
* @since 3.50.0
*/
preDestroy: function ()
{
this.removeAll(!!this.exclusive);
this.localTransform.destroy();
this.tempTransformMatrix.destroy();
this.list = [];
this._displayList = null;
this.plugin = null;
}
});
module.exports = SpineContainer;

View file

@ -0,0 +1,100 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* Renders this Game Object with the Canvas Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method Phaser.GameObjects.Container#renderCanvas
* @since 3.4.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineContainerCanvasRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var children = container.list;
if (children.length === 0)
{
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var containerHasBlendMode = (container.blendMode !== -1);
if (!containerHasBlendMode)
{
// If Container is SKIP_TEST then set blend mode to be Normal
renderer.setBlendMode(0);
}
var alpha = container._alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
if (container.mask)
{
container.mask.preRenderCanvas(renderer, null, camera);
}
for (var i = 0; i < children.length; i++)
{
var child = children[i];
if (!child.willRender(camera))
{
continue;
}
var childAlpha = child.alpha;
var childScrollFactorX = child.scrollFactorX;
var childScrollFactorY = child.scrollFactorY;
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
{
// If Container doesn't have its own blend mode, then a child can have one
renderer.setBlendMode(child.blendMode);
}
// Set parent values
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
child.setAlpha(childAlpha * alpha);
// Render
child.renderCanvas(renderer, child, interpolationPercentage, camera, transformMatrix);
// Restore original values
child.setAlpha(childAlpha);
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
}
if (container.mask)
{
container.mask.postRenderCanvas(renderer);
}
};
module.exports = SpineContainerCanvasRenderer;

View file

@ -0,0 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var renderWebGL = require('../../../../src/utils/NOOP');
var renderCanvas = require('../../../../src/utils/NOOP');
if (typeof WEBGL_RENDERER)
{
renderWebGL = require('./SpineContainerWebGLRenderer');
}
if (typeof CANVAS_RENDERER)
{
renderCanvas = require('./SpineContainerCanvasRenderer');
}
module.exports = {
renderWebGL: renderWebGL,
renderCanvas: renderCanvas
};

View file

@ -0,0 +1,168 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var Clamp = require('../../../../src/math/Clamp');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method SpineContainerWebGLRenderer#renderWebGL
* @since 3.50.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineContainerWebGLRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var plugin = container.plugin;
var sceneRenderer = plugin.sceneRenderer;
var children = container.list;
if (children.length === 0)
{
if (sceneRenderer.batcher.isDrawing && renderer.finalType)
{
sceneRenderer.end();
renderer.rebindPipeline();
}
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var alpha = container.alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
var GameObjectRenderMask = 15;
if (renderer.newType)
{
// flush + clear if this is a new type
renderer.clearPipeline();
sceneRenderer.begin();
}
for (var i = 0; i < children.length; i++)
{
var src = children[i];
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
continue;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(src.scaleY));
camMatrix.copyFrom(camera.matrix);
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(transformMatrix, -camera.scrollX * scrollFactorX, -camera.scrollY * scrollFactorY);
// Undo the camera scroll
spriteMatrix.e = src.x;
spriteMatrix.f = src.y;
// Multiply by the Sprite matrix, store result in calcMatrix
camMatrix.multiply(spriteMatrix, calcMatrix);
var viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeleton.color.a = Clamp(childAlpha * alpha, 0, 1);
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
// Restore alpha
skeleton.color.a = childAlpha;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.rebindPipeline();
}
};
module.exports = SpineContainerWebGLRenderer;

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
@ -25,24 +25,24 @@ var SpineGameObjectRender = require('./SpineGameObjectRender');
* A Spine Game Object is a Phaser level object that can be added to your Phaser Scenes. It encapsulates
* a Spine Skeleton with Spine Animation Data and Animation State, with helper methods to allow you to
* easily change the skin, slot attachment, bone positions and more.
*
*
* Spine Game Objects can be created via the Game Object Factory, Game Object Creator, or directly.
* You can only create them if the Spine plugin has been loaded into Phaser.
*
*
* The quickest way is the Game Object Factory:
*
*
* ```javascript
* let jelly = this.add.spine(512, 550, 'jelly', 'jelly-think', true);
* ```
*
*
* Here we are creating a new Spine Game Object positioned at 512 x 550. It's using the `jelly`
* Spine data, which has previously been loaded into your Scene. The `jelly-think` argument is
* an optional animation to start playing on the skeleton. The final argument `true` sets the
* animation to loop. Look at the documentation for further details on each of these options.
*
*
* For more control, you can use the Game Object Creator, passing in a Spine Game Object
* Configuration object:
*
*
* ```javascript
* let jelly = this.make.spine({
* x: 512, y: 550, key: 'jelly',
@ -52,28 +52,28 @@ var SpineGameObjectRender = require('./SpineGameObjectRender');
* slotName: 'hat', attachmentName: 'images/La_14'
* });
* ```
*
*
* Here, you've got the ability to specify extra details, such as the slot name, attachments or
* overall scale.
*
*
* If you wish to instantiate a Spine Game Object directly you can do so, but in order for it to
* update and render, it must be added to the display and update lists of your Scene:
*
*
* ```javascript
* let jelly = new SpineGameObject(this, this.spine, 512, 550, 'jelly', 'jelly-think', true);
* this.sys.displayList.add(jelly);
* this.sys.updateList.add(jelly);
* ```
*
*
* It's possible to enable Spine Game Objects for input, but you should be aware that it will use
* the bounds of the skeletons current pose to create the hit area from. Sometimes this is ok, but
* often not. Make use of the `InputPlugin.enableDebug` method to view the input shape being created.
* If it's not suitable, provide your own shape to the `setInteractive` method.
*
*
* Due to the way Spine handles scaling, it's not recommended to enable a Spine Game Object for
* physics directly. Instead, you should look at creating a proxy body and syncing the Spine Game
* Object position with it. See the examples for further details.
*
*
* If your Spine Game Object has black outlines around the different parts of the texture when it
* renders then you have exported the files from Spine with pre-multiplied alpha enabled, but have
* forgotten to set that flag when loading the Spine data. Please see the loader docs for more details.
@ -173,7 +173,7 @@ var SpineGameObject = new Class({
* @since 3.19.0
*/
this.bounds = null;
/**
* A Game Object level flag that allows you to enable debug drawing
* to the Skeleton Debug Renderer by toggling it.
@ -231,7 +231,7 @@ var SpineGameObject = new Class({
* @readonly
* @since 3.19.0
*/
this.blendMode = 0;
this.blendMode = -1;
this.setPosition(x, y);
@ -257,9 +257,9 @@ var SpineGameObject = new Class({
/**
* Set the Alpha level for the whole Skeleton of this Game Object.
*
*
* The alpha controls the opacity of the Game Object as it renders.
*
*
* Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
*
* @method SpineGameObject#setAlpha
@ -292,7 +292,7 @@ var SpineGameObject = new Class({
/**
* The alpha value of the Skeleton.
*
*
* A value between 0 and 1.
*
* This is a global value, impacting the entire Skeleton, not just a region of it.
@ -331,7 +331,7 @@ var SpineGameObject = new Class({
/**
* The amount of red used when rendering the Skeleton.
*
*
* A value between 0 and 1.
*
* This is a global value, impacting the entire Skeleton, not just a region of it.
@ -361,7 +361,7 @@ var SpineGameObject = new Class({
/**
* The amount of green used when rendering the Skeleton.
*
*
* A value between 0 and 1.
*
* This is a global value, impacting the entire Skeleton, not just a region of it.
@ -391,7 +391,7 @@ var SpineGameObject = new Class({
/**
* The amount of blue used when rendering the Skeleton.
*
*
* A value between 0 and 1.
*
* This is a global value, impacting the entire Skeleton, not just a region of it.
@ -427,7 +427,7 @@ var SpineGameObject = new Class({
*
* @param {integer} [color=0xffffff] - The color being applied to the Skeleton or named Slot. Set to white to disable any previously set color.
* @param {string} [slotName] - The name of the slot to set the color on. If not give, will be set on the whole skeleton.
*
*
* @return {this} This Game Object instance.
*/
setColor: function (color, slotName)
@ -469,7 +469,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#setSkeletonFromJSON
* @since 3.19.0
*
*
* @param {string} atlasDataKey - The key of the Spine data to use for this Skeleton.
* @param {object} skeletonJSON - The JSON data for the Skeleton.
* @param {string} [animationName] - Optional name of the animation to set on the Skeleton.
@ -484,13 +484,13 @@ var SpineGameObject = new Class({
/**
* Sets this Game Object to use the given Skeleton based on its cache key.
*
*
* Typically, once set, the Skeleton doesn't change. Instead, you change the skin,
* or slot attachment, or any other property to adjust it.
*
* @method SpineGameObject#setSkeleton
* @since 3.19.0
*
*
* @param {string} atlasDataKey - The key of the Spine data to use for this Skeleton.
* @param {object} skeletonJSON - The JSON data for the Skeleton.
* @param {string} [animationName] - Optional name of the animation to set on the Skeleton.
@ -567,7 +567,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#COMPLETE
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
*/
onComplete: function (entry)
@ -582,7 +582,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#DISPOSE
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
*/
onDispose: function (entry)
@ -597,7 +597,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#END
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
*/
onEnd: function (entry)
@ -612,7 +612,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#EVENT
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
* @param {spine.Event} event - The Spine event.
*/
@ -628,7 +628,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#INTERRUPTED
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
*/
onInterrupted: function (entry)
@ -643,7 +643,7 @@ var SpineGameObject = new Class({
* @fires SpinePluginEvents#START
* @private
* @since 3.19.0
*
*
* @param {any} entry - The event data from Spine.
*/
onStart: function (entry)
@ -653,15 +653,15 @@ var SpineGameObject = new Class({
/**
* Refreshes the data about the current Skeleton.
*
*
* This will reset the rotation, position and size of the Skeleton to match this Game Object.
*
*
* Call this method if you need to access the Skeleton data directly, and it may have changed
* recently.
*
* @method SpineGameObject#refresh
* @since 3.19.0
*
*
* @return {this} This Game Object.
*/
refresh: function ()
@ -681,20 +681,20 @@ var SpineGameObject = new Class({
/**
* Sets the size of this Game Object.
*
*
* If no arguments are given it uses the current skeleton data dimensions.
*
*
* You can use this method to set a fixed size of this Game Object, such as for input detection,
* when the skeleton data doesn't match what is required in-game.
*
* @method SpineGameObject#setSize
* @since 3.19.0
*
*
* @param {number} [width] - The width of the Skeleton. If not given it defaults to the Skeleton Data width.
* @param {number} [height] - The height of the Skeleton. If not given it defaults to the Skeleton Data height.
* @param {number} [offsetX=0] - The horizontal offset of the Skeleton from its x and y coordinate.
* @param {number} [offsetY=0] - The vertical offset of the Skeleton from its x and y coordinate.
*
*
* @return {this} This Game Object.
*/
setSize: function (width, height, offsetX, offsetY)
@ -717,15 +717,15 @@ var SpineGameObject = new Class({
/**
* Sets the offset of this Game Object from the Skeleton position.
*
*
* You can use this method to adjust how the position of this Game Object relates to the Skeleton it is using.
*
* @method SpineGameObject#setOffset
* @since 3.19.0
*
*
* @param {number} [offsetX=0] - The horizontal offset of the Skeleton from its x and y coordinate.
* @param {number} [offsetY=0] - The vertical offset of the Skeleton from its x and y coordinate.
*
*
* @return {this} This Game Object.
*/
setOffset: function (offsetX, offsetY)
@ -744,13 +744,13 @@ var SpineGameObject = new Class({
/**
* Internal method that syncs all of the Game Object position and scale data to the Skeleton.
* It then syncs the skeleton bounds back to this Game Object.
*
*
* This method is called automatically as needed internally, however, it's also exposed should
* you require overriding the size settings.
*
* @method SpineGameObject#updateSize
* @since 3.19.0
*
*
* @return {this} This Game Object.
*/
updateSize: function ()
@ -839,7 +839,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getBoneList
* @since 3.19.0
*
*
* @return {string[]} An array containing the names of all the bones in the Skeleton Data.
*/
getBoneList: function ()
@ -864,7 +864,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getSkinList
* @since 3.19.0
*
*
* @return {string[]} An array containing the names of all the skins in the Skeleton Data.
*/
getSkinList: function ()
@ -889,7 +889,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getSlotList
* @since 3.19.0
*
*
* @return {string[]} An array containing the names of all the slots in the Skeleton.
*/
getSlotList: function ()
@ -911,7 +911,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getAnimationList
* @since 3.19.0
*
*
* @return {string[]} An array containing the names of all the animations in the Skeleton Data.
*/
getAnimationList: function ()
@ -936,9 +936,9 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getCurrentAnimation
* @since 3.19.0
*
*
* @param {integer} [trackIndex=0] - The track to return the current animation on.
*
*
* @return {?spine.Animation} The current Animation on the given track, or `undefined` if there is no current animation.
*/
getCurrentAnimation: function (trackIndex)
@ -956,7 +956,7 @@ var SpineGameObject = new Class({
/**
* Sets the current animation for a track, discarding any queued animations.
* If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from).
*
*
* Animations are referenced by a unique string-based key, as defined in the Spine software.
*
* @method SpineGameObject#play
@ -979,7 +979,7 @@ var SpineGameObject = new Class({
/**
* Sets the current animation for a track, discarding any queued animations.
* If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from).
*
*
* Animations are referenced by a unique string-based key, as defined in the Spine software.
*
* @method SpineGameObject#setAnimation
@ -989,7 +989,7 @@ var SpineGameObject = new Class({
* @param {integer} trackIndex - The track index to play the animation on.
* @param {string} animationName - The string-based key of the animation to play.
* @param {boolean} [loop=false] - Should the animation be looped when played?
* @param {boolean} [ignoreIfPlaying=false] - If this animation is already playing then ignore this call.
* @param {boolean} [ignoreIfPlaying=false] - If the animation specified by the track index is already playing then ignore this call.
*
* @return {spine.TrackEntry} A track entry to allow further customization of animation playback.
*/
@ -1000,8 +1000,8 @@ var SpineGameObject = new Class({
if (ignoreIfPlaying && this.state)
{
var currentTrack = this.state.getCurrent(0);
var currentTrack = this.state.getCurrent(trackIndex);
if (currentTrack && currentTrack.animation.name === animationName && !currentTrack.isComplete())
{
return;
@ -1017,9 +1017,9 @@ var SpineGameObject = new Class({
/**
* Adds an animation to be played after the current or last queued animation for a track.
* If the track is empty, it is equivalent to calling setAnimation.
*
*
* Animations are referenced by a unique string-based key, as defined in the Spine software.
*
*
* The delay is a float. If > 0, sets delay. If <= 0, the delay set is the duration of the previous
* track entry minus any mix duration (from the AnimationStateData) plus the specified delay
* (ie the mix ends at (delay = 0) or before (delay < 0) the previous track entry duration).
@ -1043,13 +1043,13 @@ var SpineGameObject = new Class({
/**
* Sets an empty animation for a track, discarding any queued animations, and sets the track
* entry's mixDuration. An empty animation has no timelines and serves as a placeholder for mixing in or out.
*
*
* Mixing out is done by setting an empty animation with a mix duration using either setEmptyAnimation,
* setEmptyAnimations, or addEmptyAnimation. Mixing to an empty animation causes the previous animation to be
* applied less and less over the mix duration. Properties keyed in the previous animation transition to
* the value from lower tracks or to the setup pose value if no lower tracks key the property.
* A mix duration of 0 still mixes out over one frame.
*
*
* Mixing in is done by first setting an empty animation, then adding an animation using addAnimation
* and on the returned track entry, set the mixDuration. Mixing from an empty animation causes the new
* animation to be applied more and more over the mix duration. Properties keyed in the new animation
@ -1071,7 +1071,7 @@ var SpineGameObject = new Class({
/**
* Removes all animations from the track, leaving skeletons in their current pose.
*
*
* It may be desired to use setEmptyAnimation to mix the skeletons back to the setup pose,
* rather than leaving them in their current pose.
*
@ -1088,10 +1088,10 @@ var SpineGameObject = new Class({
return this;
},
/**
* Removes all animations from all tracks, leaving skeletons in their current pose.
*
*
* It may be desired to use setEmptyAnimation to mix the skeletons back to the setup pose,
* rather than leaving them in their current pose.
*
@ -1109,11 +1109,11 @@ var SpineGameObject = new Class({
/**
* Sets the skin used to look up attachments before looking in the defaultSkin.
*
*
* Attachments from the new skin are attached if the corresponding attachment from the
* old skin was attached. If there was no old skin, each slot's setup mode attachment is
* attached from the new skin.
*
*
* After changing the skin, the visible attachments can be reset to those attached in the
* setup pose by calling setSlotsToSetupPose. Also, often apply is called before the next time
* the skeleton is rendered to allow any attachment keys in the current animation(s) to hide
@ -1121,7 +1121,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#setSkinByName
* @since 3.19.0
*
*
* @param {string} skinName - The name of the skin to set.
*
* @return {this} This Game Object.
@ -1141,11 +1141,11 @@ var SpineGameObject = new Class({
/**
* Sets the skin used to look up attachments before looking in the defaultSkin.
*
*
* Attachments from the new skin are attached if the corresponding attachment from the
* old skin was attached. If there was no old skin, each slot's setup mode attachment is
* attached from the new skin.
*
*
* After changing the skin, the visible attachments can be reset to those attached in the
* setup pose by calling setSlotsToSetupPose. Also, often apply is called before the next time
* the skeleton is rendered to allow any attachment keys in the current animation(s) to hide
@ -1153,7 +1153,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#setSkin
* @since 3.19.0
*
*
* @param {?spine.Skin} newSkin - The Skin to set. May be `null`.
*
* @return {this} This Game Object.
@ -1176,7 +1176,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#setMix
* @since 3.19.0
*
*
* @param {string} fromName - The animation to mix from.
* @param {string} toName - The animation to mix to.
* @param {number} [duration] - Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData getMix based on the animation before this animation (if any).
@ -1197,7 +1197,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getAttachment
* @since 3.19.0
*
*
* @param {integer} slotIndex - The slot index to search.
* @param {string} attachmentName - The attachment name to look for.
*
@ -1213,7 +1213,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#getAttachmentByName
* @since 3.19.0
*
*
* @param {string} slotName - The slot name to search.
* @param {string} attachmentName - The attachment name to look for.
*
@ -1230,7 +1230,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#setAttachment
* @since 3.19.0
*
*
* @param {string} slotName - The slot name to add the attachment to.
* @param {string} attachmentName - The attachment name to add.
*
@ -1318,7 +1318,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#angleBoneToXY
* @since 3.19.0
*
*
* @param {spine.Bone} bone - The bone to rotate towards the world position.
* @param {number} worldX - The world x coordinate to rotate the bone towards.
* @param {number} worldY - The world y coordinate to rotate the bone towards.
@ -1350,7 +1350,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findBone
* @since 3.19.0
*
*
* @param {string} boneName - The name of the bone to find.
*
* @return {spine.Bone} The bone, or null.
@ -1366,7 +1366,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findBoneIndex
* @since 3.19.0
*
*
* @param {string} boneName - The name of the bone to find.
*
* @return {integer} The bone index. Or -1 if the bone was not found.
@ -1382,7 +1382,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findSlot
* @since 3.19.0
*
*
* @param {string} slotName - The name of the slot to find.
*
* @return {spine.Slot} The Slot. May be null.
@ -1398,7 +1398,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findSlotIndex
* @since 3.19.0
*
*
* @param {string} slotName - The name of the slot to find.
*
* @return {integer} The slot index. Or -1 if the Slot was not found.
@ -1414,7 +1414,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findSkin
* @since 3.19.0
*
*
* @param {string} skinName - The name of the skin to find.
*
* @return {spine.Skin} The Skin. May be null.
@ -1430,7 +1430,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findEvent
* @since 3.19.0
*
*
* @param {string} eventDataName - The name of the event to find.
*
* @return {spine.EventData} The Event Data. May be null.
@ -1446,7 +1446,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findAnimation
* @since 3.19.0
*
*
* @param {string} animationName - The name of the animation to find.
*
* @return {spine.Animation} The Animation. May be null.
@ -1462,7 +1462,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findIkConstraint
* @since 3.19.0
*
*
* @param {string} constraintName - The name of the constraint to find.
*
* @return {spine.IkConstraintData} The IK constraint. May be null.
@ -1478,7 +1478,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findTransformConstraint
* @since 3.19.0
*
*
* @param {string} constraintName - The name of the constraint to find.
*
* @return {spine.TransformConstraintData} The transform constraint. May be null.
@ -1494,7 +1494,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findPathConstraint
* @since 3.19.0
*
*
* @param {string} constraintName - The name of the constraint to find.
*
* @return {spine.PathConstraintData} The path constraint. May be null.
@ -1510,7 +1510,7 @@ var SpineGameObject = new Class({
*
* @method SpineGameObject#findPathConstraintIndex
* @since 3.19.0
*
*
* @param {string} constraintName - The name of the constraint to find.
*
* @return {integer} The constraint index. Or -1 if the constraint was not found.
@ -1522,15 +1522,15 @@ var SpineGameObject = new Class({
/**
* Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
*
*
* The returned object contains two properties: `offset` and `size`:
*
*
* `offset` - The distance from the skeleton origin to the bottom left corner of the AABB.
* `size` - The width and height of the AABB.
*
* @method SpineGameObject#getBounds
* @since 3.19.0
*
*
* @return {any} The bounds object.
*/
getBounds: function ()
@ -1544,7 +1544,7 @@ var SpineGameObject = new Class({
* @method SpineGameObject#preUpdate
* @protected
* @since 3.19.0
*
*
* @param {number} time - The current timestamp.
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

View file

@ -1,6 +1,6 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
@ -27,31 +27,37 @@ var SpineGameObjectWebGLRenderer = function (renderer, src, interpolationPercent
{
var plugin = src.plugin;
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var sceneRenderer = plugin.sceneRenderer;
var GameObjectRenderMask = 15;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)));
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
// Reset the current type
renderer.currentType = '';
// If there is already a batch running, and the next type isn't a Spine object, or this is the end, we need to close it
// If there is already a batch running, we need to close it
if (!renderer.nextTypeMatch)
if (sceneRenderer.batcher.isDrawing && (!renderer.nextTypeMatch || renderer.finalType))
{
// The next object in the display list is not a Spine object, so we end the batch
sceneRenderer.end();
renderer.rebindPipeline(renderer.pipelines.TextureTintPipeline);
renderer.rebindPipeline();
}
if (!renderer.finalType)
{
// Reset the current type
renderer.currentType = '';
}
return;
}
if (renderer.newType)
{
// flush + clear previous pipeline if this is a new type
renderer.clearPipeline();
}
@ -118,7 +124,7 @@ var SpineGameObjectWebGLRenderer = function (renderer, src, interpolationPercent
}
}
if (camera.renderToTexture)
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
@ -152,10 +158,11 @@ var SpineGameObjectWebGLRenderer = function (renderer, src, interpolationPercent
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine object, so we end the batch
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
renderer.rebindPipeline(renderer.pipelines.TextureTintPipeline);
// And rebind the previous pipeline
renderer.rebindPipeline();
}
};

View file

@ -144,6 +144,7 @@ declare module spine {
getFrameCount(): number;
setFrame(frameIndex: number, time: number, attachmentName: string): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string): void;
}
class DeformTimeline extends CurveTimeline {
slotIndex: number;
@ -248,12 +249,15 @@ declare module spine {
static emptyAnimation: Animation;
static SUBSEQUENT: number;
static FIRST: number;
static HOLD: number;
static HOLD_SUBSEQUENT: number;
static HOLD_FIRST: number;
static HOLD_MIX: number;
static NOT_LAST: number;
static SETUP: number;
static CURRENT: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
unkeyedState: number;
events: Event[];
listeners: AnimationStateListener[];
queue: EventQueue;
@ -265,6 +269,8 @@ declare module spine {
updateMixingFrom(to: TrackEntry, delta: number): boolean;
apply(skeleton: Skeleton): boolean;
applyMixingFrom(to: TrackEntry, skeleton: Skeleton, blend: MixBlend): number;
applyAttachmentTimeline(timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string, attachments: boolean): void;
applyRotateTimeline(timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend, timelinesRotation: Array<number>, i: number, firstFrame: boolean): void;
queueEvents(entry: TrackEntry, animationTime: number): void;
clearTracks(): void;
@ -282,7 +288,6 @@ declare module spine {
disposeNext(entry: TrackEntry): void;
_animationsChanged(): void;
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
@ -384,13 +389,14 @@ declare module spine {
private errors;
private toLoad;
private loaded;
private rawDataUris;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
private static downloadText;
private static downloadBinary;
private downloadText;
private downloadBinary;
setRawDataURI(path: string, data: string): void;
loadBinary(path: string, success?: (path: string, binary: Uint8Array) => void, error?: (path: string, error: string) => void): void;
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureAtlas(path: string, success?: (path: string, atlas: TextureAtlas) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
@ -848,8 +854,9 @@ declare module spine {
bone: Bone;
color: Color;
darkColor: Color;
private attachment;
attachment: Attachment;
private attachmentTime;
attachmentState: number;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
@ -1392,6 +1399,7 @@ declare module spine.webgl {
private texture;
private boundUnit;
private useMipMaps;
static DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL: boolean;
constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, image: HTMLImageElement, useMipMaps?: boolean);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
static validateMagFilter(magFilter: TextureFilter): TextureFilter.Nearest | TextureFilter.Linear | TextureFilter.Linear;

View file

@ -2,7 +2,7 @@ var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
@ -675,17 +675,15 @@ var spine;
var slot = skeleton.slots[this.slotIndex];
if (!slot.bone.active)
return;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
var attachmentName_1 = slot.data.attachmentName;
slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1));
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frames = this.frames;
if (time < frames[0]) {
if (blend == MixBlend.setup || blend == MixBlend.first) {
var attachmentName_2 = slot.data.attachmentName;
slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2));
}
if (blend == MixBlend.setup || blend == MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frameIndex = 0;
@ -697,6 +695,9 @@ var spine;
skeleton.slots[this.slotIndex]
.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
};
AttachmentTimeline.prototype.setAttachment = function (skeleton, slot, attachmentName) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName);
};
return AttachmentTimeline;
}());
spine.AttachmentTimeline = AttachmentTimeline;
@ -798,6 +799,7 @@ var spine;
case MixBlend.replace:
for (var i_5 = 0; i_5 < vertexCount; i_5++)
deform[i_5] += (lastVertices[i_5] - deform[i_5]) * alpha;
break;
case MixBlend.add:
var vertexAttachment = slotAttachment;
if (vertexAttachment.bones == null) {
@ -954,8 +956,9 @@ var spine;
DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
var drawOrder = skeleton.drawOrder;
var slots = skeleton.slots;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
return;
}
var frames = this.frames;
@ -1347,6 +1350,7 @@ var spine;
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.unkeyedState = 0;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
@ -1436,12 +1440,12 @@ var spine;
var events = this.events;
var tracks = this.tracks;
var applied = false;
for (var i = 0, n = tracks.length; i < n; i++) {
var current = tracks[i];
for (var i_16 = 0, n_1 = tracks.length; i_16 < n_1; i_16++) {
var current = tracks[i_16];
if (current == null || current.delay > 0)
continue;
applied = true;
var blend = i == 0 ? spine.MixBlend.first : current.mixBlend;
var blend = i_16 == 0 ? spine.MixBlend.first : current.mixBlend;
var mix = current.alpha;
if (current.mixingFrom != null)
mix *= this.applyMixingFrom(current, skeleton, blend);
@ -1450,10 +1454,14 @@ var spine;
var animationLast = current.animationLast, animationTime = current.getAnimationTime();
var timelineCount = current.animation.timelines.length;
var timelines = current.animation.timelines;
if ((i == 0 && mix == 1) || blend == spine.MixBlend.add) {
if ((i_16 == 0 && mix == 1) || blend == spine.MixBlend.add) {
for (var ii = 0; ii < timelineCount; ii++) {
spine.Utils.webkit602BugfixHelper(mix, blend);
timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
var timeline = timelines[ii];
if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true);
else
timeline.apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
}
}
else {
@ -1463,14 +1471,17 @@ var spine;
spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null);
var timelinesRotation = current.timelinesRotation;
for (var ii = 0; ii < timelineCount; ii++) {
var timeline = timelines[ii];
var timelineBlend = (timelineMode[ii] & (AnimationState.NOT_LAST - 1)) == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
var timeline_1 = timelines[ii];
var timelineBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline_1 instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline_1, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
}
else if (timeline_1 instanceof spine.AttachmentTimeline) {
this.applyAttachmentTimeline(timeline_1, skeleton, animationTime, blend, true);
}
else {
spine.Utils.webkit602BugfixHelper(mix, blend);
timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
timeline_1.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
}
}
}
@ -1479,6 +1490,16 @@ var spine;
current.nextAnimationLast = animationTime;
current.nextTrackLast = current.trackTime;
}
var setupState = this.unkeyedState + AnimationState.SETUP;
var slots = skeleton.slots;
for (var i = 0, n = skeleton.slots.length; i < n; i++) {
var slot = slots[i];
if (slot.attachmentState == setupState) {
var attachmentName = slot.data.attachmentName;
slot.attachment = (attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName));
}
}
this.unkeyedState += 2;
this.queue.drain();
return applied;
};
@ -1522,23 +1543,22 @@ var spine;
var direction = spine.MixDirection.mixOut;
var timelineBlend = void 0;
var alpha = 0;
switch (timelineMode[i] & (AnimationState.NOT_LAST - 1)) {
switch (timelineMode[i]) {
case AnimationState.SUBSEQUENT:
timelineBlend = blend;
if (!attachments && timeline instanceof spine.AttachmentTimeline) {
if ((timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
continue;
timelineBlend = spine.MixBlend.setup;
}
if (!drawOrder && timeline instanceof spine.DrawOrderTimeline)
continue;
timelineBlend = blend;
alpha = alphaMix;
break;
case AnimationState.FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaMix;
break;
case AnimationState.HOLD:
case AnimationState.HOLD_SUBSEQUENT:
timelineBlend = blend;
alpha = alphaHold;
break;
case AnimationState.HOLD_FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaHold;
break;
@ -1551,18 +1571,12 @@ var spine;
from.totalAlpha += alpha;
if (timeline instanceof spine.RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments);
else {
spine.Utils.webkit602BugfixHelper(alpha, blend);
if (timelineBlend == spine.MixBlend.setup) {
if (timeline instanceof spine.AttachmentTimeline) {
if (attachments || (timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
direction = spine.MixDirection.mixIn;
}
else if (timeline instanceof spine.DrawOrderTimeline) {
if (drawOrder)
direction = spine.MixDirection.mixIn;
}
}
if (drawOrder && timeline instanceof spine.DrawOrderTimeline && timelineBlend == spine.MixBlend.setup)
direction = spine.MixDirection.mixIn;
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction);
}
}
@ -1574,6 +1588,31 @@ var spine;
from.nextTrackLast = from.trackTime;
return mix;
};
AnimationState.prototype.applyAttachmentTimeline = function (timeline, skeleton, time, blend, attachments) {
var slot = skeleton.slots[timeline.slotIndex];
if (!slot.bone.active)
return;
var frames = timeline.frames;
if (time < frames[0]) {
if (blend == spine.MixBlend.setup || blend == spine.MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
}
else {
var frameIndex;
if (time >= frames[frames.length - 1])
frameIndex = frames.length - 1;
else
frameIndex = spine.Animation.binarySearch(frames, time) - 1;
this.setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments);
}
if (slot.attachmentState <= this.unkeyedState)
slot.attachmentState = this.unkeyedState + AnimationState.SETUP;
};
AnimationState.prototype.setAttachment = function (skeleton, slot, attachmentName, attachments) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName);
if (attachments)
slot.attachmentState = this.unkeyedState + AnimationState.CURRENT;
};
AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
if (firstFrame)
timelinesRotation[i] = 0;
@ -1836,6 +1875,7 @@ var spine;
entry.interruptAlpha = 1;
entry.mixTime = 0;
entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation);
entry.mixBlend = spine.MixBlend.replace;
return entry;
};
AnimationState.prototype.disposeNext = function (entry) {
@ -1861,14 +1901,6 @@ var spine;
entry = entry.mixingTo;
} while (entry != null);
}
this.propertyIDs.clear();
for (var i = this.tracks.length - 1; i >= 0; i--) {
var entry = this.tracks[i];
while (entry != null) {
this.computeNotLast(entry);
entry = entry.mixingFrom;
}
}
};
AnimationState.prototype.computeHold = function (entry) {
var to = entry.mixingTo;
@ -1880,8 +1912,7 @@ var spine;
var propertyIDs = this.propertyIDs;
if (to != null && to.holdPrevious) {
for (var i = 0; i < timelinesCount; i++) {
propertyIDs.add(timelines[i].getPropertyId());
timelineMode[i] = AnimationState.HOLD;
timelineMode[i] = propertyIDs.add(timelines[i].getPropertyId()) ? AnimationState.HOLD_FIRST : AnimationState.HOLD_SUBSEQUENT;
}
return;
}
@ -1905,20 +1936,7 @@ var spine;
}
break;
}
timelineMode[i] = AnimationState.HOLD;
}
}
};
AnimationState.prototype.computeNotLast = function (entry) {
var timelines = entry.animation.timelines;
var timelinesCount = entry.animation.timelines.length;
var timelineMode = entry.timelineMode;
var propertyIDs = this.propertyIDs;
for (var i = 0; i < timelinesCount; i++) {
if (timelines[i] instanceof spine.AttachmentTimeline) {
var timeline = timelines[i];
if (!propertyIDs.add(timeline.slotIndex))
timelineMode[i] |= AnimationState.NOT_LAST;
timelineMode[i] = AnimationState.HOLD_FIRST;
}
}
};
@ -1946,9 +1964,11 @@ var spine;
AnimationState.emptyAnimation = new spine.Animation("<empty>", [], 0);
AnimationState.SUBSEQUENT = 0;
AnimationState.FIRST = 1;
AnimationState.HOLD = 2;
AnimationState.HOLD_MIX = 3;
AnimationState.NOT_LAST = 4;
AnimationState.HOLD_SUBSEQUENT = 2;
AnimationState.HOLD_FIRST = 3;
AnimationState.HOLD_MIX = 4;
AnimationState.SETUP = 1;
AnimationState.CURRENT = 2;
return AnimationState;
}());
spine.AnimationState = AnimationState;
@ -2161,11 +2181,15 @@ var spine;
this.errors = {};
this.toLoad = 0;
this.loaded = 0;
this.rawDataUris = {};
this.textureLoader = textureLoader;
this.pathPrefix = pathPrefix;
}
AssetManager.downloadText = function (url, success, error) {
AssetManager.prototype.downloadText = function (url, success, error) {
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.onload = function () {
if (request.status == 200) {
@ -2180,8 +2204,10 @@ var spine;
};
request.send();
};
AssetManager.downloadBinary = function (url, success, error) {
AssetManager.prototype.downloadBinary = function (url, success, error) {
var request = new XMLHttpRequest();
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function () {
@ -2197,13 +2223,16 @@ var spine;
};
request.send();
};
AssetManager.prototype.setRawDataURI = function (path, data) {
this.rawDataUris[this.pathPrefix + path] = data;
};
AssetManager.prototype.loadBinary = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadBinary(path, function (data) {
this.downloadBinary(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2223,7 +2252,7 @@ var spine;
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (data) {
this.downloadText(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2242,12 +2271,13 @@ var spine;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
var storagePath = path;
this.toLoad++;
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.assets[storagePath] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
@ -2260,32 +2290,10 @@ var spine;
if (error)
error(path, "Couldn't load image " + path);
};
if (this.rawDataUris[path])
path = this.rawDataUris[path];
img.src = path;
};
AssetManager.prototype.loadTextureData = function (path, data, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
var img = new Image();
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
success(path, img);
};
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
_this.toLoad--;
_this.loaded++;
if (error)
error(path, "Couldn't load image " + path);
};
img.src = data;
};
AssetManager.prototype.loadTextureAtlas = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
@ -2293,12 +2301,12 @@ var spine;
var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : "";
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
this.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
atlasPages.push(parent + "/" + path);
atlasPages.push(parent == "" ? path : parent + "/" + path);
var image = document.createElement("img");
image.width = 16;
image.height = 16;
@ -2322,7 +2330,7 @@ var spine;
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
return _this.get(parent + "/" + path);
return _this.get(parent == "" ? path : parent + "/" + path);
});
_this.assets[path] = atlas;
if (success)
@ -2560,6 +2568,8 @@ var spine;
var prx = 0;
if (s > 0.0001) {
s = Math.abs(pa * pd - pb * pc) / s;
pa /= this.skeleton.scaleX;
pc /= this.skeleton.scaleY;
pb = pc * s;
pd = pa * s;
prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg;
@ -2830,10 +2840,27 @@ var spine;
if (!bone.appliedValid)
bone.updateAppliedTransform();
var p = bone.parent;
var id = 1 / (p.a * p.d - p.b * p.c);
var x = targetX - p.worldX, y = targetY - p.worldY;
var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay;
var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation;
var pa = p.a, pb = p.b, pc = p.c, pd = p.d;
var rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;
switch (bone.data.transformMode) {
case spine.TransformMode.OnlyTranslation:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
break;
case spine.TransformMode.NoRotationOrReflection:
var s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
var sa = pa / bone.skeleton.scaleX;
var sc = pc / bone.skeleton.scaleY;
pb = -sc * s * bone.skeleton.scaleX;
pd = sa * s * bone.skeleton.scaleY;
rotationIK += Math.atan2(sc, sa) * spine.MathUtils.radDeg;
default:
var x = targetX - p.worldX, y = targetY - p.worldY;
var d = pa * pd - pb * pc;
tx = (x * pd - y * pb) / d - bone.ax;
ty = (y * pa - x * pc) / d - bone.ay;
}
rotationIK += Math.atan2(ty, tx) * spine.MathUtils.radDeg;
if (bone.ascaleX < 0)
rotationIK += 180;
if (rotationIK > 180)
@ -2842,6 +2869,12 @@ var spine;
rotationIK += 360;
var sx = bone.ascaleX, sy = bone.ascaleY;
if (compress || stretch) {
switch (bone.data.transformMode) {
case spine.TransformMode.NoScale:
case spine.TransformMode.NoScaleOrReflection:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
}
var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
var s = (dd / b - 1) * alpha + 1;
@ -3500,6 +3533,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3519,6 +3553,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3538,7 +3573,6 @@ var spine;
if (!this.queueAsset(clientId, textureLoader, path))
return;
var img = new Image();
img.src = path;
img.crossOrigin = "anonymous";
img.onload = function (ev) {
_this.rawAssets[path] = img;
@ -3546,6 +3580,7 @@ var spine;
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
};
img.src = path;
};
SharedAssetManager.prototype.get = function (clientId, path) {
path = this.pathPrefix + path;
@ -4071,6 +4106,8 @@ var spine;
var input = new BinaryInput(binary);
skeletonData.hash = input.readString();
skeletonData.version = input.readString();
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = input.readFloat();
skeletonData.y = input.readFloat();
skeletonData.width = input.readFloat();
@ -5059,7 +5096,7 @@ var spine;
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
for (var i = 0, n_2 = clippingPolygons.length; i < n_2; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
@ -5481,6 +5518,8 @@ var spine;
if (skeletonMap != null) {
skeletonData.hash = skeletonMap.hash;
skeletonData.version = skeletonMap.spine;
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = skeletonMap.x;
skeletonData.y = skeletonMap.y;
skeletonData.width = skeletonMap.width;
@ -6158,7 +6197,7 @@ var spine;
skeletonData.animations.push(new spine.Animation(name, timelines, duration));
};
SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) {
if (!map.curve)
if (!map.hasOwnProperty("curve"))
return;
if (map.curve == "stepped")
timeline.setStepped(frameIndex);
@ -7473,9 +7512,7 @@ var spine;
};
Pool.prototype.freeAll = function (items) {
for (var i = 0; i < items.length; i++) {
if (items[i].reset)
items[i].reset();
this.items[i] = items[i];
this.free(items[i]);
}
};
Pool.prototype.clear = function () {
@ -8017,7 +8054,7 @@ var spine;
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
};
RegionAttachment.prototype.copy = function () {
var copy = new RegionAttachment(name);
var copy = new RegionAttachment(this.name);
copy.region = this.region;
copy.rendererObject = this.rendererObject;
copy.path = this.path;
@ -8521,6 +8558,8 @@ var spine;
this.texture = this.context.gl.createTexture();
}
this.bind();
if (GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL)
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
@ -8550,6 +8589,7 @@ var spine;
var gl = this.context.gl;
gl.deleteTexture(this.texture);
};
GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false;
return GLTexture;
}(spine.Texture));
webgl.GLTexture = GLTexture;
@ -10279,11 +10319,11 @@ var spine;
var nn = clip.worldVerticesLength;
var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0);
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
for (var i_16 = 0, n_2 = world.length; i_16 < n_2; i_16 += 2) {
var x = world[i_16];
var y = world[i_16 + 1];
var x2 = world[(i_16 + 2) % world.length];
var y2 = world[(i_16 + 3) % world.length];
for (var i_17 = 0, n_3 = world.length; i_17 < n_3; i_17 += 2) {
var x = world[i_17];
var y = world[i_17 + 1];
var x2 = world[(i_17 + 2) % world.length];
var y2 = world[(i_17 + 3) % world.length];
shapes.line(x, y, x2, y2);
}
}
@ -10444,7 +10484,7 @@ var spine;
var vertexEffect = this.vertexEffect;
var verts = clippedVertices;
if (!twoColorTint) {
for (var v = 0, n_3 = clippedVertices.length; v < n_3; v += vertexSize) {
for (var v = 0, n_4 = clippedVertices.length; v < n_4; v += vertexSize) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]);
@ -10463,7 +10503,7 @@ var spine;
}
}
else {
for (var v = 0, n_4 = clippedVertices.length; v < n_4; v += vertexSize) {
for (var v = 0, n_5 = clippedVertices.length; v < n_5; v += vertexSize) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]);
@ -10493,7 +10533,7 @@ var spine;
if (this.vertexEffect != null) {
var vertexEffect = this.vertexEffect;
if (!twoColorTint) {
for (var v = 0, u = 0, n_5 = renderable.numFloats; v < n_5; v += vertexSize, u += 2) {
for (var v = 0, u = 0, n_6 = renderable.numFloats; v < n_6; v += vertexSize, u += 2) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempUv.x = uvs[u];
@ -10512,7 +10552,7 @@ var spine;
}
}
else {
for (var v = 0, u = 0, n_6 = renderable.numFloats; v < n_6; v += vertexSize, u += 2) {
for (var v = 0, u = 0, n_7 = renderable.numFloats; v < n_7; v += vertexSize, u += 2) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempUv.x = uvs[u];
@ -10537,7 +10577,7 @@ var spine;
}
else {
if (!twoColorTint) {
for (var v = 2, u = 0, n_7 = renderable.numFloats; v < n_7; v += vertexSize, u += 2) {
for (var v = 2, u = 0, n_8 = renderable.numFloats; v < n_8; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
@ -10547,7 +10587,7 @@ var spine;
}
}
else {
for (var v = 2, u = 0, n_8 = renderable.numFloats; v < n_8; v += vertexSize, u += 2) {
for (var v = 2, u = 0, n_9 = renderable.numFloats; v < n_9; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;

File diff suppressed because one or more lines are too long

View file

@ -144,6 +144,7 @@ declare module spine {
getFrameCount(): number;
setFrame(frameIndex: number, time: number, attachmentName: string): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string): void;
}
class DeformTimeline extends CurveTimeline {
slotIndex: number;
@ -248,12 +249,15 @@ declare module spine {
static emptyAnimation: Animation;
static SUBSEQUENT: number;
static FIRST: number;
static HOLD: number;
static HOLD_SUBSEQUENT: number;
static HOLD_FIRST: number;
static HOLD_MIX: number;
static NOT_LAST: number;
static SETUP: number;
static CURRENT: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
unkeyedState: number;
events: Event[];
listeners: AnimationStateListener[];
queue: EventQueue;
@ -265,6 +269,8 @@ declare module spine {
updateMixingFrom(to: TrackEntry, delta: number): boolean;
apply(skeleton: Skeleton): boolean;
applyMixingFrom(to: TrackEntry, skeleton: Skeleton, blend: MixBlend): number;
applyAttachmentTimeline(timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string, attachments: boolean): void;
applyRotateTimeline(timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend, timelinesRotation: Array<number>, i: number, firstFrame: boolean): void;
queueEvents(entry: TrackEntry, animationTime: number): void;
clearTracks(): void;
@ -282,7 +288,6 @@ declare module spine {
disposeNext(entry: TrackEntry): void;
_animationsChanged(): void;
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
@ -384,13 +389,14 @@ declare module spine {
private errors;
private toLoad;
private loaded;
private rawDataUris;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
private static downloadText;
private static downloadBinary;
private downloadText;
private downloadBinary;
setRawDataURI(path: string, data: string): void;
loadBinary(path: string, success?: (path: string, binary: Uint8Array) => void, error?: (path: string, error: string) => void): void;
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureAtlas(path: string, success?: (path: string, atlas: TextureAtlas) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
@ -848,8 +854,9 @@ declare module spine {
bone: Bone;
color: Color;
darkColor: Color;
private attachment;
attachment: Attachment;
private attachmentTime;
attachmentState: number;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;

View file

@ -2,7 +2,7 @@ var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
@ -675,17 +675,15 @@ var spine;
var slot = skeleton.slots[this.slotIndex];
if (!slot.bone.active)
return;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
var attachmentName_1 = slot.data.attachmentName;
slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1));
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frames = this.frames;
if (time < frames[0]) {
if (blend == MixBlend.setup || blend == MixBlend.first) {
var attachmentName_2 = slot.data.attachmentName;
slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2));
}
if (blend == MixBlend.setup || blend == MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frameIndex = 0;
@ -697,6 +695,9 @@ var spine;
skeleton.slots[this.slotIndex]
.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
};
AttachmentTimeline.prototype.setAttachment = function (skeleton, slot, attachmentName) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName);
};
return AttachmentTimeline;
}());
spine.AttachmentTimeline = AttachmentTimeline;
@ -798,6 +799,7 @@ var spine;
case MixBlend.replace:
for (var i_5 = 0; i_5 < vertexCount; i_5++)
deform[i_5] += (lastVertices[i_5] - deform[i_5]) * alpha;
break;
case MixBlend.add:
var vertexAttachment = slotAttachment;
if (vertexAttachment.bones == null) {
@ -954,8 +956,9 @@ var spine;
DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
var drawOrder = skeleton.drawOrder;
var slots = skeleton.slots;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
return;
}
var frames = this.frames;
@ -1347,6 +1350,7 @@ var spine;
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.unkeyedState = 0;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
@ -1436,12 +1440,12 @@ var spine;
var events = this.events;
var tracks = this.tracks;
var applied = false;
for (var i = 0, n = tracks.length; i < n; i++) {
var current = tracks[i];
for (var i_16 = 0, n_1 = tracks.length; i_16 < n_1; i_16++) {
var current = tracks[i_16];
if (current == null || current.delay > 0)
continue;
applied = true;
var blend = i == 0 ? spine.MixBlend.first : current.mixBlend;
var blend = i_16 == 0 ? spine.MixBlend.first : current.mixBlend;
var mix = current.alpha;
if (current.mixingFrom != null)
mix *= this.applyMixingFrom(current, skeleton, blend);
@ -1450,10 +1454,14 @@ var spine;
var animationLast = current.animationLast, animationTime = current.getAnimationTime();
var timelineCount = current.animation.timelines.length;
var timelines = current.animation.timelines;
if ((i == 0 && mix == 1) || blend == spine.MixBlend.add) {
if ((i_16 == 0 && mix == 1) || blend == spine.MixBlend.add) {
for (var ii = 0; ii < timelineCount; ii++) {
spine.Utils.webkit602BugfixHelper(mix, blend);
timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
var timeline = timelines[ii];
if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true);
else
timeline.apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
}
}
else {
@ -1463,14 +1471,17 @@ var spine;
spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null);
var timelinesRotation = current.timelinesRotation;
for (var ii = 0; ii < timelineCount; ii++) {
var timeline = timelines[ii];
var timelineBlend = (timelineMode[ii] & (AnimationState.NOT_LAST - 1)) == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
var timeline_1 = timelines[ii];
var timelineBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline_1 instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline_1, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
}
else if (timeline_1 instanceof spine.AttachmentTimeline) {
this.applyAttachmentTimeline(timeline_1, skeleton, animationTime, blend, true);
}
else {
spine.Utils.webkit602BugfixHelper(mix, blend);
timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
timeline_1.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
}
}
}
@ -1479,6 +1490,16 @@ var spine;
current.nextAnimationLast = animationTime;
current.nextTrackLast = current.trackTime;
}
var setupState = this.unkeyedState + AnimationState.SETUP;
var slots = skeleton.slots;
for (var i = 0, n = skeleton.slots.length; i < n; i++) {
var slot = slots[i];
if (slot.attachmentState == setupState) {
var attachmentName = slot.data.attachmentName;
slot.attachment = (attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName));
}
}
this.unkeyedState += 2;
this.queue.drain();
return applied;
};
@ -1522,23 +1543,22 @@ var spine;
var direction = spine.MixDirection.mixOut;
var timelineBlend = void 0;
var alpha = 0;
switch (timelineMode[i] & (AnimationState.NOT_LAST - 1)) {
switch (timelineMode[i]) {
case AnimationState.SUBSEQUENT:
timelineBlend = blend;
if (!attachments && timeline instanceof spine.AttachmentTimeline) {
if ((timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
continue;
timelineBlend = spine.MixBlend.setup;
}
if (!drawOrder && timeline instanceof spine.DrawOrderTimeline)
continue;
timelineBlend = blend;
alpha = alphaMix;
break;
case AnimationState.FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaMix;
break;
case AnimationState.HOLD:
case AnimationState.HOLD_SUBSEQUENT:
timelineBlend = blend;
alpha = alphaHold;
break;
case AnimationState.HOLD_FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaHold;
break;
@ -1551,18 +1571,12 @@ var spine;
from.totalAlpha += alpha;
if (timeline instanceof spine.RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments);
else {
spine.Utils.webkit602BugfixHelper(alpha, blend);
if (timelineBlend == spine.MixBlend.setup) {
if (timeline instanceof spine.AttachmentTimeline) {
if (attachments || (timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
direction = spine.MixDirection.mixIn;
}
else if (timeline instanceof spine.DrawOrderTimeline) {
if (drawOrder)
direction = spine.MixDirection.mixIn;
}
}
if (drawOrder && timeline instanceof spine.DrawOrderTimeline && timelineBlend == spine.MixBlend.setup)
direction = spine.MixDirection.mixIn;
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction);
}
}
@ -1574,6 +1588,31 @@ var spine;
from.nextTrackLast = from.trackTime;
return mix;
};
AnimationState.prototype.applyAttachmentTimeline = function (timeline, skeleton, time, blend, attachments) {
var slot = skeleton.slots[timeline.slotIndex];
if (!slot.bone.active)
return;
var frames = timeline.frames;
if (time < frames[0]) {
if (blend == spine.MixBlend.setup || blend == spine.MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
}
else {
var frameIndex;
if (time >= frames[frames.length - 1])
frameIndex = frames.length - 1;
else
frameIndex = spine.Animation.binarySearch(frames, time) - 1;
this.setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments);
}
if (slot.attachmentState <= this.unkeyedState)
slot.attachmentState = this.unkeyedState + AnimationState.SETUP;
};
AnimationState.prototype.setAttachment = function (skeleton, slot, attachmentName, attachments) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName);
if (attachments)
slot.attachmentState = this.unkeyedState + AnimationState.CURRENT;
};
AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
if (firstFrame)
timelinesRotation[i] = 0;
@ -1836,6 +1875,7 @@ var spine;
entry.interruptAlpha = 1;
entry.mixTime = 0;
entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation);
entry.mixBlend = spine.MixBlend.replace;
return entry;
};
AnimationState.prototype.disposeNext = function (entry) {
@ -1861,14 +1901,6 @@ var spine;
entry = entry.mixingTo;
} while (entry != null);
}
this.propertyIDs.clear();
for (var i = this.tracks.length - 1; i >= 0; i--) {
var entry = this.tracks[i];
while (entry != null) {
this.computeNotLast(entry);
entry = entry.mixingFrom;
}
}
};
AnimationState.prototype.computeHold = function (entry) {
var to = entry.mixingTo;
@ -1880,8 +1912,7 @@ var spine;
var propertyIDs = this.propertyIDs;
if (to != null && to.holdPrevious) {
for (var i = 0; i < timelinesCount; i++) {
propertyIDs.add(timelines[i].getPropertyId());
timelineMode[i] = AnimationState.HOLD;
timelineMode[i] = propertyIDs.add(timelines[i].getPropertyId()) ? AnimationState.HOLD_FIRST : AnimationState.HOLD_SUBSEQUENT;
}
return;
}
@ -1905,20 +1936,7 @@ var spine;
}
break;
}
timelineMode[i] = AnimationState.HOLD;
}
}
};
AnimationState.prototype.computeNotLast = function (entry) {
var timelines = entry.animation.timelines;
var timelinesCount = entry.animation.timelines.length;
var timelineMode = entry.timelineMode;
var propertyIDs = this.propertyIDs;
for (var i = 0; i < timelinesCount; i++) {
if (timelines[i] instanceof spine.AttachmentTimeline) {
var timeline = timelines[i];
if (!propertyIDs.add(timeline.slotIndex))
timelineMode[i] |= AnimationState.NOT_LAST;
timelineMode[i] = AnimationState.HOLD_FIRST;
}
}
};
@ -1946,9 +1964,11 @@ var spine;
AnimationState.emptyAnimation = new spine.Animation("<empty>", [], 0);
AnimationState.SUBSEQUENT = 0;
AnimationState.FIRST = 1;
AnimationState.HOLD = 2;
AnimationState.HOLD_MIX = 3;
AnimationState.NOT_LAST = 4;
AnimationState.HOLD_SUBSEQUENT = 2;
AnimationState.HOLD_FIRST = 3;
AnimationState.HOLD_MIX = 4;
AnimationState.SETUP = 1;
AnimationState.CURRENT = 2;
return AnimationState;
}());
spine.AnimationState = AnimationState;
@ -2161,11 +2181,15 @@ var spine;
this.errors = {};
this.toLoad = 0;
this.loaded = 0;
this.rawDataUris = {};
this.textureLoader = textureLoader;
this.pathPrefix = pathPrefix;
}
AssetManager.downloadText = function (url, success, error) {
AssetManager.prototype.downloadText = function (url, success, error) {
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.onload = function () {
if (request.status == 200) {
@ -2180,8 +2204,10 @@ var spine;
};
request.send();
};
AssetManager.downloadBinary = function (url, success, error) {
AssetManager.prototype.downloadBinary = function (url, success, error) {
var request = new XMLHttpRequest();
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function () {
@ -2197,13 +2223,16 @@ var spine;
};
request.send();
};
AssetManager.prototype.setRawDataURI = function (path, data) {
this.rawDataUris[this.pathPrefix + path] = data;
};
AssetManager.prototype.loadBinary = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadBinary(path, function (data) {
this.downloadBinary(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2223,7 +2252,7 @@ var spine;
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (data) {
this.downloadText(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2242,12 +2271,13 @@ var spine;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
var storagePath = path;
this.toLoad++;
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.assets[storagePath] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
@ -2260,32 +2290,10 @@ var spine;
if (error)
error(path, "Couldn't load image " + path);
};
if (this.rawDataUris[path])
path = this.rawDataUris[path];
img.src = path;
};
AssetManager.prototype.loadTextureData = function (path, data, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
var img = new Image();
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
success(path, img);
};
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
_this.toLoad--;
_this.loaded++;
if (error)
error(path, "Couldn't load image " + path);
};
img.src = data;
};
AssetManager.prototype.loadTextureAtlas = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
@ -2293,12 +2301,12 @@ var spine;
var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : "";
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
this.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
atlasPages.push(parent + "/" + path);
atlasPages.push(parent == "" ? path : parent + "/" + path);
var image = document.createElement("img");
image.width = 16;
image.height = 16;
@ -2322,7 +2330,7 @@ var spine;
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
return _this.get(parent + "/" + path);
return _this.get(parent == "" ? path : parent + "/" + path);
});
_this.assets[path] = atlas;
if (success)
@ -2560,6 +2568,8 @@ var spine;
var prx = 0;
if (s > 0.0001) {
s = Math.abs(pa * pd - pb * pc) / s;
pa /= this.skeleton.scaleX;
pc /= this.skeleton.scaleY;
pb = pc * s;
pd = pa * s;
prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg;
@ -2830,10 +2840,27 @@ var spine;
if (!bone.appliedValid)
bone.updateAppliedTransform();
var p = bone.parent;
var id = 1 / (p.a * p.d - p.b * p.c);
var x = targetX - p.worldX, y = targetY - p.worldY;
var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay;
var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation;
var pa = p.a, pb = p.b, pc = p.c, pd = p.d;
var rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;
switch (bone.data.transformMode) {
case spine.TransformMode.OnlyTranslation:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
break;
case spine.TransformMode.NoRotationOrReflection:
var s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
var sa = pa / bone.skeleton.scaleX;
var sc = pc / bone.skeleton.scaleY;
pb = -sc * s * bone.skeleton.scaleX;
pd = sa * s * bone.skeleton.scaleY;
rotationIK += Math.atan2(sc, sa) * spine.MathUtils.radDeg;
default:
var x = targetX - p.worldX, y = targetY - p.worldY;
var d = pa * pd - pb * pc;
tx = (x * pd - y * pb) / d - bone.ax;
ty = (y * pa - x * pc) / d - bone.ay;
}
rotationIK += Math.atan2(ty, tx) * spine.MathUtils.radDeg;
if (bone.ascaleX < 0)
rotationIK += 180;
if (rotationIK > 180)
@ -2842,6 +2869,12 @@ var spine;
rotationIK += 360;
var sx = bone.ascaleX, sy = bone.ascaleY;
if (compress || stretch) {
switch (bone.data.transformMode) {
case spine.TransformMode.NoScale:
case spine.TransformMode.NoScaleOrReflection:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
}
var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
var s = (dd / b - 1) * alpha + 1;
@ -3500,6 +3533,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3519,6 +3553,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3538,7 +3573,6 @@ var spine;
if (!this.queueAsset(clientId, textureLoader, path))
return;
var img = new Image();
img.src = path;
img.crossOrigin = "anonymous";
img.onload = function (ev) {
_this.rawAssets[path] = img;
@ -3546,6 +3580,7 @@ var spine;
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
};
img.src = path;
};
SharedAssetManager.prototype.get = function (clientId, path) {
path = this.pathPrefix + path;
@ -4071,6 +4106,8 @@ var spine;
var input = new BinaryInput(binary);
skeletonData.hash = input.readString();
skeletonData.version = input.readString();
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = input.readFloat();
skeletonData.y = input.readFloat();
skeletonData.width = input.readFloat();
@ -5059,7 +5096,7 @@ var spine;
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
for (var i = 0, n_2 = clippingPolygons.length; i < n_2; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
@ -5481,6 +5518,8 @@ var spine;
if (skeletonMap != null) {
skeletonData.hash = skeletonMap.hash;
skeletonData.version = skeletonMap.spine;
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = skeletonMap.x;
skeletonData.y = skeletonMap.y;
skeletonData.width = skeletonMap.width;
@ -6158,7 +6197,7 @@ var spine;
skeletonData.animations.push(new spine.Animation(name, timelines, duration));
};
SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) {
if (!map.curve)
if (!map.hasOwnProperty("curve"))
return;
if (map.curve == "stepped")
timeline.setStepped(frameIndex);
@ -7473,9 +7512,7 @@ var spine;
};
Pool.prototype.freeAll = function (items) {
for (var i = 0; i < items.length; i++) {
if (items[i].reset)
items[i].reset();
this.items[i] = items[i];
this.free(items[i]);
}
};
Pool.prototype.clear = function () {
@ -8017,7 +8054,7 @@ var spine;
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
};
RegionAttachment.prototype.copy = function () {
var copy = new RegionAttachment(name);
var copy = new RegionAttachment(this.name);
copy.region = this.region;
copy.rendererObject = this.rendererObject;
copy.path = this.path;

File diff suppressed because one or more lines are too long

View file

@ -144,6 +144,7 @@ declare module spine {
getFrameCount(): number;
setFrame(frameIndex: number, time: number, attachmentName: string): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string): void;
}
class DeformTimeline extends CurveTimeline {
slotIndex: number;
@ -248,12 +249,15 @@ declare module spine {
static emptyAnimation: Animation;
static SUBSEQUENT: number;
static FIRST: number;
static HOLD: number;
static HOLD_SUBSEQUENT: number;
static HOLD_FIRST: number;
static HOLD_MIX: number;
static NOT_LAST: number;
static SETUP: number;
static CURRENT: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
unkeyedState: number;
events: Event[];
listeners: AnimationStateListener[];
queue: EventQueue;
@ -265,6 +269,8 @@ declare module spine {
updateMixingFrom(to: TrackEntry, delta: number): boolean;
apply(skeleton: Skeleton): boolean;
applyMixingFrom(to: TrackEntry, skeleton: Skeleton, blend: MixBlend): number;
applyAttachmentTimeline(timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean): void;
setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string, attachments: boolean): void;
applyRotateTimeline(timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend, timelinesRotation: Array<number>, i: number, firstFrame: boolean): void;
queueEvents(entry: TrackEntry, animationTime: number): void;
clearTracks(): void;
@ -282,7 +288,6 @@ declare module spine {
disposeNext(entry: TrackEntry): void;
_animationsChanged(): void;
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
@ -384,13 +389,14 @@ declare module spine {
private errors;
private toLoad;
private loaded;
private rawDataUris;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
private static downloadText;
private static downloadBinary;
private downloadText;
private downloadBinary;
setRawDataURI(path: string, data: string): void;
loadBinary(path: string, success?: (path: string, binary: Uint8Array) => void, error?: (path: string, error: string) => void): void;
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureAtlas(path: string, success?: (path: string, atlas: TextureAtlas) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
@ -848,8 +854,9 @@ declare module spine {
bone: Bone;
color: Color;
darkColor: Color;
private attachment;
attachment: Attachment;
private attachmentTime;
attachmentState: number;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
@ -1361,6 +1368,7 @@ declare module spine.webgl {
private texture;
private boundUnit;
private useMipMaps;
static DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL: boolean;
constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, image: HTMLImageElement, useMipMaps?: boolean);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
static validateMagFilter(magFilter: TextureFilter): TextureFilter.Nearest | TextureFilter.Linear | TextureFilter.Linear;

View file

@ -2,7 +2,7 @@ var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
@ -675,17 +675,15 @@ var spine;
var slot = skeleton.slots[this.slotIndex];
if (!slot.bone.active)
return;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
var attachmentName_1 = slot.data.attachmentName;
slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1));
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frames = this.frames;
if (time < frames[0]) {
if (blend == MixBlend.setup || blend == MixBlend.first) {
var attachmentName_2 = slot.data.attachmentName;
slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2));
}
if (blend == MixBlend.setup || blend == MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName);
return;
}
var frameIndex = 0;
@ -697,6 +695,9 @@ var spine;
skeleton.slots[this.slotIndex]
.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
};
AttachmentTimeline.prototype.setAttachment = function (skeleton, slot, attachmentName) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName);
};
return AttachmentTimeline;
}());
spine.AttachmentTimeline = AttachmentTimeline;
@ -798,6 +799,7 @@ var spine;
case MixBlend.replace:
for (var i_5 = 0; i_5 < vertexCount; i_5++)
deform[i_5] += (lastVertices[i_5] - deform[i_5]) * alpha;
break;
case MixBlend.add:
var vertexAttachment = slotAttachment;
if (vertexAttachment.bones == null) {
@ -954,8 +956,9 @@ var spine;
DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
var drawOrder = skeleton.drawOrder;
var slots = skeleton.slots;
if (direction == MixDirection.mixOut && blend == MixBlend.setup) {
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
if (direction == MixDirection.mixOut) {
if (blend == MixBlend.setup)
spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
return;
}
var frames = this.frames;
@ -1347,6 +1350,7 @@ var spine;
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.unkeyedState = 0;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
@ -1436,12 +1440,12 @@ var spine;
var events = this.events;
var tracks = this.tracks;
var applied = false;
for (var i = 0, n = tracks.length; i < n; i++) {
var current = tracks[i];
for (var i_16 = 0, n_1 = tracks.length; i_16 < n_1; i_16++) {
var current = tracks[i_16];
if (current == null || current.delay > 0)
continue;
applied = true;
var blend = i == 0 ? spine.MixBlend.first : current.mixBlend;
var blend = i_16 == 0 ? spine.MixBlend.first : current.mixBlend;
var mix = current.alpha;
if (current.mixingFrom != null)
mix *= this.applyMixingFrom(current, skeleton, blend);
@ -1450,10 +1454,14 @@ var spine;
var animationLast = current.animationLast, animationTime = current.getAnimationTime();
var timelineCount = current.animation.timelines.length;
var timelines = current.animation.timelines;
if ((i == 0 && mix == 1) || blend == spine.MixBlend.add) {
if ((i_16 == 0 && mix == 1) || blend == spine.MixBlend.add) {
for (var ii = 0; ii < timelineCount; ii++) {
spine.Utils.webkit602BugfixHelper(mix, blend);
timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
var timeline = timelines[ii];
if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true);
else
timeline.apply(skeleton, animationLast, animationTime, events, mix, blend, spine.MixDirection.mixIn);
}
}
else {
@ -1463,14 +1471,17 @@ var spine;
spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null);
var timelinesRotation = current.timelinesRotation;
for (var ii = 0; ii < timelineCount; ii++) {
var timeline = timelines[ii];
var timelineBlend = (timelineMode[ii] & (AnimationState.NOT_LAST - 1)) == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
var timeline_1 = timelines[ii];
var timelineBlend = timelineMode[ii] == AnimationState.SUBSEQUENT ? blend : spine.MixBlend.setup;
if (timeline_1 instanceof spine.RotateTimeline) {
this.applyRotateTimeline(timeline_1, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
}
else if (timeline_1 instanceof spine.AttachmentTimeline) {
this.applyAttachmentTimeline(timeline_1, skeleton, animationTime, blend, true);
}
else {
spine.Utils.webkit602BugfixHelper(mix, blend);
timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
timeline_1.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, spine.MixDirection.mixIn);
}
}
}
@ -1479,6 +1490,16 @@ var spine;
current.nextAnimationLast = animationTime;
current.nextTrackLast = current.trackTime;
}
var setupState = this.unkeyedState + AnimationState.SETUP;
var slots = skeleton.slots;
for (var i = 0, n = skeleton.slots.length; i < n; i++) {
var slot = slots[i];
if (slot.attachmentState == setupState) {
var attachmentName = slot.data.attachmentName;
slot.attachment = (attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName));
}
}
this.unkeyedState += 2;
this.queue.drain();
return applied;
};
@ -1522,23 +1543,22 @@ var spine;
var direction = spine.MixDirection.mixOut;
var timelineBlend = void 0;
var alpha = 0;
switch (timelineMode[i] & (AnimationState.NOT_LAST - 1)) {
switch (timelineMode[i]) {
case AnimationState.SUBSEQUENT:
timelineBlend = blend;
if (!attachments && timeline instanceof spine.AttachmentTimeline) {
if ((timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
continue;
timelineBlend = spine.MixBlend.setup;
}
if (!drawOrder && timeline instanceof spine.DrawOrderTimeline)
continue;
timelineBlend = blend;
alpha = alphaMix;
break;
case AnimationState.FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaMix;
break;
case AnimationState.HOLD:
case AnimationState.HOLD_SUBSEQUENT:
timelineBlend = blend;
alpha = alphaHold;
break;
case AnimationState.HOLD_FIRST:
timelineBlend = spine.MixBlend.setup;
alpha = alphaHold;
break;
@ -1551,18 +1571,12 @@ var spine;
from.totalAlpha += alpha;
if (timeline instanceof spine.RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else if (timeline instanceof spine.AttachmentTimeline)
this.applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments);
else {
spine.Utils.webkit602BugfixHelper(alpha, blend);
if (timelineBlend == spine.MixBlend.setup) {
if (timeline instanceof spine.AttachmentTimeline) {
if (attachments || (timelineMode[i] & AnimationState.NOT_LAST) == AnimationState.NOT_LAST)
direction = spine.MixDirection.mixIn;
}
else if (timeline instanceof spine.DrawOrderTimeline) {
if (drawOrder)
direction = spine.MixDirection.mixIn;
}
}
if (drawOrder && timeline instanceof spine.DrawOrderTimeline && timelineBlend == spine.MixBlend.setup)
direction = spine.MixDirection.mixIn;
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, direction);
}
}
@ -1574,6 +1588,31 @@ var spine;
from.nextTrackLast = from.trackTime;
return mix;
};
AnimationState.prototype.applyAttachmentTimeline = function (timeline, skeleton, time, blend, attachments) {
var slot = skeleton.slots[timeline.slotIndex];
if (!slot.bone.active)
return;
var frames = timeline.frames;
if (time < frames[0]) {
if (blend == spine.MixBlend.setup || blend == spine.MixBlend.first)
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
}
else {
var frameIndex;
if (time >= frames[frames.length - 1])
frameIndex = frames.length - 1;
else
frameIndex = spine.Animation.binarySearch(frames, time) - 1;
this.setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments);
}
if (slot.attachmentState <= this.unkeyedState)
slot.attachmentState = this.unkeyedState + AnimationState.SETUP;
};
AnimationState.prototype.setAttachment = function (skeleton, slot, attachmentName, attachments) {
slot.attachment = attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName);
if (attachments)
slot.attachmentState = this.unkeyedState + AnimationState.CURRENT;
};
AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
if (firstFrame)
timelinesRotation[i] = 0;
@ -1836,6 +1875,7 @@ var spine;
entry.interruptAlpha = 1;
entry.mixTime = 0;
entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation);
entry.mixBlend = spine.MixBlend.replace;
return entry;
};
AnimationState.prototype.disposeNext = function (entry) {
@ -1861,14 +1901,6 @@ var spine;
entry = entry.mixingTo;
} while (entry != null);
}
this.propertyIDs.clear();
for (var i = this.tracks.length - 1; i >= 0; i--) {
var entry = this.tracks[i];
while (entry != null) {
this.computeNotLast(entry);
entry = entry.mixingFrom;
}
}
};
AnimationState.prototype.computeHold = function (entry) {
var to = entry.mixingTo;
@ -1880,8 +1912,7 @@ var spine;
var propertyIDs = this.propertyIDs;
if (to != null && to.holdPrevious) {
for (var i = 0; i < timelinesCount; i++) {
propertyIDs.add(timelines[i].getPropertyId());
timelineMode[i] = AnimationState.HOLD;
timelineMode[i] = propertyIDs.add(timelines[i].getPropertyId()) ? AnimationState.HOLD_FIRST : AnimationState.HOLD_SUBSEQUENT;
}
return;
}
@ -1905,20 +1936,7 @@ var spine;
}
break;
}
timelineMode[i] = AnimationState.HOLD;
}
}
};
AnimationState.prototype.computeNotLast = function (entry) {
var timelines = entry.animation.timelines;
var timelinesCount = entry.animation.timelines.length;
var timelineMode = entry.timelineMode;
var propertyIDs = this.propertyIDs;
for (var i = 0; i < timelinesCount; i++) {
if (timelines[i] instanceof spine.AttachmentTimeline) {
var timeline = timelines[i];
if (!propertyIDs.add(timeline.slotIndex))
timelineMode[i] |= AnimationState.NOT_LAST;
timelineMode[i] = AnimationState.HOLD_FIRST;
}
}
};
@ -1946,9 +1964,11 @@ var spine;
AnimationState.emptyAnimation = new spine.Animation("<empty>", [], 0);
AnimationState.SUBSEQUENT = 0;
AnimationState.FIRST = 1;
AnimationState.HOLD = 2;
AnimationState.HOLD_MIX = 3;
AnimationState.NOT_LAST = 4;
AnimationState.HOLD_SUBSEQUENT = 2;
AnimationState.HOLD_FIRST = 3;
AnimationState.HOLD_MIX = 4;
AnimationState.SETUP = 1;
AnimationState.CURRENT = 2;
return AnimationState;
}());
spine.AnimationState = AnimationState;
@ -2161,11 +2181,15 @@ var spine;
this.errors = {};
this.toLoad = 0;
this.loaded = 0;
this.rawDataUris = {};
this.textureLoader = textureLoader;
this.pathPrefix = pathPrefix;
}
AssetManager.downloadText = function (url, success, error) {
AssetManager.prototype.downloadText = function (url, success, error) {
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.onload = function () {
if (request.status == 200) {
@ -2180,8 +2204,10 @@ var spine;
};
request.send();
};
AssetManager.downloadBinary = function (url, success, error) {
AssetManager.prototype.downloadBinary = function (url, success, error) {
var request = new XMLHttpRequest();
if (this.rawDataUris[url])
url = this.rawDataUris[url];
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function () {
@ -2197,13 +2223,16 @@ var spine;
};
request.send();
};
AssetManager.prototype.setRawDataURI = function (path, data) {
this.rawDataUris[this.pathPrefix + path] = data;
};
AssetManager.prototype.loadBinary = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadBinary(path, function (data) {
this.downloadBinary(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2223,7 +2252,7 @@ var spine;
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (data) {
this.downloadText(path, function (data) {
_this.assets[path] = data;
if (success)
success(path, data);
@ -2242,12 +2271,13 @@ var spine;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
var storagePath = path;
this.toLoad++;
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.assets[storagePath] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
@ -2260,32 +2290,10 @@ var spine;
if (error)
error(path, "Couldn't load image " + path);
};
if (this.rawDataUris[path])
path = this.rawDataUris[path];
img.src = path;
};
AssetManager.prototype.loadTextureData = function (path, data, success, error) {
var _this = this;
if (success === void 0) { success = null; }
if (error === void 0) { error = null; }
path = this.pathPrefix + path;
this.toLoad++;
var img = new Image();
img.onload = function (ev) {
var texture = _this.textureLoader(img);
_this.assets[path] = texture;
_this.toLoad--;
_this.loaded++;
if (success)
success(path, img);
};
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
_this.toLoad--;
_this.loaded++;
if (error)
error(path, "Couldn't load image " + path);
};
img.src = data;
};
AssetManager.prototype.loadTextureAtlas = function (path, success, error) {
var _this = this;
if (success === void 0) { success = null; }
@ -2293,12 +2301,12 @@ var spine;
var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : "";
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
this.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
atlasPages.push(parent + "/" + path);
atlasPages.push(parent == "" ? path : parent + "/" + path);
var image = document.createElement("img");
image.width = 16;
image.height = 16;
@ -2322,7 +2330,7 @@ var spine;
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
return _this.get(parent + "/" + path);
return _this.get(parent == "" ? path : parent + "/" + path);
});
_this.assets[path] = atlas;
if (success)
@ -2560,6 +2568,8 @@ var spine;
var prx = 0;
if (s > 0.0001) {
s = Math.abs(pa * pd - pb * pc) / s;
pa /= this.skeleton.scaleX;
pc /= this.skeleton.scaleY;
pb = pc * s;
pd = pa * s;
prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg;
@ -2830,10 +2840,27 @@ var spine;
if (!bone.appliedValid)
bone.updateAppliedTransform();
var p = bone.parent;
var id = 1 / (p.a * p.d - p.b * p.c);
var x = targetX - p.worldX, y = targetY - p.worldY;
var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay;
var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation;
var pa = p.a, pb = p.b, pc = p.c, pd = p.d;
var rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;
switch (bone.data.transformMode) {
case spine.TransformMode.OnlyTranslation:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
break;
case spine.TransformMode.NoRotationOrReflection:
var s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
var sa = pa / bone.skeleton.scaleX;
var sc = pc / bone.skeleton.scaleY;
pb = -sc * s * bone.skeleton.scaleX;
pd = sa * s * bone.skeleton.scaleY;
rotationIK += Math.atan2(sc, sa) * spine.MathUtils.radDeg;
default:
var x = targetX - p.worldX, y = targetY - p.worldY;
var d = pa * pd - pb * pc;
tx = (x * pd - y * pb) / d - bone.ax;
ty = (y * pa - x * pc) / d - bone.ay;
}
rotationIK += Math.atan2(ty, tx) * spine.MathUtils.radDeg;
if (bone.ascaleX < 0)
rotationIK += 180;
if (rotationIK > 180)
@ -2842,6 +2869,12 @@ var spine;
rotationIK += 360;
var sx = bone.ascaleX, sy = bone.ascaleY;
if (compress || stretch) {
switch (bone.data.transformMode) {
case spine.TransformMode.NoScale:
case spine.TransformMode.NoScaleOrReflection:
tx = targetX - bone.worldX;
ty = targetY - bone.worldY;
}
var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
var s = (dd / b - 1) * alpha + 1;
@ -3500,6 +3533,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3519,6 +3553,7 @@ var spine;
if (!this.queueAsset(clientId, null, path))
return;
var request = new XMLHttpRequest();
request.overrideMimeType("text/html");
request.onreadystatechange = function () {
if (request.readyState == XMLHttpRequest.DONE) {
if (request.status >= 200 && request.status < 300) {
@ -3538,7 +3573,6 @@ var spine;
if (!this.queueAsset(clientId, textureLoader, path))
return;
var img = new Image();
img.src = path;
img.crossOrigin = "anonymous";
img.onload = function (ev) {
_this.rawAssets[path] = img;
@ -3546,6 +3580,7 @@ var spine;
img.onerror = function (ev) {
_this.errors[path] = "Couldn't load image " + path;
};
img.src = path;
};
SharedAssetManager.prototype.get = function (clientId, path) {
path = this.pathPrefix + path;
@ -4071,6 +4106,8 @@ var spine;
var input = new BinaryInput(binary);
skeletonData.hash = input.readString();
skeletonData.version = input.readString();
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = input.readFloat();
skeletonData.y = input.readFloat();
skeletonData.width = input.readFloat();
@ -5059,7 +5096,7 @@ var spine;
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
for (var i = 0, n_2 = clippingPolygons.length; i < n_2; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
@ -5481,6 +5518,8 @@ var spine;
if (skeletonMap != null) {
skeletonData.hash = skeletonMap.hash;
skeletonData.version = skeletonMap.spine;
if ("3.8.75" == skeletonData.version)
throw new Error("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = skeletonMap.x;
skeletonData.y = skeletonMap.y;
skeletonData.width = skeletonMap.width;
@ -6158,7 +6197,7 @@ var spine;
skeletonData.animations.push(new spine.Animation(name, timelines, duration));
};
SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) {
if (!map.curve)
if (!map.hasOwnProperty("curve"))
return;
if (map.curve == "stepped")
timeline.setStepped(frameIndex);
@ -7473,9 +7512,7 @@ var spine;
};
Pool.prototype.freeAll = function (items) {
for (var i = 0; i < items.length; i++) {
if (items[i].reset)
items[i].reset();
this.items[i] = items[i];
this.free(items[i]);
}
};
Pool.prototype.clear = function () {
@ -8017,7 +8054,7 @@ var spine;
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
};
RegionAttachment.prototype.copy = function () {
var copy = new RegionAttachment(name);
var copy = new RegionAttachment(this.name);
copy.region = this.region;
copy.rendererObject = this.rendererObject;
copy.path = this.path;
@ -8253,6 +8290,8 @@ var spine;
this.texture = this.context.gl.createTexture();
}
this.bind();
if (GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL)
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
@ -8282,6 +8321,7 @@ var spine;
var gl = this.context.gl;
gl.deleteTexture(this.texture);
};
GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false;
return GLTexture;
}(spine.Texture));
webgl.GLTexture = GLTexture;
@ -10011,11 +10051,11 @@ var spine;
var nn = clip.worldVerticesLength;
var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0);
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
for (var i_16 = 0, n_2 = world.length; i_16 < n_2; i_16 += 2) {
var x = world[i_16];
var y = world[i_16 + 1];
var x2 = world[(i_16 + 2) % world.length];
var y2 = world[(i_16 + 3) % world.length];
for (var i_17 = 0, n_3 = world.length; i_17 < n_3; i_17 += 2) {
var x = world[i_17];
var y = world[i_17 + 1];
var x2 = world[(i_17 + 2) % world.length];
var y2 = world[(i_17 + 3) % world.length];
shapes.line(x, y, x2, y2);
}
}
@ -10176,7 +10216,7 @@ var spine;
var vertexEffect = this.vertexEffect;
var verts = clippedVertices;
if (!twoColorTint) {
for (var v = 0, n_3 = clippedVertices.length; v < n_3; v += vertexSize) {
for (var v = 0, n_4 = clippedVertices.length; v < n_4; v += vertexSize) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]);
@ -10195,7 +10235,7 @@ var spine;
}
}
else {
for (var v = 0, n_4 = clippedVertices.length; v < n_4; v += vertexSize) {
for (var v = 0, n_5 = clippedVertices.length; v < n_5; v += vertexSize) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempLight.set(verts[v + 2], verts[v + 3], verts[v + 4], verts[v + 5]);
@ -10225,7 +10265,7 @@ var spine;
if (this.vertexEffect != null) {
var vertexEffect = this.vertexEffect;
if (!twoColorTint) {
for (var v = 0, u = 0, n_5 = renderable.numFloats; v < n_5; v += vertexSize, u += 2) {
for (var v = 0, u = 0, n_6 = renderable.numFloats; v < n_6; v += vertexSize, u += 2) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempUv.x = uvs[u];
@ -10244,7 +10284,7 @@ var spine;
}
}
else {
for (var v = 0, u = 0, n_6 = renderable.numFloats; v < n_6; v += vertexSize, u += 2) {
for (var v = 0, u = 0, n_7 = renderable.numFloats; v < n_7; v += vertexSize, u += 2) {
tempPos.x = verts[v];
tempPos.y = verts[v + 1];
tempUv.x = uvs[u];
@ -10269,7 +10309,7 @@ var spine;
}
else {
if (!twoColorTint) {
for (var v = 2, u = 0, n_7 = renderable.numFloats; v < n_7; v += vertexSize, u += 2) {
for (var v = 2, u = 0, n_8 = renderable.numFloats; v < n_8; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
@ -10279,7 +10319,7 @@ var spine;
}
}
else {
for (var v = 2, u = 0, n_8 = renderable.numFloats; v < n_8; v += vertexSize, u += 2) {
for (var v = 2, u = 0, n_9 = renderable.numFloats; v < n_9; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;

File diff suppressed because one or more lines are too long

View file

@ -30,11 +30,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-both.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -28,11 +28,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-both.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -30,11 +30,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -28,11 +28,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -30,11 +30,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -28,11 +28,19 @@ module.exports = {
rules: [
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},

View file

@ -3,12 +3,11 @@ let fs = require('fs-extra');
/*
BitmapMask.frag
BitmapMask.vert
DeferredDiffuse.frag
DeferredDiffuse.vert
ForwardDiffuse.frag
GBuffer.frag
TextureTint.frag
TextureTint.vert
Light.frag
Single.frag
Single.vert
Multi.frag
Multi.vert
*/
let srcdir = './src/renderer/webgl/shaders/src/';

View file

@ -0,0 +1,35 @@
let scene:Phaser.Scene = new Phaser.Scene("");
let blitter = new Phaser.GameObjects.Blitter(scene, 10, 10);
let conf:GameConfig = {
type:Phaser.AUTO,
width: 100,
height: 100,
zoom: 1,
resolution: 1
}
let tex:Phaser.Textures.Texture = <any>null;
tex.source[0].setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.NEAREST);
let sprite = new Phaser.GameObjects.Sprite(scene, 0, 0, "test");
class MyVec extends Phaser.Geom.Rectangle {
public extra() {
}
}
let p = new MyVec();
sprite.getBounds(p).extra();
let container = scene.add.container(0, 0);
container.getWorldTransformMatrix();

View file

@ -65,6 +65,26 @@ var GridAlign = function (items, options)
// We keep laying them out vertically until we've done them all
tempZone.y += cellHeight;
}
else if (heightSet && !widthSet)
{
// We keep laying them out until we hit the column limit
cy += cellHeight;
tempZone.y += cellHeight;
if (cy === h)
{
cy = 0;
cx += cellWidth;
tempZone.y = y;
tempZone.x += cellWidth;
if (cx === w)
{
// We've hit the column limit, so return, even if there are items left
break;
}
}
}
else
{
// We keep laying them out until we hit the column limit

View file

@ -34,8 +34,14 @@ var SetOrigin = function (items, originX, originY, stepX, stepY, index, directio
if (originY === undefined || originY === null) { originY = originX; }
PropertyValueSet(items, 'originX', originX, stepX, index, direction);
PropertyValueSet(items, 'originY', originY, stepY, index, direction);
return PropertyValueSet(items, 'originY', originY, stepY, index, direction);
items.forEach(function (item)
{
item.updateDisplayOrigin();
});
return items;
};
module.exports = SetOrigin;

View file

@ -6,25 +6,29 @@
var Clamp = require('../math/Clamp');
var Class = require('../utils/Class');
var EventEmitter = require('eventemitter3');
var Events = require('./events');
var FindClosestInSorted = require('../utils/array/FindClosestInSorted');
var Frame = require('./AnimationFrame');
var GetValue = require('../utils/object/GetValue');
var SortByDigits = require('../utils/array/SortByDigits');
/**
* @classdesc
* A Frame based Animation.
*
* This consists of a key, some default values (like the frame rate) and a bunch of Frame objects.
* Animations in Phaser consist of a sequence of `AnimationFrame` objects, which are managed by
* this class, along with properties that impact playback, such as the animations frame rate
* or delay.
*
* The Animation Manager creates these. Game Objects don't own an instance of these directly.
* Game Objects have the Animation Component, which are like playheads to global Animations (these objects)
* So multiple Game Objects can have playheads all pointing to this one Animation instance.
* This class contains all of the properties and methods needed to handle playback of the animation
* directly to an `AnimationState` instance, which is owned by a Sprite, or similar Game Object.
*
* You don't typically create an instance of this class directly, but instead go via
* either the `AnimationManager` or the `AnimationState` and use their `create` methods,
* depending on if you need a global animation, or local to a specific Sprite.
*
* @class Animation
* @memberof Phaser.Animations
* @extends Phaser.Events.EventEmitter
* @constructor
* @since 3.0.0
*
@ -34,14 +38,10 @@ var GetValue = require('../utils/object/GetValue');
*/
var Animation = new Class({
Extends: EventEmitter,
initialize:
function Animation (manager, key, config)
{
EventEmitter.call(this);
/**
* A reference to the global Animation Manager.
*
@ -80,7 +80,8 @@ var Animation = new Class({
this.frames = this.getFrames(
manager.textureManager,
GetValue(config, 'frames', []),
GetValue(config, 'defaultTextureKey', null)
GetValue(config, 'defaultTextureKey', null),
GetValue(config, 'sortFrames', true)
);
/**
@ -104,27 +105,6 @@ var Animation = new Class({
*/
this.duration = GetValue(config, 'duration', null);
if (this.duration === null && this.frameRate === null)
{
// No duration or frameRate given, use default frameRate of 24fps
this.frameRate = 24;
this.duration = (this.frameRate / this.frames.length) * 1000;
}
else if (this.duration && this.frameRate === null)
{
// Duration given but no frameRate, so set the frameRate based on duration
// I.e. 12 frames in the animation, duration = 4000 ms
// So frameRate is 12 / (4000 / 1000) = 3 fps
this.frameRate = this.frames.length / (this.duration / 1000);
}
else
{
// frameRate given, derive duration from it (even if duration also specified)
// I.e. 15 frames in the animation, frameRate = 30 fps
// So duration is 15 / 30 = 0.5 * 1000 (half a second, or 500ms)
this.duration = (this.frames.length / this.frameRate) * 1000;
}
/**
* How many ms per frame, not including frame specific modifiers.
*
@ -132,14 +112,14 @@ var Animation = new Class({
* @type {integer}
* @since 3.0.0
*/
this.msPerFrame = 1000 / this.frameRate;
this.msPerFrame;
/**
* Skip frames if the time lags, or always advanced anyway?
*
* @name Phaser.Animations.Animation#skipMissedFrames
* @type {boolean}
* @default false
* @default true
* @since 3.0.0
*/
this.skipMissedFrames = GetValue(config, 'skipMissedFrames', true);
@ -214,8 +194,65 @@ var Animation = new Class({
*/
this.paused = false;
this.manager.on(Events.PAUSE_ALL, this.pause, this);
this.manager.on(Events.RESUME_ALL, this.resume, this);
this.calculateDuration(this, this.getTotalFrames(), this.duration, this.frameRate);
if (this.manager.on)
{
this.manager.on(Events.PAUSE_ALL, this.pause, this);
this.manager.on(Events.RESUME_ALL, this.resume, this);
}
},
/**
* Gets the total number of frames in this animation.
*
* @method Phaser.Animations.Animation#getTotalFrames
* @since 3.50.0
*
* @return {number} The total number of frames in this animation.
*/
getTotalFrames: function ()
{
return this.frames.length;
},
/**
* Calculates the duration, frame rate and msPerFrame values.
*
* @method Phaser.Animations.Animation#calculateDuration
* @since 3.50.0
*
* @param {(Phaser.Animations.Animation|Phaser.GameObjects.Components.Animation)} target - The target to set the values on.
* @param {number} totalFrames - The total number of frames in the animation.
* @param {number} duration - The duration to calculate the frame rate from.
* @param {number} frameRate - The frame ate to calculate the duration from.
*/
calculateDuration: function (target, totalFrames, duration, frameRate)
{
if (duration === null && frameRate === null)
{
// No duration or frameRate given, use default frameRate of 24fps
target.frameRate = 24;
target.duration = (24 / totalFrames) * 1000;
}
else if (duration && frameRate === null)
{
// Duration given but no frameRate, so set the frameRate based on duration
// I.e. 12 frames in the animation, duration = 4000 ms
// So frameRate is 12 / (4000 / 1000) = 3 fps
target.duration = duration;
target.frameRate = totalFrames / (duration / 1000);
}
else
{
// frameRate given, derive duration from it (even if duration also specified)
// I.e. 15 frames in the animation, frameRate = 30 fps
// So duration is 15 / 30 = 0.5 * 1000 (half a second, or 500ms)
target.frameRate = frameRate;
target.duration = (totalFrames / frameRate) * 1000;
}
target.msPerFrame = 1000 / target.frameRate;
},
/**
@ -287,26 +324,6 @@ var Animation = new Class({
return (index >= 0 && index < this.frames.length);
},
/**
* Called internally when this Animation completes playback.
* Optionally, hides the parent Game Object, then stops playback.
*
* @method Phaser.Animations.Animation#completeAnimation
* @protected
* @since 3.0.0
*
* @param {Phaser.GameObjects.Components.Animation} component - The Animation Component belonging to the Game Object invoking this call.
*/
completeAnimation: function (component)
{
if (this.hideOnComplete)
{
component.parent.visible = false;
}
component.stop();
},
/**
* Called internally when this Animation first starts to play.
* Sets the accumulator and nextTick properties.
@ -316,20 +333,13 @@ var Animation = new Class({
* @since 3.0.0
*
* @param {Phaser.GameObjects.Components.Animation} component - The Animation Component belonging to the Game Object invoking this call.
* @param {boolean} [includeDelay=true] - If `true` the Animation Components delay value will be added to the `nextTick` total.
*/
getFirstTick: function (component, includeDelay)
getFirstTick: function (component)
{
if (includeDelay === undefined) { includeDelay = true; }
// When is the first update due?
component.accumulator = 0;
component.nextTick = component.msPerFrame + component.currentFrame.duration;
if (includeDelay)
{
component.nextTick += component._delay;
}
component.nextTick = component.msPerFrame + component.currentFrame.duration;
},
/**
@ -360,8 +370,10 @@ var Animation = new Class({
*
* @return {Phaser.Animations.AnimationFrame[]} An array of newly created AnimationFrame instances.
*/
getFrames: function (textureManager, frames, defaultTextureKey)
getFrames: function (textureManager, frames, defaultTextureKey, sortFrames)
{
if (sortFrames === undefined) { sortFrames = true; }
var out = [];
var prev;
var animationFrame;
@ -377,9 +389,14 @@ var Animation = new Class({
var texture = textureManager.get(textureKey);
var frameKeys = texture.getFrameNames();
if (sortFrames)
{
SortByDigits(frameKeys);
}
frames = [];
frameKeys.forEach(function (idx, value)
frameKeys.forEach(function (value)
{
frames.push({ key: textureKey, frame: value });
});
@ -460,57 +477,11 @@ var Animation = new Class({
*/
getNextTick: function (component)
{
// accumulator += delta * _timeScale
// after a large delta surge (perf issue for example) we need to adjust for it here
// When is the next update due?
component.accumulator -= component.nextTick;
component.nextTick = component.msPerFrame + component.currentFrame.duration;
},
/**
* Loads the Animation values into the Animation Component.
*
* @method Phaser.Animations.Animation#load
* @private
* @since 3.0.0
*
* @param {Phaser.GameObjects.Components.Animation} component - The Animation Component to load values into.
* @param {integer} startFrame - The start frame of the animation to load.
*/
load: function (component, startFrame)
{
if (startFrame >= this.frames.length)
{
startFrame = 0;
}
if (component.currentAnim !== this)
{
component.currentAnim = this;
component.frameRate = this.frameRate;
component.duration = this.duration;
component.msPerFrame = this.msPerFrame;
component.skipMissedFrames = this.skipMissedFrames;
component._delay = this.delay;
component._repeat = this.repeat;
component._repeatDelay = this.repeatDelay;
component._yoyo = this.yoyo;
}
var frame = this.frames[startFrame];
if (startFrame === 0 && !component.forward)
{
frame = this.getLastFrame();
}
component.updateFrame(frame);
},
/**
* Returns the frame closest to the given progress value between 0 and 1.
*
@ -540,14 +511,12 @@ var Animation = new Class({
{
var frame = component.currentFrame;
// TODO: Add frame skip support
if (frame.isLast)
{
// We're at the end of the animation
// Yoyo? (happens before repeat)
if (component._yoyo)
if (component.yoyo)
{
this.handleYoyoFrame(component, false);
}
@ -555,7 +524,7 @@ var Animation = new Class({
{
// Repeat (happens before complete)
if (component._reverse && component.forward)
if (component.inReverse && component.forward)
{
component.forward = false;
}
@ -566,7 +535,7 @@ var Animation = new Class({
}
else
{
this.completeAnimation(component);
component.complete();
}
}
else
@ -589,10 +558,9 @@ var Animation = new Class({
{
if (!isReverse) { isReverse = false; }
if (component._reverse === !isReverse && component.repeatCounter > 0)
if (component.inReverse === !isReverse && component.repeatCounter > 0)
{
if (!component._repeatDelay || component.pendingRepeat)
if (component.repeatDelay === 0 || component.pendingRepeat)
{
component.forward = isReverse;
}
@ -602,13 +570,13 @@ var Animation = new Class({
return;
}
if (component._reverse !== isReverse && component.repeatCounter === 0)
if (component.inReverse !== isReverse && component.repeatCounter === 0)
{
this.completeAnimation(component);
component.complete();
return;
}
component.forward = isReverse;
var frame = (isReverse) ? component.currentFrame.nextFrame : component.currentFrame.prevFrame;
@ -642,33 +610,30 @@ var Animation = new Class({
{
var frame = component.currentFrame;
// TODO: Add frame skip support
if (frame.isFirst)
{
// We're at the start of the animation
if (component._yoyo)
if (component.yoyo)
{
this.handleYoyoFrame(component, true);
}
else if (component.repeatCounter > 0)
{
if (component._reverse && !component.forward)
if (component.inReverse && !component.forward)
{
component.currentFrame = this.getLastFrame();
this.repeatAnimation(component);
}
else
{
// Repeat (happens before complete)
component.forward = true;
this.repeatAnimation(component);
}
}
else
{
this.completeAnimation(component);
component.complete();
}
}
else
@ -688,7 +653,7 @@ var Animation = new Class({
*/
updateAndGetNextTick: function (component, frame)
{
component.updateFrame(frame);
component.setCurrentFrame(frame);
this.getNextTick(component);
},
@ -752,60 +717,44 @@ var Animation = new Class({
{
if (component._pendingStop === 2)
{
return this.completeAnimation(component);
if (component._pendingStopValue === 0)
{
return component.stop();
}
else
{
component._pendingStopValue--;
}
}
if (component._repeatDelay > 0 && component.pendingRepeat === false)
if (component.repeatDelay > 0 && !component.pendingRepeat)
{
component.pendingRepeat = true;
component.accumulator -= component.nextTick;
component.nextTick += component._repeatDelay;
component.nextTick += component.repeatDelay;
}
else
{
component.repeatCounter--;
component.updateFrame(component.currentFrame[(component.forward) ? 'nextFrame' : 'prevFrame']);
if (component.forward)
{
component.setCurrentFrame(component.currentFrame.nextFrame);
}
else
{
component.setCurrentFrame(component.currentFrame.prevFrame);
}
if (component.isPlaying)
{
this.getNextTick(component);
component.pendingRepeat = false;
var frame = component.currentFrame;
var parent = component.parent;
this.emit(Events.ANIMATION_REPEAT, this, frame);
parent.emit(Events.SPRITE_ANIMATION_KEY_REPEAT + this.key, this, frame, component.repeatCounter, parent);
parent.emit(Events.SPRITE_ANIMATION_REPEAT, this, frame, component.repeatCounter, parent);
component.handleRepeat();
}
}
},
/**
* Sets the texture frame the animation uses for rendering.
*
* @method Phaser.Animations.Animation#setFrame
* @since 3.0.0
*
* @param {Phaser.GameObjects.Components.Animation} component - The Animation Component belonging to the Game Object invoking this call.
*/
setFrame: function (component)
{
// Work out which frame should be set next on the child, and set it
if (component.forward)
{
this.nextFrame(component);
}
else
{
this.previousFrame(component);
}
},
/**
* Converts the animation data to JSON.
*
@ -936,10 +885,11 @@ var Animation = new Class({
*/
destroy: function ()
{
this.removeAllListeners();
this.manager.off(Events.PAUSE_ALL, this.pause, this);
this.manager.off(Events.RESUME_ALL, this.resume, this);
if (this.manager.off)
{
this.manager.off(Events.PAUSE_ALL, this.pause, this);
this.manager.off(Events.RESUME_ALL, this.resume, this);
}
this.manager.remove(this.key);

View file

@ -10,8 +10,10 @@ var CustomMap = require('../structs/Map');
var EventEmitter = require('eventemitter3');
var Events = require('./events');
var GameEvents = require('../core/events');
var GetFastValue = require('../utils/object/GetFastValue');
var GetValue = require('../utils/object/GetValue');
var Pad = require('../utils/string/Pad');
var NumberArray = require('../utils/array/NumberArray');
/**
* @classdesc
@ -85,6 +87,17 @@ var AnimationManager = new Class({
*/
this.anims = new CustomMap();
/**
* A list of animation mix times.
*
* See the {@link #setMix} method for more details.
*
* @name Phaser.Animations.AnimationManager#mixes
* @type {Phaser.Structs.Map.<string>}
* @since 3.50.0
*/
this.mixes = new CustomMap();
/**
* Whether the Animation Manager is paused along with all of its Animations.
*
@ -121,6 +134,144 @@ var AnimationManager = new Class({
this.game.events.once(GameEvents.DESTROY, this.destroy, this);
},
/**
* Adds a mix between two animations.
*
* Mixing allows you to specify a unique delay between a pairing of animations.
*
* When playing Animation A on a Game Object, if you then play Animation B, and a
* mix exists, it will wait for the specified delay to be over before playing Animation B.
*
* This allows you to customise smoothing between different types of animation, such
* as blending between an idle and a walk state, or a running and a firing state.
*
* Note that mixing is only applied if you use the `Sprite.play` method. If you opt to use
* `playAfterRepeat` or `playAfterDelay` instead, those will take pririty and the mix
* delay will not be used.
*
* To update an existing mix, just call this method with the new delay.
*
* To remove a mix pairing, see the `removeMix` method.
*
* @method Phaser.Animations.AnimationManager#addMix
* @since 3.50.0
*
* @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A.
* @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B.
* @param {number} delay - The delay, in milliseconds, to wait when transitioning from Animation A to B.
*
* @return {this} This Animation Manager.
*/
addMix: function (animA, animB, delay)
{
var anims = this.anims;
var mixes = this.mixes;
var keyA = (typeof(animA) === 'string') ? animA : animA.key;
var keyB = (typeof(animB) === 'string') ? animB : animB.key;
if (anims.has(keyA) && anims.has(keyB))
{
var mixObj = mixes.get(keyA);
if (!mixObj)
{
mixObj = {};
}
mixObj[keyB] = delay;
mixes.set(keyA, mixObj);
}
return this;
},
/**
* Removes a mix between two animations.
*
* Mixing allows you to specify a unique delay between a pairing of animations.
*
* Calling this method lets you remove those pairings. You can either remove
* it between `animA` and `animB`, or if you do not provide the `animB` parameter,
* it will remove all `animA` mixes.
*
* If you wish to update an existing mix instead, call the `addMix` method with the
* new delay.
*
* @method Phaser.Animations.AnimationManager#removeMix
* @since 3.50.0
*
* @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A.
* @param {(string|Phaser.Animations.Animation)} [animB] - The string-based key, or instance of, Animation B. If not given, all mixes for Animation A will be removed.
*
* @return {this} This Animation Manager.
*/
removeMix: function (animA, animB)
{
var mixes = this.mixes;
var keyA = (typeof(animA) === 'string') ? animA : animA.key;
var mixObj = mixes.get(keyA);
if (mixObj)
{
if (animB)
{
var keyB = (typeof(animB) === 'string') ? animB : animB.key;
if (mixObj.hasOwnProperty(keyB))
{
// Remove just this pairing
delete mixObj[keyB];
}
}
else if (!animB)
{
// Remove everything for animA
mixes.delete(keyA);
}
}
return this;
},
/**
* Returns the mix delay between two animations.
*
* If no mix has been set-up, this method will return zero.
*
* If you wish to create, or update, a new mix, call the `addMix` method.
* If you wish to remove a mix, call the `removeMix` method.
*
* @method Phaser.Animations.AnimationManager#getMix
* @since 3.50.0
*
* @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A.
* @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B.
*
* @return {number} The mix duration, or zero if no mix exists.
*/
getMix: function (animA, animB)
{
var mixes = this.mixes;
var keyA = (typeof(animA) === 'string') ? animA : animA.key;
var keyB = (typeof(animB) === 'string') ? animB : animB.key;
var mixObj = mixes.get(keyA);
if (mixObj && mixObj.hasOwnProperty(keyB))
{
return mixObj[keyB];
}
else
{
return 0;
}
},
/**
* Adds an existing Animation to the Animation Manager.
*
@ -153,7 +304,7 @@ var AnimationManager = new Class({
/**
* Checks to see if the given key is already in use within the Animation Manager or not.
*
*
* Animations are global. Keys created in one scene can be used from any other Scene in your game. They are not Scene specific.
*
* @method Phaser.Animations.AnimationManager#exists
@ -168,17 +319,189 @@ var AnimationManager = new Class({
return this.anims.has(key);
},
/**
* Create one, or more animations from a loaded Aseprite JSON file.
*
* Aseprite is a powerful animated sprite editor and pixel art tool.
*
* You can find more details at https://www.aseprite.org/
*
* To export a compatible JSON file in Aseprite, please do the following:
*
* 1. Go to "File - Export Sprite Sheet"
*
* 2. On the **Layout** tab:
* 2a. Set the "Sheet type" to "Packed"
* 2b. Set the "Constraints" to "None"
* 2c. Check the "Merge Duplicates" checkbox
*
* 3. On the **Sprite** tab:
* 3a. Set "Layers" to "Visible layers"
* 3b. Set "Frames" to "All frames", unless you only wish to export a sub-set of tags
*
* 4. On the **Borders** tab:
* 4a. Check the "Trim Sprite" and "Trim Cells" options
* 4b. Ensure "Border Padding", "Spacing" and "Inner Padding" are all > 0 (1 is usually enough)
*
* 5. On the **Output** tab:
* 5a. Check "Output File", give your image a name and make sure you choose "png files" as the file type
* 5b. Check "JSON Data" and give your json file a name
* 5c. The JSON Data type can be either a Hash or Array, Phaser doesn't mind.
* 5d. Make sure "Tags" is checked in the Meta options
* 5e. In the "Item Filename" input box, make sure it says just "{frame}" and nothing more.
*
* 6. Click export
*
* This was tested with Aseprite 1.2.25.
*
* This will export a png and json file which you can load using the Atlas Loader, i.e.:
*
* ```javascript
* function preload ()
* {
* this.load.path = 'assets/animations/aseprite/';
* this.load.atlas('paladin', 'paladin.png', 'paladin.json');
* }
* ```
*
* Once exported, you can call this method from within a Scene with the 'atlas' key:
*
* ```javascript
* this.anims.createFromAseprite('paladin');
* ```
*
* Any animations defined in the JSON will now be available to use in Phaser and you play them
* via their Tag name. For example, if you have an animation called 'War Cry' on your Aseprite timeline,
* you can play it in Phaser using that Tag name:
*
* ```javascript
* this.add.sprite(400, 300).play('War Cry');
* ```
*
* When calling this method you can optionally provide an array of tag names, and only those animations
* will be created. For example:
*
* ```javascript
* this.anims.createFromAseprite('paladin', [ 'step', 'War Cry', 'Magnum Break' ]);
* ```
*
* This will only create the 3 animations defined. Note that the tag names are case-sensitive.
*
* @method Phaser.Animations.AnimationManager#createFromAseprite
* @since 3.50.0
*
* @param {string} key - The key of the loaded Aseprite atlas. It must have been loaded prior to calling this method.
* @param {string[]} [tags] - An array of Tag names. If provided, only animations found in this array will be created.
*
* @return {Phaser.Animations.Animation[]} An array of Animation instances that were successfully created.
*/
createFromAseprite: function (key, tags)
{
var output = [];
var data = this.game.cache.json.get(key);
if (!data)
{
return output;
}
var _this = this;
var meta = GetValue(data, 'meta', null);
var frames = GetValue(data, 'frames', null);
if (meta && frames)
{
var frameTags = GetValue(meta, 'frameTags', []);
frameTags.forEach(function (tag)
{
var animFrames = [];
var name = GetFastValue(tag, 'name', null);
var from = GetFastValue(tag, 'from', 0);
var to = GetFastValue(tag, 'to', 0);
var direction = GetFastValue(tag, 'direction', 'forward');
if (!name)
{
// Skip if no name
return;
}
if (!tags || (tags && tags.indexOf(name) > -1))
{
// Get all the frames for this tag
var tempFrames = [];
var minDuration = Number.MAX_SAFE_INTEGER;
for (var i = from; i <= to; i++)
{
var frameKey = i.toString();
var frame = frames[frameKey];
if (frame)
{
var frameDuration = GetFastValue(frame, 'duration', Number.MAX_SAFE_INTEGER);
if (frameDuration < minDuration)
{
minDuration = frameDuration;
}
tempFrames.push({ frame: frameKey, duration: frameDuration });
}
}
tempFrames.forEach(function (entry)
{
animFrames.push({
key: key,
frame: entry.frame,
duration: (minDuration - entry.duration)
});
});
var totalDuration = (minDuration * animFrames.length);
if (direction === 'reverse')
{
animFrames = animFrames.reverse();
}
// Create the animation
var createConfig = {
key: name,
frames: animFrames,
duration: totalDuration,
yoyo: (direction === 'pingpong')
};
var result = _this.create(createConfig);
if (result)
{
output.push(result);
}
}
});
}
return output;
},
/**
* Creates a new Animation and adds it to the Animation Manager.
*
*
* Animations are global. Once created, you can use them in any Scene in your game. They are not Scene specific.
*
*
* If an invalid key is given this method will return `false`.
*
*
* If you pass the key of an animation that already exists in the Animation Manager, that animation will be returned.
*
*
* A brand new animation is only created if the key is valid and not already in use.
*
*
* If you wish to re-use an existing key, call `AnimationManager.remove` first, then this method.
*
* @method Phaser.Animations.AnimationManager#create
@ -187,7 +510,7 @@ var AnimationManager = new Class({
*
* @param {Phaser.Types.Animations.Animation} config - The configuration settings for the Animation.
*
* @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` is the key is already in use.
* @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` if the key is already in use.
*/
create: function (config)
{
@ -204,7 +527,7 @@ var AnimationManager = new Class({
anim = new Animation(this, key, config);
this.anims.set(key, anim);
this.emit(Events.ADD_ANIMATION, key, anim);
}
}
@ -265,18 +588,18 @@ var AnimationManager = new Class({
* Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object.
*
* Generates objects with string based frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNames}.
*
*
* It's a helper method, designed to make it easier for you to extract all of the frame names from texture atlases.
* If you're working with a sprite sheet, see the `generateFrameNumbers` method instead.
*
*
* Example:
*
*
* If you have a texture atlases loaded called `gems` and it contains 6 frames called `ruby_0001`, `ruby_0002`, and so on,
* then you can call this method using: `this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 })`.
*
*
* The `end` value tells it to look for 6 frames, incrementally numbered, all starting with the prefix `ruby_`. The `zeroPad`
* value tells it how many zeroes pad out the numbers. To create an animation using this method, you can do:
*
*
* ```javascript
* this.anims.create({
* key: 'ruby',
@ -288,7 +611,7 @@ var AnimationManager = new Class({
* })
* });
* ```
*
*
* Please see the animation examples for further details.
*
* @method Phaser.Animations.AnimationManager#generateFrameNames
@ -316,17 +639,11 @@ var AnimationManager = new Class({
return out;
}
var diff = (start < end) ? 1 : -1;
// Adjust because we use i !== end in the for loop
end += diff;
var i;
var frame;
if (!config)
{
// Use every frame in the atlas?
// Use every frame in the atlas
frames = texture.getFrameNames();
for (i = 0; i < frames.length; i++)
@ -334,28 +651,24 @@ var AnimationManager = new Class({
out.push({ key: key, frame: frames[i] });
}
}
else if (Array.isArray(frames))
else
{
// Have they provided their own custom frame sequence array?
if (!frames)
{
frames = NumberArray(start, end);
}
for (i = 0; i < frames.length; i++)
{
frame = prefix + Pad(frames[i], zeroPad, '0', 1) + suffix;
var frame = prefix + Pad(frames[i], zeroPad, '0', 1) + suffix;
if (texture.has(frame))
{
out.push({ key: key, frame: frame });
}
}
}
else
{
for (i = start; i !== end; i += diff)
{
frame = prefix + Pad(i, zeroPad, '0', 1) + suffix;
if (texture.has(frame))
else
{
out.push({ key: key, frame: frame });
console.warn('generateFrameNames: Frame missing: ' + frame + ' from texture: ' + key);
}
}
}
@ -367,7 +680,7 @@ var AnimationManager = new Class({
* Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object.
*
* Generates objects with numbered frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNumbers}.
*
*
* If you're working with a texture atlas, see the `generateFrameNames` method instead.
*
* @method Phaser.Animations.AnimationManager#generateFrameNumbers
@ -380,9 +693,9 @@ var AnimationManager = new Class({
*/
generateFrameNumbers: function (key, config)
{
var startFrame = GetValue(config, 'start', 0);
var endFrame = GetValue(config, 'end', -1);
var firstFrame = GetValue(config, 'first', false);
var start = GetValue(config, 'start', 0);
var end = GetValue(config, 'end', -1);
var first = GetValue(config, 'first', false);
var out = GetValue(config, 'outputArray', []);
var frames = GetValue(config, 'frames', false);
@ -393,43 +706,33 @@ var AnimationManager = new Class({
return out;
}
if (firstFrame && texture.has(firstFrame))
if (first && texture.has(first))
{
out.push({ key: key, frame: firstFrame });
out.push({ key: key, frame: first });
}
var i;
// Have they provided their own custom frame sequence array?
if (Array.isArray(frames))
// No 'frames' array? Then generate one automatically
if (!frames)
{
for (i = 0; i < frames.length; i++)
if (end === -1)
{
if (texture.has(frames[i]))
{
out.push({ key: key, frame: frames[i] });
}
// -1 because of __BASE, which we don't want in our results
// and -1 because frames are zero based
end = texture.frameTotal - 2;
}
frames = NumberArray(start, end);
}
else
for (var i = 0; i < frames.length; i++)
{
// No endFrame then see if we can get it
if (endFrame === -1)
if (texture.has(frames[i]))
{
endFrame = texture.frameTotal;
out.push({ key: key, frame: frames[i] });
}
var diff = (startFrame < endFrame) ? 1 : -1;
// Adjust because we use i !== end in the for loop
endFrame += diff;
for (i = startFrame; i !== endFrame; i += diff)
else
{
if (texture.has(i))
{
out.push({ key: key, frame: i });
}
console.warn('generateFrameNumbers: Frame ' + i + ' missing from texture: ' + key);
}
}
@ -451,34 +754,6 @@ var AnimationManager = new Class({
return this.anims.get(key);
},
/**
* Load an Animation into a Game Object's Animation Component.
*
* @method Phaser.Animations.AnimationManager#load
* @since 3.0.0
*
* @param {Phaser.GameObjects.GameObject} child - The Game Object to load the animation into.
* @param {string} key - The key of the animation to load.
* @param {(string|integer)} [startFrame] - The name of a start frame to set on the loaded animation.
*
* @return {Phaser.GameObjects.GameObject} The Game Object with the animation loaded into it.
*/
load: function (child, key, startFrame)
{
var anim = this.get(key);
if (anim)
{
anim.load(child, startFrame);
}
else
{
console.warn('Missing animation: ' + key);
}
return child;
},
/**
* Pause all animations.
*
@ -506,28 +781,87 @@ var AnimationManager = new Class({
* @method Phaser.Animations.AnimationManager#play
* @since 3.0.0
*
* @param {string} key - The key of the animation to play on the Game Object.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Objects to play the animation on.
* @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component.
*
* @return {this} This Animation Manager.
*/
play: function (key, child)
play: function (key, children)
{
if (!Array.isArray(child))
if (!Array.isArray(children))
{
child = [ child ];
children = [ children ];
}
var anim = this.get(key);
if (!anim)
for (var i = 0; i < children.length; i++)
{
return this;
children[i].anims.play(key);
}
for (var i = 0; i < child.length; i++)
return this;
},
/**
* Takes an array of Game Objects that have an Animation Component and then
* starts the given animation playing on them. The start time of each Game Object
* is offset, incrementally, by the `stagger` amount.
*
* For example, if you pass an array with 4 children and a stagger time of 1000,
* the delays will be:
*
* child 1: 1000ms delay
* child 2: 2000ms delay
* child 3: 3000ms delay
* child 4: 4000ms delay
*
* If you set the `staggerFirst` parameter to `false` they would be:
*
* child 1: 0ms delay
* child 2: 1000ms delay
* child 3: 2000ms delay
* child 4: 3000ms delay
*
* You can also set `stagger` to be a negative value. If it was -1000, the above would be:
*
* child 1: 3000ms delay
* child 2: 2000ms delay
* child 3: 1000ms delay
* child 4: 0ms delay
*
* @method Phaser.Animations.AnimationManager#staggerPlay
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component.
* @param {number} stagger - The amount of time, in milliseconds, to offset each play time by. If a negative value is given, it's applied to the children in reverse order.
* @param {boolean} [staggerFirst=true] -Should the first child be staggered as well?
*
* @return {this} This Animation Manager.
*/
staggerPlay: function (key, children, stagger, staggerFirst)
{
if (stagger === undefined) { stagger = 0; }
if (staggerFirst === undefined) { staggerFirst = true; }
if (!Array.isArray(children))
{
child[i].anims.play(key);
children = [ children ];
}
var len = children.length;
if (!staggerFirst)
{
len--;
}
for (var i = 0; i < children.length; i++)
{
var time = (stagger < 0) ? Math.abs(stagger) * (len - i) : stagger * i;
children[i].anims.playAfterDelay(key, time);
}
return this;
@ -535,7 +869,7 @@ var AnimationManager = new Class({
/**
* Removes an Animation from this Animation Manager, based on the given key.
*
*
* This is a global action. Once an Animation has been removed, no Game Objects
* can carry on using it.
*
@ -556,6 +890,8 @@ var AnimationManager = new Class({
this.emit(Events.REMOVE_ANIMATION, key, anim);
this.anims.delete(key);
this.removeMix(key);
}
return anim;
@ -582,46 +918,6 @@ var AnimationManager = new Class({
return this;
},
/**
* Takes an array of Game Objects that have an Animation Component and then
* starts the given animation playing on them, each one offset by the
* `stagger` amount given to this method.
*
* @method Phaser.Animations.AnimationManager#staggerPlay
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {string} key - The key of the animation to play on the Game Objects.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component.
* @param {number} [stagger=0] - The amount of time, in milliseconds, to offset each play time by.
*
* @return {this} This Animation Manager.
*/
staggerPlay: function (key, children, stagger)
{
if (stagger === undefined) { stagger = 0; }
if (!Array.isArray(children))
{
children = [ children ];
}
var anim = this.get(key);
if (!anim)
{
return this;
}
for (var i = 0; i < children.length; i++)
{
children[i].anims.delayedPlay(stagger * i, key);
}
return this;
},
/**
* Returns the Animation data as JavaScript object based on the given key.
* Or, if not key is defined, it will return the data of all animations as array of objects.
@ -665,6 +961,7 @@ var AnimationManager = new Class({
destroy: function ()
{
this.anims.clear();
this.mixes.clear();
this.textureManager = null;

File diff suppressed because it is too large Load diff

View file

@ -6,17 +6,34 @@
/**
* The Animation Complete Event.
*
* This event is dispatched by an Animation instance when it completes, i.e. finishes playing or is manually stopped.
*
* Be careful with the volume of events this could generate. If a group of Sprites all complete the same
* animation at the same time, this event will invoke its handler for each one of them.
*
* This event is dispatched by a Sprite when an animation playing on it completes playback.
* This happens when the animation gets to the end of its sequence, factoring in any delays
* or repeats it may have to process.
*
* An animation that is set to loop, or repeat forever, will never fire this event, because
* it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP`
* event instead, as this is emitted when the animation is stopped directly.
*
* Listen for it on the Sprite using `sprite.on('animationcomplete', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_COMPLETE
* @since 3.16.1
*
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation completed on.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'complete';
module.exports = 'animationcomplete';

View file

@ -6,16 +6,31 @@
/**
* The Animation Repeat Event.
*
* This event is dispatched when a currently playing animation repeats.
*
* The event is dispatched directly from the Animation object itself. Which means that listeners
* bound to this event will be invoked every time the Animation repeats, for every Game Object that may have it.
*
* This event is dispatched by a Sprite when an animation repeats playing on it.
* This happens if the animation was created, or played, with a `repeat` value specified.
*
* An animation will repeat when it reaches the end of its sequence.
*
* Listen for it on the Sprite using `sprite.on('animationrepeat', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_REPEAT
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that repeated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation was on when it repeated.
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has repeated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'repeat';
module.exports = 'animationrepeat';

View file

@ -6,17 +6,29 @@
/**
* The Animation Restart Event.
*
* This event is dispatched by an Animation instance when it restarts.
*
* Be careful with the volume of events this could generate. If a group of Sprites all restart the same
* animation at the same time, this event will invoke its handler for each one of them.
*
* This event is dispatched by a Sprite when an animation restarts playing on it.
* This only happens when the `Sprite.anims.restart` method is called.
*
* Listen for it on the Sprite using `sprite.on('animationrestart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_RESTART
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that restarted playing.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation restarted with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted playing.
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has restarted.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'restart';
module.exports = 'animationrestart';

View file

@ -6,17 +6,30 @@
/**
* The Animation Start Event.
*
* This event is dispatched by an Animation instance when it starts playing.
*
* Be careful with the volume of events this could generate. If a group of Sprites all play the same
* animation at the same time, this event will invoke its handler for each one of them.
*
* This event is dispatched by a Sprite when an animation starts playing on it.
* This happens when the animation is played, factoring in any delay that may have been specified.
* This event happens after the delay has expired and prior to the first update event.
*
* Listen for it on the Sprite using `sprite.on('animationstart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_START
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that started playing.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation started with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started playing.
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has started.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'start';
module.exports = 'animationstart';

View file

@ -0,0 +1,35 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Stop Event.
*
* This event is dispatched by a Sprite when an animation is stopped on it. An animation
* will only be stopeed if a method such as `Sprite.stop` or `Sprite.anims.stopAfterDelay`
* is called. It can also be emitted if a new animation is started before the current one completes.
*
* Listen for it on the Sprite using `sprite.on('animationstop', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_STOP
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has stopped.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation stopped.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationstop';

View file

@ -0,0 +1,39 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Update Event.
*
* This event is dispatched by a Sprite when an animation playing on it updates. This happens when the animation changes frame.
* An animation will change frame based on the frme rate and other factors like `timeScale` and `delay`. It can also change
* frame when stopped or restarted.
*
* Listen for it on the Sprite using `sprite.on('animationupdate', listener)`
*
* If an animation is playing faster than the game frame-rate can handle, it's entirely possible for it to emit several
* update events in a single game frame, so please be aware of this in your code. The **final** event received that frame
* is the one that is rendered to the game.
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_UPDATE
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationupdate';

View file

@ -1,23 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Complete Event.
*
* This event is dispatched by a Sprite when an animation finishes playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationcomplete', listener)`
*
* This same event is dispatched for all animations. To listen for a specific animation, use the `SPRITE_ANIMATION_KEY_COMPLETE` event.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_COMPLETE
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation completed on.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation completed.
*/
module.exports = 'animationcomplete';

View file

@ -1,22 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Key Complete Event.
*
* This event is dispatched by a Sprite when a specific animation finishes playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationcomplete-key', listener)` where `key` is the key of
* the animation. For example, if you had an animation with the key 'explode' you should listen for `animationcomplete-explode`.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_KEY_COMPLETE
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation completed on.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation completed.
*/
module.exports = 'animationcomplete-';

View file

@ -1,23 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Key Repeat Event.
*
* This event is dispatched by a Sprite when a specific animation repeats playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationrepeat-key', listener)` where `key` is the key of
* the animation. For example, if you had an animation with the key 'explode' you should listen for `animationrepeat-explode`.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_KEY_REPEAT
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that is repeating on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation started with.
* @param {integer} repeatCount - The number of times the Animation has repeated so far.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated playing.
*/
module.exports = 'animationrepeat-';

View file

@ -1,22 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Key Restart Event.
*
* This event is dispatched by a Sprite when a specific animation restarts playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationrestart-key', listener)` where `key` is the key of
* the animation. For example, if you had an animation with the key 'explode' you should listen for `animationrestart-explode`.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_KEY_RESTART
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that was restarted on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation restarted with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted playing.
*/
module.exports = 'animationrestart-';

View file

@ -1,22 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Key Start Event.
*
* This event is dispatched by a Sprite when a specific animation starts playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationstart-key', listener)` where `key` is the key of
* the animation. For example, if you had an animation with the key 'explode' you should listen for `animationstart-explode`.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_KEY_START
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that was started on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation started with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started playing.
*/
module.exports = 'animationstart-';

View file

@ -1,23 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Key Update Event.
*
* This event is dispatched by a Sprite when a specific animation playing on it updates. This happens when the animation changes frame,
* based on the animation frame rate and other factors like `timeScale` and `delay`.
*
* Listen for it on the Sprite using `sprite.on('animationupdate-key', listener)` where `key` is the key of
* the animation. For example, if you had an animation with the key 'explode' you should listen for `animationupdate-explode`.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_KEY_UPDATE
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
*/
module.exports = 'animationupdate-';

View file

@ -1,24 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Repeat Event.
*
* This event is dispatched by a Sprite when an animation repeats playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationrepeat', listener)`
*
* This same event is dispatched for all animations. To listen for a specific animation, use the `SPRITE_ANIMATION_KEY_REPEAT` event.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_REPEAT
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that is repeating on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation started with.
* @param {integer} repeatCount - The number of times the Animation has repeated so far.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated playing.
*/
module.exports = 'animationrepeat';

View file

@ -1,23 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Restart Event.
*
* This event is dispatched by a Sprite when an animation restarts playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationrestart', listener)`
*
* This same event is dispatched for all animations. To listen for a specific animation, use the `SPRITE_ANIMATION_KEY_RESTART` event.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_RESTART
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that was restarted on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation restarted with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted playing.
*/
module.exports = 'animationrestart';

View file

@ -1,23 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Start Event.
*
* This event is dispatched by a Sprite when an animation starts playing on it.
*
* Listen for it on the Sprite using `sprite.on('animationstart', listener)`
*
* This same event is dispatched for all animations. To listen for a specific animation, use the `SPRITE_ANIMATION_KEY_START` event.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_START
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that was started on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame that the Animation started with.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started playing.
*/
module.exports = 'animationstart';

View file

@ -1,24 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sprite Animation Update Event.
*
* This event is dispatched by a Sprite when an animation playing on it updates. This happens when the animation changes frame,
* based on the animation frame rate and other factors like `timeScale` and `delay`.
*
* Listen for it on the Sprite using `sprite.on('animationupdate', listener)`
*
* This same event is dispatched for all animations. To listen for a specific animation, use the `SPRITE_ANIMATION_KEY_UPDATE` event.
*
* @event Phaser.Animations.Events#SPRITE_ANIMATION_UPDATE
* @since 3.16.1
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated on the Sprite.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
*/
module.exports = 'animationupdate';

View file

@ -15,18 +15,10 @@ module.exports = {
ANIMATION_REPEAT: require('./ANIMATION_REPEAT_EVENT'),
ANIMATION_RESTART: require('./ANIMATION_RESTART_EVENT'),
ANIMATION_START: require('./ANIMATION_START_EVENT'),
ANIMATION_STOP: require('./ANIMATION_STOP_EVENT'),
ANIMATION_UPDATE: require('./ANIMATION_UPDATE_EVENT'),
PAUSE_ALL: require('./PAUSE_ALL_EVENT'),
REMOVE_ANIMATION: require('./REMOVE_ANIMATION_EVENT'),
RESUME_ALL: require('./RESUME_ALL_EVENT'),
SPRITE_ANIMATION_COMPLETE: require('./SPRITE_ANIMATION_COMPLETE_EVENT'),
SPRITE_ANIMATION_KEY_COMPLETE: require('./SPRITE_ANIMATION_KEY_COMPLETE_EVENT'),
SPRITE_ANIMATION_KEY_REPEAT: require('./SPRITE_ANIMATION_KEY_REPEAT_EVENT'),
SPRITE_ANIMATION_KEY_RESTART: require('./SPRITE_ANIMATION_KEY_RESTART_EVENT'),
SPRITE_ANIMATION_KEY_START: require('./SPRITE_ANIMATION_KEY_START_EVENT'),
SPRITE_ANIMATION_KEY_UPDATE: require('./SPRITE_ANIMATION_KEY_UPDATE_EVENT'),
SPRITE_ANIMATION_REPEAT: require('./SPRITE_ANIMATION_REPEAT_EVENT'),
SPRITE_ANIMATION_RESTART: require('./SPRITE_ANIMATION_RESTART_EVENT'),
SPRITE_ANIMATION_START: require('./SPRITE_ANIMATION_START_EVENT'),
SPRITE_ANIMATION_UPDATE: require('./SPRITE_ANIMATION_UPDATE_EVENT')
RESUME_ALL: require('./RESUME_ALL_EVENT')
};

View file

@ -13,6 +13,7 @@ module.exports = {
Animation: require('./Animation'),
AnimationFrame: require('./AnimationFrame'),
AnimationManager: require('./AnimationManager'),
AnimationState: require('./AnimationState'),
Events: require('./events')
};

View file

@ -3,7 +3,8 @@
* @since 3.0.0
*
* @property {string} [key] - The key that the animation will be associated with. i.e. sprite.animations.play(key)
* @property {Phaser.Types.Animations.AnimationFrame[]} [frames] - An object containing data used to generate the frames for the animation
* @property {string|Phaser.Types.Animations.AnimationFrame[]} [frames] - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects.
* @property {boolean} [sortFrames=true] - If you provide a string for `frames` you can optionally have the frame names numerically sorted.
* @property {string} [defaultTextureKey=null] - The key of the texture all frames of the animation will use. Can be overridden on a per frame basis.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.

View file

@ -2,8 +2,8 @@
* @typedef {object} Phaser.Types.Animations.AnimationFrame
* @since 3.0.0
*
* @property {string} key - The key that the animation will be associated with. i.e. sprite.animations.play(key)
* @property {(string|number)} frame - The key, or index number, of the frame within the animation.
* @property {string} key - The key of the texture within the Texture Manager to use for this Animation Frame.
* @property {(string|number)} [frame] - The key, or index number, of the frame within the texture to use for this Animation Frame.
* @property {number} [duration=0] - The duration, in ms, of this frame of the animation.
* @property {boolean} [visible] - Should the parent Game Object be visible during this frame of the animation?
*/

View file

@ -0,0 +1,16 @@
/**
* @typedef {object} Phaser.Types.Animations.PlayAnimationConfig
* @since 3.50.0
*
* @property {(string|Phaser.Animations.Animation)} key - The string-based key of the animation to play, or an Animation instance.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.
* @property {integer} [delay] - Delay before starting playback. Value given in milliseconds.
* @property {integer} [repeat] - Number of times to repeat the animation (-1 for infinity)
* @property {integer} [repeatDelay] - Delay before the animation repeats. Value given in milliseconds.
* @property {boolean} [yoyo] - Should the animation yoyo? (reverse back down to the start) before repeating?
* @property {boolean} [showOnStart] - Should sprite.visible = true when the animation starts to play?
* @property {boolean} [hideOnComplete] - Should sprite.visible = false when the animation finishes?
* @property {integer} [startFrame] - The frame of the animation to start playback from.
* @property {number} [timeScale] - The time scale to be applied to playback of this animation.
*/

View file

@ -301,7 +301,7 @@ var Fade = new Class({
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @param {function} getTintFunction - A function that will return the gl safe tint colors.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.

View file

@ -269,7 +269,7 @@ var Flash = new Class({
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @param {function} getTintFunction - A function that will return the gl safe tint colors.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.

View file

@ -20,7 +20,7 @@ var CONST = {
* @type {string}
* @since 3.0.0
*/
VERSION: '3.50.0-beta.1',
VERSION: '3.50.0-beta.4',
BlendModes: require('./renderer/BlendModes'),

View file

@ -10,6 +10,7 @@
module.exports = {
Path: require('./path/Path'),
MoveTo: require('./path/MoveTo'),
CubicBezier: require('./CubicBezierCurve'),
Curve: require('./Curve'),

View file

@ -9,15 +9,16 @@ var Vector2 = require('../../math/Vector2');
/**
* @classdesc
* A MoveTo Curve is a very simple curve consisting of only a single point. Its intended use is to move the ending point in a Path.
* A MoveTo Curve is a very simple curve consisting of only a single point.
* Its intended use is to move the ending point in a Path.
*
* @class MoveTo
* @memberof Phaser.Curves
* @constructor
* @since 3.0.0
*
* @param {number} [x] - `x` pixel coordinate.
* @param {number} [y] - `y` pixel coordinate.
* @param {number} [x=0] - `x` pixel coordinate.
* @param {number} [y=0] - `y` pixel coordinate.
*/
var MoveTo = new Class({
@ -25,8 +26,6 @@ var MoveTo = new Class({
function MoveTo (x, y)
{
// Skip length calcs in paths
/**
* Denotes that this Curve does not influence the bounds, points, and drawing of its parent Path. Must be `false` or some methods in the parent Path will throw errors.
*

View file

@ -7,10 +7,32 @@
var GetColor = require('./GetColor');
/**
* Converts an HSV (hue, saturation and value) color value to RGB.
* Conversion formula from http://en.wikipedia.org/wiki/HSL_color_space.
* RGB space conversion.
*
* @ignore
*
* @param {number} n - The value to convert.
* @param {number} h - The h value.
* @param {number} s - The s value.
* @param {number} v - The v value.
*
* @return {number} The converted value.
*/
function ConvertValue (n, h, s, v)
{
var k = (n + h * 6) % 6;
var min = Math.min(k, 4 - k, 1);
return Math.round(255 * (v - v * s * Math.max(0, min)));
}
/**
* Converts a HSV (hue, saturation and value) color set to RGB.
*
* Conversion formula from https://en.wikipedia.org/wiki/HSL_and_HSV
*
* Assumes HSV values are contained in the set [0, 1].
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @function Phaser.Display.Color.HSVToRGB
* @since 3.0.0
@ -27,51 +49,9 @@ var HSVToRGB = function (h, s, v, out)
if (s === undefined) { s = 1; }
if (v === undefined) { v = 1; }
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = Math.floor((v * (1 - s)) * 255);
var q = Math.floor((v * (1 - f * s)) * 255);
var t = Math.floor((v * (1 - (1 - f) * s)) * 255);
v = Math.floor(v *= 255);
var r = v;
var g = v;
var b = v;
var c = i % 6;
if (c === 0)
{
g = t;
b = p;
}
else if (c === 1)
{
r = q;
b = p;
}
else if (c === 2)
{
r = p;
b = t;
}
else if (c === 3)
{
r = p;
g = q;
}
else if (c === 4)
{
r = t;
g = p;
}
else if (c === 5)
{
g = p;
b = q;
}
var r = ConvertValue(5, h, s, v);
var g = ConvertValue(3, h, s, v);
var b = ConvertValue(1, h, s, v);
if (!out)
{

View file

@ -9,16 +9,16 @@ var Class = require('../../utils/Class');
/**
* @classdesc
* A BaseShader is a small resource class that contains the data required for a WebGL Shader to be created.
*
*
* It contains the raw source code to the fragment and vertex shader, as well as an object that defines
* the uniforms the shader requires, if any.
*
*
* BaseShaders are stored in the Shader Cache, available in a Scene via `this.cache.shaders` and are referenced
* by a unique key-based string. Retrieve them via `this.cache.shaders.get(key)`.
*
*
* BaseShaders are created automatically by the GLSL File Loader when loading an external shader resource.
* They can also be created at runtime, allowing you to use dynamically generated shader source code.
*
*
* Default fragment and vertex source is used if not provided in the constructor, setting-up a basic shader,
* suitable for debug rendering.
*
@ -66,10 +66,12 @@ var BaseShader = new Class({
'attribute vec2 inPosition;',
'varying vec2 fragCoord;',
'varying vec2 outTexCoord;',
'void main () {',
'gl_Position = uProjectionMatrix * uViewMatrix * vec4(inPosition, 1.0, 1.0);',
'fragCoord = vec2(inPosition.x, uResolution.y - inPosition.y);',
' gl_Position = uProjectionMatrix * uViewMatrix * vec4(inPosition, 1.0, 1.0);',
' fragCoord = vec2(inPosition.x, uResolution.y - inPosition.y);',
' outTexCoord = vec2(inPosition.x / uResolution.x, fragCoord.y / uResolution.y);',
'}'
].join('\n');
}

View file

@ -12,6 +12,7 @@ var Dom = {
AddToDOM: require('./AddToDOM'),
DOMContentLoaded: require('./DOMContentLoaded'),
GetInnerHeight: require('./GetInnerHeight'),
GetScreenOrientation: require('./GetScreenOrientation'),
GetTarget: require('./GetTarget'),
ParseXML: require('./ParseXML'),

View file

@ -48,32 +48,40 @@ var BuildGameObjectAnimation = function (sprite, config)
var anims = sprite.anims;
var key = GetAdvancedValue(animConfig, 'key', undefined);
var startFrame = GetAdvancedValue(animConfig, 'startFrame', undefined);
var delay = GetAdvancedValue(animConfig, 'delay', 0);
var repeat = GetAdvancedValue(animConfig, 'repeat', 0);
var repeatDelay = GetAdvancedValue(animConfig, 'repeatDelay', 0);
var yoyo = GetAdvancedValue(animConfig, 'yoyo', false);
var play = GetAdvancedValue(animConfig, 'play', false);
var delayedPlay = GetAdvancedValue(animConfig, 'delayedPlay', 0);
anims.setDelay(delay);
anims.setRepeat(repeat);
anims.setRepeatDelay(repeatDelay);
anims.setYoyo(yoyo);
if (play)
if (key)
{
anims.play(key, startFrame);
}
else if (delayedPlay > 0)
{
anims.delayedPlay(delayedPlay, key, startFrame);
}
else
{
anims.load(key);
var startFrame = GetAdvancedValue(animConfig, 'startFrame', undefined);
var delay = GetAdvancedValue(animConfig, 'delay', 0);
var repeat = GetAdvancedValue(animConfig, 'repeat', 0);
var repeatDelay = GetAdvancedValue(animConfig, 'repeatDelay', 0);
var yoyo = GetAdvancedValue(animConfig, 'yoyo', false);
var play = GetAdvancedValue(animConfig, 'play', false);
var delayedPlay = GetAdvancedValue(animConfig, 'delayedPlay', 0);
var playConfig = {
key: key,
delay: delay,
repeat: repeat,
repeatDelay: repeatDelay,
yoyo: yoyo,
startFrame: startFrame
};
if (play)
{
anims.play(playConfig);
}
else if (delayedPlay > 0)
{
anims.playAfterDelay(playConfig, delayedPlay);
}
else
{
anims.load(playConfig);
}
}
}

View file

@ -7,6 +7,7 @@
var Class = require('../utils/Class');
var List = require('../structs/List');
var PluginCache = require('../plugins/PluginCache');
var GameObjectEvents = require('./events');
var SceneEvents = require('../scene/events');
var StableSort = require('../utils/array/StableSort');
@ -64,8 +65,21 @@ var DisplayList = new Class({
*/
this.systems = scene.sys;
scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
scene.sys.events.on(SceneEvents.START, this.start, this);
/**
* The Scene's Event Emitter.
*
* @name Phaser.GameObjects.DisplayList#events
* @type {Phaser.Events.EventEmitter}
* @since 3.50.0
*/
this.events = scene.sys.events;
// Set the List callbacks
this.addCallback = this.addChildCallback;
this.removeCallback = this.removeChildCallback;
this.events.once(SceneEvents.BOOT, this.boot, this);
this.events.on(SceneEvents.START, this.start, this);
},
/**
@ -78,7 +92,43 @@ var DisplayList = new Class({
*/
boot: function ()
{
this.systems.events.once(SceneEvents.DESTROY, this.destroy, this);
this.events.once(SceneEvents.DESTROY, this.destroy, this);
},
/**
* Internal method called from `List.addCallback`.
*
* @method Phaser.GameObjects.DisplayList#addChildCallback
* @private
* @fires Phaser.Scenes.Events#ADDED_TO_SCENE
* @fires Phaser.GameObjects.Events#ADDED_TO_SCENE
* @since 3.50.0
*
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the list.
*/
addChildCallback: function (gameObject)
{
gameObject.emit(GameObjectEvents.ADDED_TO_SCENE, gameObject, this.scene);
this.events.emit(SceneEvents.ADDED_TO_SCENE, gameObject, this.scene);
},
/**
* Internal method called from `List.removeCallback`.
*
* @method Phaser.GameObjects.DisplayList#removeChildCallback
* @private
* @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE
* @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE
* @since 3.50.0
*
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the list.
*/
removeChildCallback: function (gameObject)
{
gameObject.emit(GameObjectEvents.REMOVED_FROM_SCENE, gameObject, this.scene);
this.events.emit(SceneEvents.REMOVED_FROM_SCENE, gameObject, this.scene);
},
/**
@ -92,7 +142,7 @@ var DisplayList = new Class({
*/
start: function ()
{
this.systems.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -116,7 +166,7 @@ var DisplayList = new Class({
{
if (this.sortChildrenFlag)
{
StableSort.inplace(this.list, this.sortByDepth);
StableSort(this.list, this.sortByDepth);
this.sortChildrenFlag = false;
}
@ -162,16 +212,18 @@ var DisplayList = new Class({
*/
shutdown: function ()
{
var i = this.list.length;
var list = this.list;
var i = list.length;
while (i--)
{
this.list[i].destroy(true);
list[i].destroy(true);
}
this.list.length = 0;
list.length = 0;
this.systems.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -186,10 +238,11 @@ var DisplayList = new Class({
{
this.shutdown();
this.scene.sys.events.off(SceneEvents.START, this.start, this);
this.events.off(SceneEvents.START, this.start, this);
this.scene = null;
this.systems = null;
this.events = null;
}
});

View file

@ -58,9 +58,9 @@ var GameObject = new Class({
/**
* The current state of this Game Object.
*
*
* Phaser itself will never modify this value, although plugins may do so.
*
*
* Use this property to track the state of a Game Object during its lifetime. For example, it could change from
* a state of 'moving', to 'attacking', to 'dead'. The state value should be an integer (ideally mapped to a constant
* in your game code), or a string. These are recommended to keep it light and simple, with fast comparisons.
@ -230,9 +230,9 @@ var GameObject = new Class({
/**
* Sets the current state of this Game Object.
*
*
* Phaser itself will never modify the State of a Game Object, although plugins may do so.
*
*
* For example, a Game Object could change from a state of 'moving', to 'attacking', to 'dead'.
* The state value should typically be an integer (ideally mapped to a constant
* in your game code), but could also be a string. It is recommended to keep it light and simple.
@ -337,7 +337,7 @@ var GameObject = new Class({
* before setting the value.
*
* If the key doesn't already exist in the Data Manager then it is created.
*
*
* When the value is first set, a `setdata` event is emitted from this Game Object.
*
* @method Phaser.GameObjects.GameObject#incData
@ -367,7 +367,7 @@ var GameObject = new Class({
* before setting the value.
*
* If the key doesn't already exist in the Data Manager then it is created.
*
*
* When the value is first set, a `setdata` event is emitted from this Game Object.
*
* @method Phaser.GameObjects.GameObject#toggleData
@ -505,7 +505,7 @@ var GameObject = new Class({
* If you wish to only temporarily stop an object from receiving input then use
* `disableInteractive` instead, as that toggles the interactive state, where-as
* this erases it completely.
*
*
* If you wish to resize a hit area, don't remove and then set it as being
* interactive. Instead, access the hitarea object directly and resize the shape
* being used. I.e.: `sprite.input.hitArea.setSize(width, height)` (assuming the
@ -525,6 +525,36 @@ var GameObject = new Class({
return this;
},
/**
* This callback is invoked when this Game Object is added to a Scene.
*
* Can be overriden by custom Game Objects, but be aware of some Game Objects that
* will use this, such as Sprites, to add themselves into the Update List.
*
* You can also listen for the `ADDED_TO_SCENE` event from this Game Object.
*
* @method Phaser.GameObjects.GameObject#addedToScene
* @since 3.50.0
*/
addedToScene: function ()
{
},
/**
* This callback is invoked when this Game Object is removed from a Scene.
*
* Can be overriden by custom Game Objects, but be aware of some Game Objects that
* will use this, such as Sprites, to removed themselves from the Update List.
*
* You can also listen for the `REMOVED_FROM_SCENE` event from this Game Object.
*
* @method Phaser.GameObjects.GameObject#removedFromScene
* @since 3.50.0
*/
removedFromScene: function ()
{
},
/**
* To be overridden by custom GameObjects. Allows base objects to be used in a Pool.
*
@ -651,7 +681,6 @@ var GameObject = new Class({
if (!fromScene)
{
sys.displayList.remove(this);
sys.updateList.remove(this);
}
if (this.input)

View file

@ -50,6 +50,16 @@ var GameObjectCreator = new Class({
*/
this.systems = scene.sys;
/**
* A reference to the Scene Event Emitter.
*
* @name Phaser.GameObjects.GameObjectCreator#events
* @type {Phaser.Events.EventEmitter}
* @protected
* @since 3.50.0
*/
this.events = scene.sys.events;
/**
* A reference to the Scene Display List.
*
@ -70,8 +80,8 @@ var GameObjectCreator = new Class({
*/
this.updateList;
scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
scene.sys.events.on(SceneEvents.START, this.start, this);
this.events.once(SceneEvents.BOOT, this.boot, this);
this.events.on(SceneEvents.START, this.start, this);
},
/**
@ -87,7 +97,7 @@ var GameObjectCreator = new Class({
this.displayList = this.systems.displayList;
this.updateList = this.systems.updateList;
this.systems.events.once(SceneEvents.DESTROY, this.destroy, this);
this.events.once(SceneEvents.DESTROY, this.destroy, this);
},
/**
@ -101,7 +111,7 @@ var GameObjectCreator = new Class({
*/
start: function ()
{
this.systems.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -114,7 +124,7 @@ var GameObjectCreator = new Class({
*/
shutdown: function ()
{
this.systems.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -129,10 +139,12 @@ var GameObjectCreator = new Class({
{
this.shutdown();
this.scene.sys.events.off(SceneEvents.START, this.start, this);
this.events.off(SceneEvents.START, this.start, this);
this.scene = null;
this.systems = null;
this.events = null;
this.displayList = null;
this.updateList = null;
}

View file

@ -49,6 +49,16 @@ var GameObjectFactory = new Class({
*/
this.systems = scene.sys;
/**
* A reference to the Scene Event Emitter.
*
* @name Phaser.GameObjects.GameObjectFactory#events
* @type {Phaser.Events.EventEmitter}
* @protected
* @since 3.50.0
*/
this.events = scene.sys.events;
/**
* A reference to the Scene Display List.
*
@ -69,8 +79,8 @@ var GameObjectFactory = new Class({
*/
this.updateList;
scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
scene.sys.events.on(SceneEvents.START, this.start, this);
this.events.once(SceneEvents.BOOT, this.boot, this);
this.events.on(SceneEvents.START, this.start, this);
},
/**
@ -86,7 +96,7 @@ var GameObjectFactory = new Class({
this.displayList = this.systems.displayList;
this.updateList = this.systems.updateList;
this.systems.events.once(SceneEvents.DESTROY, this.destroy, this);
this.events.once(SceneEvents.DESTROY, this.destroy, this);
},
/**
@ -100,7 +110,7 @@ var GameObjectFactory = new Class({
*/
start: function ()
{
this.systems.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -143,7 +153,7 @@ var GameObjectFactory = new Class({
*/
shutdown: function ()
{
this.systems.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
},
/**
@ -158,10 +168,11 @@ var GameObjectFactory = new Class({
{
this.shutdown();
this.scene.sys.events.off(SceneEvents.START, this.start, this);
this.events.off(SceneEvents.START, this.start, this);
this.scene = null;
this.systems = null;
this.events = null;
this.displayList = null;
this.updateList = null;

View file

@ -35,6 +35,9 @@ var UpdateList = new Class({
{
ProcessQueue.call(this);
// No duplicates in this list
this.checkQueue = true;
/**
* The Scene that the Update List belongs to.
*
@ -157,7 +160,7 @@ var UpdateList = new Class({
/**
* The Scene that owns this plugin is shutting down.
*
*
* We need to kill and reset all internal properties as well as stop listening to Scene events.
*
* @method Phaser.GameObjects.UpdateList#shutdown
@ -203,7 +206,7 @@ var UpdateList = new Class({
/**
* The Scene that owns this plugin is being destroyed.
*
*
* We need to shutdown and then kill off all external references.
*
* @method Phaser.GameObjects.UpdateList#destroy
@ -221,7 +224,7 @@ var UpdateList = new Class({
/**
* Adds a new item to the Update List.
*
*
* The item is added to the pending list and made active in the next update.
*
* @method Phaser.GameObjects.UpdateList#add
@ -234,7 +237,7 @@ var UpdateList = new Class({
/**
* Removes an item from the Update List.
*
*
* The item is added to the pending destroy and fully removed in the next update.
*
* @method Phaser.GameObjects.UpdateList#remove
@ -247,7 +250,7 @@ var UpdateList = new Class({
/**
* Removes all active items from this Update List.
*
*
* All the items are marked as 'pending destroy' and fully removed in the next update.
*
* @method Phaser.GameObjects.UpdateList#removeAll
@ -258,7 +261,7 @@ var UpdateList = new Class({
/**
* Update this queue. First it will process any items awaiting destruction, and remove them.
*
*
* Then it will check to see if there are any items pending insertion, and move them to an
* active state. Finally, it will return a list of active items for further processing.
*
@ -270,7 +273,7 @@ var UpdateList = new Class({
/**
* Returns the current list of active items.
*
*
* This method returns a reference to the active list array, not a copy of it.
* Therefore, be careful to not modify this array outside of the ProcessQueue.
*

View file

@ -11,10 +11,10 @@ var Render = require('./DynamicBitmapTextRender');
/**
* @classdesc
* BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure.
*
*
* During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to
* match the font structure.
*
*
* Dynamic Bitmap Text objects are different from Static Bitmap Text in that they invoke a callback for each
* letter being rendered during the render pass. This callback allows you to manipulate the properties of
* each letter being rendered, such as its position, scale or tint, allowing you to create interesting effects
@ -29,12 +29,12 @@ var Render = require('./DynamicBitmapTextRender');
*
* To create a BitmapText data files you need a 3rd party app such as:
*
* BMFont (Windows, free): http://www.angelcode.com/products/bmfont/
* Glyph Designer (OS X, commercial): http://www.71squared.com/en/glyphdesigner
* Littera (Web-based, free): http://kvazars.com/littera/
* BMFont (Windows, free): {@link http://www.angelcode.com/products/bmfont/|http://www.angelcode.com/products/bmfont/}
* Glyph Designer (OS X, commercial): {@link http://www.71squared.com/en/glyphdesigner|http://www.71squared.com/en/glyphdesigner}
* Littera (Web-based, free): {@link http://kvazars.com/littera/|http://kvazars.com/littera/}
*
* For most use cases it is recommended to use XML. If you wish to use JSON, the formatting should be equal to the result of
* converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: http://codebeautify.org/xmltojson
* converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: {@link http://codebeautify.org/xmltojson|http://codebeautify.org/xmltojson}
*
* @class DynamicBitmapText
* @extends Phaser.GameObjects.BitmapText
@ -119,7 +119,7 @@ var DynamicBitmapText = new Class({
* The data object that is populated during rendering, then passed to the displayCallback.
* You should modify this object then return it back from the callback. It's updated values
* will be used to render the specific glyph.
*
*
* Please note that if you need a reference to this object locally in your game code then you
* should shallow copy it, as it's updated and re-used for every glyph in the text.
*

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more