├── analysis_options.yaml ├── example ├── coin │ ├── spine │ │ ├── coin.png │ │ └── coin.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── hero │ ├── spine │ │ ├── hero.png │ │ └── hero.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── tank │ ├── spine │ │ ├── tank.png │ │ └── tank.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── vine │ ├── spine │ │ ├── vine.png │ │ └── vine.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── raptor │ ├── atlas1 │ │ └── raptor.png │ ├── atlas2 │ │ └── raptor.png │ ├── atlas3 │ │ └── raptor.png │ ├── example.html │ ├── example.css │ └── example.dart ├── goblins │ ├── spine │ │ └── goblins.png │ ├── example.html │ ├── example.css │ └── example.dart ├── powerup │ ├── spine │ │ ├── powerup-pro.png │ │ └── powerup-pro.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── spineboy │ ├── spine │ │ └── spineboy.png │ ├── example.html │ ├── example.css │ └── example.dart ├── texture_atlas │ ├── spine │ │ ├── hero.png │ │ ├── goblins.png │ │ ├── raptor.png │ │ ├── speedy.png │ │ ├── spineboy.png │ │ ├── hero.atlas │ │ └── speedy.atlas │ ├── atlas │ │ ├── combined.png │ │ └── combined.json │ ├── example.html │ ├── example.css │ └── example.dart ├── stretchyman │ ├── spine │ │ ├── stretchyman.png │ │ └── stretchyman.atlas │ ├── example.html │ ├── example.css │ └── example.dart ├── encode_png.bat └── README.MD ├── .gitignore ├── .travis.yml ├── AUTHORS.md ├── pubspec.yaml ├── lib ├── src │ ├── stagexl │ │ ├── skeleton_animation.dart │ │ ├── skeleton_clipping.dart │ │ └── texture_atlas_attachment_loader.dart │ ├── math_util.dart │ ├── animation │ │ ├── mix_direction.dart │ │ ├── mix_pose.dart │ │ ├── timeline.dart │ │ ├── timeline_type.dart │ │ ├── animation_state_data.dart │ │ ├── track_entry_event.dart │ │ ├── event_timeline.dart │ │ ├── attachment_timeline.dart │ │ ├── path_constraint_spacing_timeline.dart │ │ ├── draw_order_timeline.dart │ │ ├── shear_timeline.dart │ │ ├── animation.dart │ │ ├── rotate_timeline.dart │ │ ├── path_constraint_position_timeline.dart │ │ ├── scale_timeline.dart │ │ ├── translate_timeline.dart │ │ ├── curve_timeline.dart │ │ └── ik_constraint_timeline.dart │ ├── position_mode.dart │ ├── rotate_mode.dart │ ├── updatable.dart │ ├── constraint.dart │ ├── transform_mode.dart │ ├── attachments │ │ ├── attachment_type.dart │ │ ├── bounding_box_attachment.dart │ │ ├── path_attachment.dart │ │ ├── clipping_attachment.dart │ │ ├── attachment.dart │ │ ├── render_attachment.dart │ │ ├── point_attachment.dart │ │ ├── attachment_loader.dart │ │ ├── mesh_attachment.dart │ │ └── region_attachment.dart │ ├── event_data.dart │ ├── spine_event.dart │ ├── spacing_mode.dart │ ├── ik_constraint_data.dart │ ├── slot_data.dart │ ├── bone_data.dart │ ├── path_constraint_data.dart │ ├── transform_constraint_data.dart │ ├── slot.dart │ ├── skin.dart │ └── spine_color.dart └── stagexl_spine.dart ├── LICENSE.md ├── CHANGELOG.md └── README.md /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:pedantic/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /example/coin/spine/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/coin/spine/coin.png -------------------------------------------------------------------------------- /example/hero/spine/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/hero/spine/hero.png -------------------------------------------------------------------------------- /example/tank/spine/tank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/tank/spine/tank.png -------------------------------------------------------------------------------- /example/vine/spine/vine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/vine/spine/vine.png -------------------------------------------------------------------------------- /example/raptor/atlas1/raptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/raptor/atlas1/raptor.png -------------------------------------------------------------------------------- /example/raptor/atlas2/raptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/raptor/atlas2/raptor.png -------------------------------------------------------------------------------- /example/raptor/atlas3/raptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/raptor/atlas3/raptor.png -------------------------------------------------------------------------------- /example/goblins/spine/goblins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/goblins/spine/goblins.png -------------------------------------------------------------------------------- /example/powerup/spine/powerup-pro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/powerup/spine/powerup-pro.png -------------------------------------------------------------------------------- /example/spineboy/spine/spineboy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/spineboy/spine/spineboy.png -------------------------------------------------------------------------------- /example/texture_atlas/spine/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/spine/hero.png -------------------------------------------------------------------------------- /example/texture_atlas/spine/goblins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/spine/goblins.png -------------------------------------------------------------------------------- /example/texture_atlas/spine/raptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/spine/raptor.png -------------------------------------------------------------------------------- /example/texture_atlas/spine/speedy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/spine/speedy.png -------------------------------------------------------------------------------- /example/stretchyman/spine/stretchyman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/stretchyman/spine/stretchyman.png -------------------------------------------------------------------------------- /example/texture_atlas/atlas/combined.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/atlas/combined.png -------------------------------------------------------------------------------- /example/texture_atlas/spine/spineboy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp74/StageXL_Spine/HEAD/example/texture_atlas/spine/spineboy.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .buildlog 2 | .DS_Store 3 | .idea 4 | .packages 5 | .pub/ 6 | .dart_tool/ 7 | build/ 8 | packages 9 | pubspec.lock 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # https://docs.travis-ci.com/user/languages/dart 2 | 3 | language: dart 4 | 5 | dart: 6 | - dev 7 | 8 | dart_task: 9 | - dartanalyzer: --fatal-warnings lib/stagexl_spine.dart 10 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Below is a list of people and organizations who have contributed to StageXL_Spine. 2 | 3 | In alphabetical order: 4 | 5 | Bernhard Pichler 6 | Nils Döhring 7 | -------------------------------------------------------------------------------- /example/vine/spine/vine.atlas: -------------------------------------------------------------------------------- 1 | 2 | vine.png 3 | size: 72,966 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | vine 8 | rotate: false 9 | xy: 2, 2 10 | size: 68, 962 11 | orig: 68, 962 12 | offset: 0, 0 13 | index: -1 14 | -------------------------------------------------------------------------------- /example/encode_png.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | call :treeProcess 4 | goto :eof 5 | 6 | :treeProcess 7 | 8 | FOR %%f IN (*.png) DO C:\Tools\libwebp\bin\cwebp.exe "%%f" -m 6 -q 100 -o "%%~nf.webp" 9 | 10 | for /D %%d in (*) do ( 11 | cd %%d 12 | call :treeProcess 13 | cd .. 14 | ) 15 | 16 | exit /b -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: stagexl_spine 2 | version: 0.10.2 3 | author: Bernhard Pichler 4 | description: The Spine runtime for the StageXL library. 5 | homepage: https://github.com/bp74/StageXL_Spine 6 | 7 | environment: 8 | sdk: '>=2.9.0 <3.0.0' 9 | 10 | dependencies: 11 | stagexl: '>=1.4.6 <2.0.0' 12 | 13 | dev_dependencies: 14 | pedantic: any 15 | build_test: any 16 | build_runner: any 17 | build_web_compilers: any 18 | -------------------------------------------------------------------------------- /example/coin/spine/coin.atlas: -------------------------------------------------------------------------------- 1 | 2 | coin.png 3 | size: 592,247 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | coin 8 | rotate: false 9 | xy: 2, 2 10 | size: 257, 243 11 | orig: 259, 245 12 | offset: 1, 1 13 | index: -1 14 | coin-invert 15 | rotate: false 16 | xy: 261, 2 17 | size: 257, 243 18 | orig: 259, 245 19 | offset: 1, 1 20 | index: -1 21 | shine 22 | rotate: false 23 | xy: 520, 2 24 | size: 70, 243 25 | orig: 72, 245 26 | offset: 1, 1 27 | index: -1 28 | -------------------------------------------------------------------------------- /example/coin/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/hero/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/powerup/spine/powerup-pro.atlas: -------------------------------------------------------------------------------- 1 | 2 | powerup-pro.png 3 | size: 353,141 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | star 8 | rotate: true 9 | xy: 279, 63 10 | size: 76, 72 11 | orig: 76, 72 12 | offset: 0, 0 13 | index: -1 14 | token 15 | rotate: false 16 | xy: 154, 17 17 | size: 123, 122 18 | orig: 123, 122 19 | offset: 0, 0 20 | index: -1 21 | wing 22 | rotate: true 23 | xy: 2, 2 24 | size: 137, 150 25 | orig: 137, 150 26 | offset: 0, 0 27 | index: -1 28 | -------------------------------------------------------------------------------- /example/tank/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/vine/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/goblins/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/powerup/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/raptor/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/spineboy/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/stretchyman/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/texture_atlas/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spine Example 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/README.MD: -------------------------------------------------------------------------------- 1 | http://www.stagexl.org/show/spine/coin/example.html 2 | http://www.stagexl.org/show/spine/goblins/example.html 3 | http://www.stagexl.org/show/spine/hero/example.html 4 | http://www.stagexl.org/show/spine/powerup/example.html 5 | http://www.stagexl.org/show/spine/raptor/example.html 6 | http://www.stagexl.org/show/spine/spineboy/example.html 7 | http://www.stagexl.org/show/spine/stretchyman/example.html 8 | http://www.stagexl.org/show/spine/tank/example.html 9 | http://www.stagexl.org/show/spine/texture-atlas/example.html 10 | http://www.stagexl.org/show/spine/vine/example.html 11 | -------------------------------------------------------------------------------- /lib/src/stagexl/skeleton_animation.dart: -------------------------------------------------------------------------------- 1 | part of stagexl_spine; 2 | 3 | class SkeletonAnimation extends SkeletonDisplayObject implements Animatable { 4 | final AnimationState state; 5 | double timeScale = 1.0; 6 | 7 | SkeletonAnimation(SkeletonData skeletonData, [AnimationStateData stateData]) 8 | : state = AnimationState(stateData ?? AnimationStateData(skeletonData)), 9 | super(skeletonData); 10 | 11 | @override 12 | bool advanceTime(num time) { 13 | double timeScaled = time * timeScale; 14 | skeleton.update(timeScaled); 15 | state.update(timeScaled); 16 | state.apply(skeleton); 17 | skeleton.updateWorldTransform(); 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/math_util.dart: -------------------------------------------------------------------------------- 1 | part of stagexl_spine; 2 | 3 | /// multiplier for degrees to radians conversion 4 | double _deg2rad = math.pi / 180.0; 5 | 6 | /// multiplier for radians to degrees conversion 7 | double _rad2deg = 180.0 / math.pi; 8 | 9 | /// calculate cos based on degrees 10 | double _cosDeg(double deg) => math.cos(_deg2rad * deg); 11 | 12 | /// calculate sin based on degrees 13 | double _sinDeg(double deg) => math.sin(_deg2rad * deg); 14 | 15 | /// convert radians to degrees 16 | double _toDeg(double rad) => _rad2deg * rad; 17 | 18 | /// convert degrees to radians 19 | double _toRad(double deg) => _deg2rad * deg; 20 | 21 | /// Wrap within -180 degrees and 180 degrees 22 | double _wrapRotation(double deg) => (180.0 + deg) % 360.0 - 180.0; 23 | -------------------------------------------------------------------------------- /example/stretchyman/spine/stretchyman.atlas: -------------------------------------------------------------------------------- 1 | 2 | stretchyman.png 3 | size: 303,548 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | back-arm 8 | rotate: false 9 | xy: 235, 350 10 | size: 66, 196 11 | orig: 72, 202 12 | offset: 3, 3 13 | index: -1 14 | back-leg 15 | rotate: false 16 | xy: 139, 233 17 | size: 94, 313 18 | orig: 100, 318 19 | offset: 3, 3 20 | index: -1 21 | body 22 | rotate: false 23 | xy: 2, 100 24 | size: 135, 446 25 | orig: 141, 452 26 | offset: 3, 3 27 | index: -1 28 | front-arm 29 | rotate: false 30 | xy: 139, 18 31 | size: 139, 213 32 | orig: 145, 221 33 | offset: 3, 4 34 | index: -1 35 | head 36 | rotate: false 37 | xy: 2, 2 38 | size: 80, 96 39 | orig: 87, 102 40 | offset: 4, 3 41 | index: -1 42 | -------------------------------------------------------------------------------- /lib/src/stagexl/skeleton_clipping.dart: -------------------------------------------------------------------------------- 1 | part of stagexl_spine; 2 | 3 | class SkeletonClipping implements RenderMask { 4 | final Graphics _graphics = Graphics(); 5 | final _SkeletonClippingCommand _command = _SkeletonClippingCommand(); 6 | 7 | @override 8 | bool relativeToParent = false; 9 | @override 10 | bool border = false; 11 | @override 12 | int borderWidth = 1; 13 | @override 14 | int borderColor = 0xFFFF00FF; 15 | 16 | SkeletonClipping() { 17 | _graphics.addCommand(_command); 18 | _graphics.fillColor(Color.Magenta); 19 | } 20 | 21 | set vertices(Float32List vertices) { 22 | _command.vertices = vertices; 23 | _command.invalidate(); 24 | } 25 | 26 | @override 27 | void renderMask(RenderState renderState) { 28 | _graphics.renderMask(renderState); 29 | } 30 | } 31 | 32 | //----------------------------------------------------------------------------- 33 | 34 | class _SkeletonClippingCommand extends GraphicsCommand { 35 | Float32List vertices = Float32List(0); 36 | 37 | @override 38 | void updateContext(GraphicsContext context) { 39 | for (int i = 0; i < vertices.length - 1; i += 2) { 40 | context.lineTo(vertices[i], vertices[i + 1]); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/coin/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/hero/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/raptor/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/tank/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/vine/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/goblins/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/powerup/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/spineboy/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/stretchyman/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /example/texture_atlas/example.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | /* stage-full-window */ 16 | body.stage-full-window { margin: 0; padding: 0; overflow: hidden; } 17 | canvas.stage-full-window { width: 100%; height: 100%; position:fixed; } 18 | 19 | /* stage-fixed-size */ 20 | canvas.stage-fixed-size { width: 800px; height: 600px; border: 1px dotted black; } 21 | 22 | /* stage-full-screen */ 23 | /* https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#:fullscreen-pseudo-class */ 24 | canvas.stage-full-screen:-webkit-full-screen { 25 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 26 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 27 | } 28 | 29 | canvas.stage-full-screen:-moz-full-screen { 30 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 31 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 32 | } 33 | 34 | canvas.stage-full-screen:fullscreen { 35 | position:fixed; top:0; right:0; bottom:0; left:0; margin:0; 36 | box-sizing:border-box; width:100%; height:100%; object-fit:contain; 37 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### StageXL_Spine: Simplified BSD License 2 | 3 | Copyright (c) 2014, Bernhard Pichler 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /lib/src/stagexl/texture_atlas_attachment_loader.dart: -------------------------------------------------------------------------------- 1 | part of stagexl_spine; 2 | 3 | class TextureAtlasAttachmentLoader implements AttachmentLoader { 4 | final TextureAtlas textureAtlas; 5 | final String namePrefix; 6 | 7 | TextureAtlasAttachmentLoader(this.textureAtlas, [this.namePrefix = ""]) { 8 | if (textureAtlas == null) { 9 | throw ArgumentError("textureAtlas cannot be null."); 10 | } 11 | } 12 | 13 | @override 14 | RegionAttachment newRegionAttachment(Skin skin, String name, String path) { 15 | var bitmapData = textureAtlas.getBitmapData(namePrefix + path); 16 | return RegionAttachment(name, path, bitmapData); 17 | } 18 | 19 | @override 20 | MeshAttachment newMeshAttachment(Skin skin, String name, String path) { 21 | var bitmapData = textureAtlas.getBitmapData(namePrefix + path); 22 | return MeshAttachment(name, path, bitmapData); 23 | } 24 | 25 | @override 26 | BoundingBoxAttachment newBoundingBoxAttachment(Skin skin, String name) { 27 | return BoundingBoxAttachment(name); 28 | } 29 | 30 | @override 31 | PathAttachment newPathAttachment(Skin skin, String name) { 32 | return PathAttachment(name); 33 | } 34 | 35 | @override 36 | PointAttachment newPointAttachment(Skin skin, String name) { 37 | return PointAttachment(name); 38 | } 39 | 40 | @override 41 | ClippingAttachment newClippingAttachment(Skin skin, String name) { 42 | return ClippingAttachment(name); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/coin/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 600, height: 600); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "raptor" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var format = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("coin", "spine/coin.json"); 24 | resourceManager.addTextureAtlas("coin", "spine/coin.atlas", format); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("coin"); 30 | var textureAtlas = resourceManager.getTextureAtlas("coin"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 300; 40 | skeletonAnimation.y = 600; 41 | skeletonAnimation.state.setAnimationByName(0, "rotate", true); 42 | 43 | stage.addChild(skeletonAnimation); 44 | stage.juggler.add(skeletonAnimation); 45 | } 46 | -------------------------------------------------------------------------------- /example/texture_atlas/atlas/combined.json: -------------------------------------------------------------------------------- 1 | {"frames": [ 2 | 3 | { 4 | "filename": "goblins.png", 5 | "frame": {"x":816,"y":2,"w":431,"h":267}, 6 | "rotated": false, 7 | "trimmed": true, 8 | "spriteSourceSize": {"x":1,"y":1,"w":431,"h":267}, 9 | "sourceSize": {"w":433,"h":269}, 10 | "pivot": {"x":0.5,"y":0.5} 11 | }, 12 | { 13 | "filename": "hero.png", 14 | "frame": {"x":1249,"y":2,"w":500,"h":267}, 15 | "rotated": false, 16 | "trimmed": true, 17 | "spriteSourceSize": {"x":1,"y":1,"w":500,"h":267}, 18 | "sourceSize": {"w":502,"h":269}, 19 | "pivot": {"x":0.5,"y":0.5} 20 | }, 21 | { 22 | "filename": "raptor.png", 23 | "frame": {"x":2,"y":546,"w":1918,"h":288}, 24 | "rotated": false, 25 | "trimmed": true, 26 | "spriteSourceSize": {"x":1,"y":1,"w":1918,"h":288}, 27 | "sourceSize": {"w":1920,"h":290}, 28 | "pivot": {"x":0.5,"y":0.5} 29 | }, 30 | { 31 | "filename": "speedy.png", 32 | "frame": {"x":2,"y":2,"w":812,"h":131}, 33 | "rotated": false, 34 | "trimmed": true, 35 | "spriteSourceSize": {"x":1,"y":1,"w":812,"h":131}, 36 | "sourceSize": {"w":814,"h":133}, 37 | "pivot": {"x":0.5,"y":0.5} 38 | }, 39 | { 40 | "filename": "spineboy.png", 41 | "frame": {"x":2,"y":271,"w":1760,"h":273}, 42 | "rotated": false, 43 | "trimmed": true, 44 | "spriteSourceSize": {"x":1,"y":1,"w":1760,"h":273}, 45 | "sourceSize": {"w":1762,"h":275}, 46 | "pivot": {"x":0.5,"y":0.5} 47 | }], 48 | "meta": { 49 | "app": "http://www.codeandweb.com/texturepacker", 50 | "version": "1.0", 51 | "image": "combined.png", 52 | "format": "RGBA8888", 53 | "size": {"w":1922,"h":836}, 54 | "scale": "1", 55 | "smartupdate": "$TexturePacker:SmartUpdate:199428d0f5dee86697c2f97140285c27:c5c007e99fc803ff1c101a18f93a53bd:3095d46931c42493d5042f9206258520$" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/tank/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 2000, height: 800); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "raptor" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var format = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("tank", "spine/tank.json"); 24 | resourceManager.addTextureAtlas("tank", "spine/tank.atlas", format); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("tank"); 30 | var textureAtlas = resourceManager.getTextureAtlas("tank"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 2300; 40 | skeletonAnimation.y = 700; 41 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.5; 42 | skeletonAnimation.state.setAnimationByName(0, "drive", true); 43 | 44 | stage.addChild(skeletonAnimation); 45 | stage.juggler.add(skeletonAnimation); 46 | } 47 | -------------------------------------------------------------------------------- /example/vine/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 600, height: 1000); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "raptor" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var libgdx = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("vine", "spine/vine.json"); 24 | resourceManager.addTextureAtlas("vine", "spine/vine.atlas", libgdx); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("vine"); 30 | var textureAtlas = resourceManager.getTextureAtlas("vine"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 300; 40 | skeletonAnimation.y = 950; 41 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.8; 42 | skeletonAnimation.state.setAnimationByName(0, "grow", true); 43 | 44 | stage.addChild(skeletonAnimation); 45 | stage.juggler.add(skeletonAnimation); 46 | } 47 | -------------------------------------------------------------------------------- /example/powerup/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 600, height: 400); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "powerup" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var libgdx = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("powerup", "spine/powerup-pro.json"); 24 | resourceManager.addTextureAtlas("powerup", "spine/powerup-pro.atlas", libgdx); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("powerup"); 30 | var textureAtlas = resourceManager.getTextureAtlas("powerup"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 300; 40 | skeletonAnimation.y = 320; 41 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.7; 42 | skeletonAnimation.state.setAnimationByName(0, "bounce", true); 43 | stage.addChild(skeletonAnimation); 44 | stage.juggler.add(skeletonAnimation); 45 | } 46 | -------------------------------------------------------------------------------- /example/stretchyman/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 1600, height: 800); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "raptor" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var format = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("stretchyman", "spine/stretchyman.json"); 24 | resourceManager.addTextureAtlas("stretchyman", "spine/stretchyman.atlas", format); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("stretchyman"); 30 | var textureAtlas = resourceManager.getTextureAtlas("stretchyman"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 200; 40 | skeletonAnimation.y = 700; 41 | //skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.5; 42 | skeletonAnimation.state.setAnimationByName(0, "sneak", true); 43 | 44 | stage.addChild(skeletonAnimation); 45 | stage.juggler.add(skeletonAnimation); 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/animation/mix_direction.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum MixDirection { In, Out } 34 | -------------------------------------------------------------------------------- /lib/src/position_mode.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum PositionMode { fixed, percent } 34 | -------------------------------------------------------------------------------- /lib/src/rotate_mode.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum RotateMode { tangent, chain, chainScale } 34 | -------------------------------------------------------------------------------- /lib/src/animation/mix_pose.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum MixPose { setup, current, currentLayered } 34 | -------------------------------------------------------------------------------- /lib/src/updatable.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class Updatable { 34 | void update(); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/constraint.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class Constraint extends Updatable { 34 | int getOrder(); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/transform_mode.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum TransformMode { normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection } 34 | -------------------------------------------------------------------------------- /lib/src/attachments/attachment_type.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | enum AttachmentType { region, regionsequence, boundingbox, mesh, linkedmesh, path, point, clipping } 34 | -------------------------------------------------------------------------------- /lib/src/attachments/bounding_box_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class BoundingBoxAttachment extends VertexAttachment { 34 | BoundingBoxAttachment(String name) : super(name); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/attachments/path_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class PathAttachment extends VertexAttachment { 34 | Float32List lengths; 35 | bool closed = false; 36 | bool constantSpeed = false; 37 | 38 | PathAttachment(String name) : super(name); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/attachments/clipping_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class ClippingAttachment extends VertexAttachment { 34 | SlotData endSlot; 35 | SpineColor color = SpineColor(0.2275, 0.2275, 0.2275, 1.0); 36 | 37 | ClippingAttachment(String name) : super(name); 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/attachments/attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class Attachment { 34 | final String name; 35 | 36 | Attachment(this.name) { 37 | if (name == null) throw ArgumentError("name cannot be null."); 38 | } 39 | 40 | @override 41 | String toString() => name; 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/animation/timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class Timeline { 34 | /// Sets the value(s) for the specified time. 35 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 36 | double alpha, MixPose pose, MixDirection direction); 37 | 38 | int getPropertyId(); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/event_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class EventData { 34 | final String name; 35 | 36 | int intValue = 0; 37 | double floatValue = 0.0; 38 | String stringValue = ""; 39 | 40 | EventData(this.name) { 41 | if (name == null) throw ArgumentError("name cannot be null."); 42 | } 43 | 44 | @override 45 | String toString() => name; 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/spine_event.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class SpineEvent { 34 | final double time; 35 | final EventData data; 36 | 37 | int intValue; 38 | double floatValue; 39 | String stringValue; 40 | 41 | SpineEvent(this.time, this.data) { 42 | if (data == null) throw ArgumentError("data cannot be null."); 43 | } 44 | 45 | @override 46 | String toString() => data.name; 47 | } 48 | -------------------------------------------------------------------------------- /example/goblins/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 480, height: 600); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "goblins-ffd" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var libgdx = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("goblins", "spine/goblins.json"); 24 | resourceManager.addTextureAtlas("goblins", "spine/goblins.atlas", libgdx); 25 | await resourceManager.load(); 26 | 27 | // load Spine skeleton 28 | 29 | var spineJson = resourceManager.getTextFile("goblins"); 30 | var textureAtlas = resourceManager.getTextureAtlas("goblins"); 31 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 32 | var skeletonLoader = SkeletonLoader(attachmentLoader); 33 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 34 | var animationStateData = AnimationStateData(skeletonData); 35 | 36 | // create the display object showing the skeleton animation 37 | 38 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 39 | skeletonAnimation.x = 240; 40 | skeletonAnimation.y = 560; 41 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 1.5; 42 | skeletonAnimation.state.setAnimationByName(0, "walk", true); 43 | skeletonAnimation.skeleton.skinName = "goblin"; 44 | stage.addChild(skeletonAnimation); 45 | stage.juggler.add(skeletonAnimation); 46 | 47 | // feature: change the skin used for the skeleton 48 | 49 | //skeletonAnimation.skeleton.skinName = "goblin"; 50 | //skeletonAnimation.skeleton.skinName = "goblingirl"; 51 | 52 | // feature: change the attachments assigned to slots 53 | 54 | //skeletonAnimation.skeleton.setAttachment("left hand item", "dagger"); 55 | //skeletonAnimation.skeleton.setAttachment("right hand item", null); 56 | //skeletonAnimation.skeleton.setAttachment("right hand item 2", null); 57 | } 58 | -------------------------------------------------------------------------------- /lib/src/spacing_mode.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | //enum SpacingMode { fixed, percent, length } 34 | 35 | /// Workaround for https://github.com/dart-lang/build/issues/1521 36 | class SpacingMode { 37 | static final String length = "SpacingMode.length"; 38 | static final String percent = "SpacingMode.percent"; 39 | static final String fixed = "SpacingMode.fixed"; 40 | static final List values = [length, percent, fixed]; 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/ik_constraint_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class IkConstraintData { 34 | final String name; 35 | final List bones = List(); 36 | 37 | BoneData target; 38 | int bendDirection = 1; 39 | int order = 0; 40 | double mix = 1.0; 41 | 42 | IkConstraintData(this.name) { 43 | if (name == null) throw ArgumentError("name cannot be null."); 44 | } 45 | 46 | @override 47 | String toString() => name; 48 | } 49 | -------------------------------------------------------------------------------- /example/raptor/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:math' as math; 3 | import 'dart:html' as html; 4 | import 'package:stagexl/stagexl.dart'; 5 | import 'package:stagexl_spine/stagexl_spine.dart'; 6 | 7 | Future main() async { 8 | // configure StageXL default options 9 | 10 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 11 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 12 | 13 | // init Stage and RenderLoop 14 | 15 | var canvas = html.querySelector('#stage'); 16 | var stage = Stage(canvas, width: 1300, height: 1100); 17 | var renderLoop = RenderLoop(); 18 | renderLoop.addStage(stage); 19 | stage.console.visible = true; 20 | stage.console.alpha = 0.75; 21 | 22 | // load "raptor" skeleton resources 23 | 24 | var resourceManager = ResourceManager(); 25 | //var libgdx = TextureAtlasFormat.LIBGDX; 26 | resourceManager.addTextFile("raptor", "spine/raptor.json"); 27 | //resourceManager.addTextureAtlas("raptor", "atlas1/raptor.atlas", libgdx); 28 | //resourceManager.addTextureAtlas("raptor", "atlas2/raptor.json"); 29 | resourceManager.addTextureAtlas("raptor", "atlas3/raptor.json"); 30 | await resourceManager.load(); 31 | 32 | // load Spine skeleton 33 | 34 | var spineJson = resourceManager.getTextFile("raptor"); 35 | var textureAtlas = resourceManager.getTextureAtlas("raptor"); 36 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 37 | var skeletonLoader = SkeletonLoader(attachmentLoader); 38 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 39 | var animationStateData = AnimationStateData(skeletonData); 40 | 41 | // create the display object showing the skeleton animation 42 | 43 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 44 | skeletonAnimation.x = 600; 45 | skeletonAnimation.y = 1000; 46 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.8; 47 | skeletonAnimation.state.setAnimationByName(0, "walk", true); 48 | 49 | stage.onMouseClick.listen((me) { 50 | var state = skeletonAnimation.state; 51 | var roarAnimation = state.setAnimationByName(0, "roar", false); 52 | roarAnimation.mixDuration = 0.25; 53 | roarAnimation.onTrackComplete.first.then((_) { 54 | var walkAnimation = state.setAnimationByName(0, "walk", true); 55 | walkAnimation.mixDuration = 1.0; 56 | }); 57 | }); 58 | 59 | stage.addChild(skeletonAnimation); 60 | stage.juggler.add(skeletonAnimation); 61 | stage.juggler.onElapsedTimeChange.listen((time) { 62 | skeletonAnimation.timeScale = 0.7 + 0.5 * math.sin(time / 2); 63 | }); 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/slot_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class SlotData { 34 | final int index; 35 | final String name; 36 | final BoneData boneData; 37 | 38 | SpineColor color = SpineColor(1.0, 1.0, 1.0, 1.0); 39 | SpineColor darkColor; 40 | 41 | String attachmentName; 42 | BlendMode blendMode = BlendMode.NORMAL; 43 | 44 | SlotData(this.index, this.name, this.boneData) { 45 | if (index < 0) throw ArgumentError("index must be >= 0."); 46 | if (name == null) throw ArgumentError("name cannot be null."); 47 | if (boneData == null) throw ArgumentError("boneData cannot be null."); 48 | } 49 | 50 | @override 51 | String toString() => name; 52 | } 53 | -------------------------------------------------------------------------------- /lib/src/attachments/render_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class RenderAttachment extends VertexAttachment { 34 | final String path; 35 | 36 | BitmapData bitmapData; 37 | Float32List vxList; 38 | Int16List ixList; 39 | int hullLength = 0; 40 | SpineColor color = SpineColor(1.0, 1.0, 1.0, 1.0); 41 | 42 | RenderAttachment(String name, this.path, this.bitmapData) : super(name); 43 | 44 | //---------------------------------------------------------------------------- 45 | 46 | void initRenderGeometry(); 47 | 48 | void updateRenderGeometry(Slot slot) { 49 | computeWorldVertices2(slot, 0, worldVerticesLength, vxList, 0, 4); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/bone_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class BoneData { 34 | final int index; 35 | final String name; 36 | final BoneData parent; 37 | 38 | double length = 0.0; 39 | double x = 0.0; 40 | double y = 0.0; 41 | double rotation = 0.0; 42 | double scaleX = 1.0; 43 | double scaleY = 1.0; 44 | double shearX = 0.0; 45 | double shearY = 0.0; 46 | TransformMode transformMode = TransformMode.normal; 47 | 48 | BoneData(this.index, this.name, this.parent) { 49 | if (index < 0) throw ArgumentError("index must be >= 0"); 50 | if (name == null) throw ArgumentError("name cannot be null."); 51 | } 52 | 53 | @override 54 | String toString() => name; 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/path_constraint_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class PathConstraintData { 34 | final String name; 35 | final List bones = List(); 36 | 37 | SlotData target; 38 | PositionMode positionMode; 39 | //SpacingMode spacingMode; 40 | // Workaround for https://github.com/dart-lang/build/issues/1521 41 | String spacingMode; 42 | RotateMode rotateMode; 43 | 44 | int order = 0; 45 | double offsetRotation = 0.0; 46 | double position = 0.0; 47 | double spacing = 0.0; 48 | double rotateMix = 0.0; 49 | double translateMix = 0.0; 50 | 51 | PathConstraintData(this.name) { 52 | if (name == null) throw ArgumentError("name cannot be null."); 53 | } 54 | 55 | @override 56 | String toString() => name; 57 | } 58 | -------------------------------------------------------------------------------- /lib/src/transform_constraint_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class TransformConstraintData { 34 | final String name; 35 | final List bones = List(); 36 | 37 | BoneData target; 38 | 39 | int order = 0; 40 | bool relative = false; 41 | bool local = false; 42 | 43 | double translateMix = 0.0; 44 | double rotateMix = 0.0; 45 | double scaleMix = 0.0; 46 | double shearMix = 0.0; 47 | double offsetRotation = 0.0; 48 | double offsetX = 0.0; 49 | double offsetY = 0.0; 50 | double offsetScaleX = 0.0; 51 | double offsetScaleY = 0.0; 52 | double offsetShearY = 0.0; 53 | 54 | TransformConstraintData(this.name) { 55 | if (name == null) throw ArgumentError("name cannot be null."); 56 | } 57 | 58 | @override 59 | String toString() => name; 60 | } 61 | -------------------------------------------------------------------------------- /example/hero/spine/hero.atlas: -------------------------------------------------------------------------------- 1 | 2 | hero.png 3 | size: 502,269 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | body 8 | rotate: true 9 | xy: 395, 170 10 | size: 97, 95 11 | orig: 97, 95 12 | offset: 0, 0 13 | index: -1 14 | cape 15 | rotate: true 16 | xy: 177, 50 17 | size: 146, 159 18 | orig: 146, 159 19 | offset: 0, 0 20 | index: -1 21 | eyes 22 | rotate: true 23 | xy: 140, 11 24 | size: 82, 31 25 | orig: 82, 31 26 | offset: 0, 0 27 | index: -1 28 | fingers 29 | rotate: true 30 | xy: 41, 5 31 | size: 31, 33 32 | orig: 31, 33 33 | offset: 0, 0 34 | index: -1 35 | foot1 36 | rotate: true 37 | xy: 456, 118 38 | size: 50, 42 39 | orig: 50, 42 40 | offset: 0, 0 41 | index: -1 42 | foot2 43 | rotate: true 44 | xy: 461, 2 45 | size: 53, 38 46 | orig: 53, 38 47 | offset: 0, 0 48 | index: -1 49 | forearm1 50 | rotate: true 51 | xy: 173, 7 52 | size: 41, 49 53 | orig: 41, 49 54 | offset: 0, 0 55 | index: -1 56 | forearm2 57 | rotate: true 58 | xy: 274, 17 59 | size: 31, 32 60 | orig: 31, 32 61 | offset: 0, 0 62 | index: -1 63 | hand1 64 | rotate: true 65 | xy: 224, 11 66 | size: 37, 48 67 | orig: 37, 48 68 | offset: 0, 0 69 | index: -1 70 | hand2 71 | rotate: true 72 | xy: 2, 5 73 | size: 31, 37 74 | orig: 31, 37 75 | offset: 0, 0 76 | index: -1 77 | head 78 | rotate: true 79 | xy: 2, 95 80 | size: 172, 173 81 | orig: 172, 173 82 | offset: 0, 0 83 | index: -1 84 | mantles 85 | rotate: false 86 | xy: 2, 38 87 | size: 136, 55 88 | orig: 136, 55 89 | offset: 0, 0 90 | index: -1 91 | mouth 92 | rotate: false 93 | xy: 76, 23 94 | size: 61, 13 95 | orig: 61, 13 96 | offset: 0, 0 97 | index: -1 98 | shin1 99 | rotate: true 100 | xy: 397, 115 101 | size: 53, 57 102 | orig: 53, 57 103 | offset: 0, 0 104 | index: -1 105 | shin2 106 | rotate: false 107 | xy: 403, 59 108 | size: 51, 54 109 | orig: 51, 54 110 | offset: 0, 0 111 | index: -1 112 | sword 113 | rotate: false 114 | xy: 177, 198 115 | size: 216, 69 116 | orig: 216, 69 117 | offset: 0, 0 118 | index: -1 119 | thigh1 120 | rotate: true 121 | xy: 338, 42 122 | size: 60, 63 123 | orig: 60, 63 124 | offset: 0, 0 125 | index: -1 126 | thigh2 127 | rotate: false 128 | xy: 338, 104 129 | size: 57, 64 130 | orig: 57, 64 131 | offset: 0, 0 132 | index: -1 133 | upper-arm1 134 | rotate: true 135 | xy: 403, 7 136 | size: 50, 56 137 | orig: 50, 56 138 | offset: 0, 0 139 | index: -1 140 | upper-arm2 141 | rotate: false 142 | xy: 461, 57 143 | size: 39, 59 144 | orig: 39, 59 145 | offset: 0, 0 146 | index: -1 147 | -------------------------------------------------------------------------------- /lib/src/attachments/point_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class PointAttachment extends VertexAttachment { 34 | double x = 0.0; 35 | double y = 0.0; 36 | double rotation = 0.0; 37 | SpineColor color = SpineColor(0.38, 0.94, 0.0, 1.0); 38 | 39 | PointAttachment(String name) : super(name); 40 | 41 | Point computeWorldPosition(Bone bone) { 42 | var x = this.x * bone.a + this.y * bone.b + bone.worldX; 43 | var y = this.x * bone.c + this.y * bone.d + bone.worldY; 44 | return Point(x, y); 45 | } 46 | 47 | double computeWorldRotation(Bone bone) { 48 | double cos = _cosDeg(this.rotation); 49 | double sin = _sinDeg(this.rotation); 50 | double x = cos * bone.a + sin * bone.b; 51 | double y = cos * bone.c + sin * bone.d; 52 | return _toDeg(math.atan2(y, x)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/texture_atlas/spine/hero.atlas: -------------------------------------------------------------------------------- 1 | 2 | hero.png 3 | size: 502,269 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | body 8 | rotate: true 9 | xy: 395, 170 10 | size: 97, 95 11 | orig: 97, 95 12 | offset: 0, 0 13 | index: -1 14 | cape 15 | rotate: true 16 | xy: 177, 50 17 | size: 146, 159 18 | orig: 146, 159 19 | offset: 0, 0 20 | index: -1 21 | eyes 22 | rotate: true 23 | xy: 140, 11 24 | size: 82, 31 25 | orig: 82, 31 26 | offset: 0, 0 27 | index: -1 28 | fingers 29 | rotate: true 30 | xy: 41, 5 31 | size: 31, 33 32 | orig: 31, 33 33 | offset: 0, 0 34 | index: -1 35 | foot1 36 | rotate: true 37 | xy: 456, 118 38 | size: 50, 42 39 | orig: 50, 42 40 | offset: 0, 0 41 | index: -1 42 | foot2 43 | rotate: true 44 | xy: 461, 2 45 | size: 53, 38 46 | orig: 53, 38 47 | offset: 0, 0 48 | index: -1 49 | forearm1 50 | rotate: true 51 | xy: 173, 7 52 | size: 41, 49 53 | orig: 41, 49 54 | offset: 0, 0 55 | index: -1 56 | forearm2 57 | rotate: true 58 | xy: 274, 17 59 | size: 31, 32 60 | orig: 31, 32 61 | offset: 0, 0 62 | index: -1 63 | hand1 64 | rotate: true 65 | xy: 224, 11 66 | size: 37, 48 67 | orig: 37, 48 68 | offset: 0, 0 69 | index: -1 70 | hand2 71 | rotate: true 72 | xy: 2, 5 73 | size: 31, 37 74 | orig: 31, 37 75 | offset: 0, 0 76 | index: -1 77 | head 78 | rotate: true 79 | xy: 2, 95 80 | size: 172, 173 81 | orig: 172, 173 82 | offset: 0, 0 83 | index: -1 84 | mantles 85 | rotate: false 86 | xy: 2, 38 87 | size: 136, 55 88 | orig: 136, 55 89 | offset: 0, 0 90 | index: -1 91 | mouth 92 | rotate: false 93 | xy: 76, 23 94 | size: 61, 13 95 | orig: 61, 13 96 | offset: 0, 0 97 | index: -1 98 | shin1 99 | rotate: true 100 | xy: 397, 115 101 | size: 53, 57 102 | orig: 53, 57 103 | offset: 0, 0 104 | index: -1 105 | shin2 106 | rotate: false 107 | xy: 403, 59 108 | size: 51, 54 109 | orig: 51, 54 110 | offset: 0, 0 111 | index: -1 112 | sword 113 | rotate: false 114 | xy: 177, 198 115 | size: 216, 69 116 | orig: 216, 69 117 | offset: 0, 0 118 | index: -1 119 | thigh1 120 | rotate: true 121 | xy: 338, 42 122 | size: 60, 63 123 | orig: 60, 63 124 | offset: 0, 0 125 | index: -1 126 | thigh2 127 | rotate: false 128 | xy: 338, 104 129 | size: 57, 64 130 | orig: 57, 64 131 | offset: 0, 0 132 | index: -1 133 | upper-arm1 134 | rotate: true 135 | xy: 403, 7 136 | size: 50, 56 137 | orig: 50, 56 138 | offset: 0, 0 139 | index: -1 140 | upper-arm2 141 | rotate: false 142 | xy: 461, 57 143 | size: 39, 59 144 | orig: 39, 59 145 | offset: 0, 0 146 | index: -1 147 | -------------------------------------------------------------------------------- /lib/src/attachments/attachment_loader.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class AttachmentLoader { 34 | /// @return May be null to not load an attachment. 35 | RegionAttachment newRegionAttachment(Skin skin, String name, String path); 36 | 37 | /// @return May be null to not load an attachment. 38 | MeshAttachment newMeshAttachment(Skin skin, String name, String path); 39 | 40 | /// @return May be null to not load an attachment. 41 | BoundingBoxAttachment newBoundingBoxAttachment(Skin skin, String name); 42 | 43 | /// @return May be null to not load an attachment. 44 | PathAttachment newPathAttachment(Skin skin, String name); 45 | 46 | /// @return May be null to not load an attachment 47 | PointAttachment newPointAttachment(Skin skin, String name); 48 | 49 | /// @return May be null to not load an attachment 50 | ClippingAttachment newClippingAttachment(Skin skin, String name); 51 | } 52 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # changelog 2 | 3 | This file contains highlights of what changes on each version of the StageXL_Spine 4 | package. This file is normally updated whenever we push a new version to pub. 5 | 6 | #### Pub version 0.10.2 7 | * Raised dependency to StageXL 1.4.6 8 | * Ready for Dart 2.9 9 | 10 | #### Pub version 0.10.1 11 | * Raised dependency to StageXL 1.4.1 12 | * Ready for Dart 2.4 13 | 14 | #### Pub version 0.10.0 15 | * Raised dependency to StageXL 1.4.0 16 | * Ready for Dart 2.0 17 | 18 | #### Pub version 0.9.0 19 | * Added new features of Spine v3.6 20 | * Updated examples to Spine 3.6 21 | 22 | #### Pub version 0.8.6 23 | * Fixed MeshAttachment.applyDeform 24 | * Fixed Skeleton.updateCache 25 | 26 | #### Pub version 0.8.5 27 | * Don't fire event or complete events when mixDuration is 0 28 | * Fixed AnimationState concurrent modification during iteration 29 | 30 | #### Pub version 0.8.4 31 | * Fixed AnimationState 32 | 33 | #### Pub version 0.8.3 34 | * Raised dependency to StageXL 1.0.0 35 | 36 | #### Pub version 0.8.2 37 | * Fixed AnimationState 38 | 39 | #### Pub version 0.8.1 40 | * Code size and performance optimizations 41 | 42 | #### Pub version 0.8.0 43 | * Added optional DisplayObject bounds and hitTest calculation 44 | * Added all features of the Spine v3.5 format. 45 | * Updated examples to Spine 3.5 46 | 47 | #### Pub version 0.7.0 48 | * Added all features of the Spine v3.4 format. 49 | * Updated examples to Spine 3.4 50 | 51 | #### Pub version 0.6.0 52 | * Added all features of the Spine v3.1 format. 53 | * Updated examples to Spine 3.1 54 | 55 | #### Pub version 0.5.1 56 | * Fixed bone matrix calculation. 57 | * Fixed bone sorting transform behavior. 58 | * Fixed wrong matrix calculation. 59 | 60 | #### Pub version 0.5.0 61 | * Updated to Spine v3 export format. 62 | 63 | #### Pub version 0.4.1 64 | * Added support for all texture atlas features. 65 | * Code optimizations and cleanups. 66 | * Updated to StageXL 0.13.0 67 | 68 | #### Pub version 0.4.0 69 | * Added support for BlendModes. 70 | * Added combined texture atlas example. 71 | * Fixed IK rotation. 72 | * Fixed AnimationState event streams. 73 | * Updated to StageXL 0.12.0 74 | 75 | #### Pub version 0.3.2 76 | * Fixed single bone IK with flip coordinate systems 77 | * Updated to StageXL 0.11.0 78 | 79 | #### Pub version 0.3.1 80 | * Added FFD support for Canvas2D renderer. 81 | * Fixed RegionAttachment transformation matrix. 82 | * Updated to StageXL 0.10.3 83 | 84 | #### Pub version 0.3.0 85 | * Support for FlipX and FlipY timelines. 86 | 87 | #### Pub version 0.2.0 88 | * Support for Inverse Kinematics (IK). 89 | 90 | #### Pub version 0.1.0 91 | * Support for RegionAttachment, MeshAttachment and SkinnedMeshAttachment. 92 | * Support for BoundingBoxAttachment. 93 | * Optimized render path for WebGL and Canvas2D. 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | StageXL_Spine 2 | ============= 3 | 4 | The Spine runtime for the StageXL library. 5 | 6 | *NOTE:* as of version 0.10.0-dev, `StageXL_Spine` requires a Dart 2 SDK. 7 | 8 | [![Build Status](https://travis-ci.org/bp74/StageXL_Spine.svg?branch=master)](https://travis-ci.org/bp74/StageXL_Spine) 9 | 10 | ## Examples 11 | 12 | Raptor () 13 | Tank () 14 | Stretchyman () 15 | SpineBoy () 16 | Goblins () 17 | PowerUp () 18 | Hero () 19 | Coin () 20 | Combined () 21 | 22 | ## Spine Runtime 23 | 24 | Based on the spine-as3 runtime (2017-07-01) 25 | This runtime supports the export format and features of Spine v3.6. 26 | 27 | 28 | 29 | ## Spine License 30 | 31 | Spine Runtimes Software License v2.5 32 | 33 | Copyright (c) 2013-2016, Esoteric Software 34 | All rights reserved. 35 | 36 | You are granted a perpetual, non-exclusive, non-sublicensable, and 37 | non-transferable license to use, install, execute, and perform the Spine 38 | Runtimes software and derivative works solely for personal or internal 39 | use. Without the written permission of Esoteric Software (see Section 2 of 40 | the Spine Software License Agreement), you may not (a) modify, translate, 41 | adapt, or develop new applications using the Spine Runtimes or otherwise 42 | create derivative works or improvements of the Spine Runtimes or (b) remove, 43 | delete, alter, or obscure any trademarks or any copyright, trademark, patent, 44 | or other intellectual property or proprietary rights notices on or in the 45 | Software, including any copy thereof. Redistributions in binary or source 46 | form must include this license and terms. 47 | 48 | THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 49 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 51 | EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 53 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 54 | USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 55 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 | POSSIBILITY OF SUCH DAMAGE. 58 | 59 | -------------------------------------------------------------------------------- /lib/src/animation/timeline_type.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class TimelineType { 34 | final int ordinal; 35 | TimelineType(this.ordinal); 36 | 37 | static final TimelineType rotate = TimelineType(0); 38 | static final TimelineType translate = TimelineType(1); 39 | static final TimelineType scale = TimelineType(2); 40 | static final TimelineType shear = TimelineType(3); 41 | static final TimelineType attachment = TimelineType(4); 42 | static final TimelineType color = TimelineType(5); 43 | static final TimelineType deform = TimelineType(6); 44 | static final TimelineType event = TimelineType(7); 45 | static final TimelineType drawOrder = TimelineType(8); 46 | static final TimelineType ikConstraint = TimelineType(9); 47 | static final TimelineType transformConstraint = TimelineType(10); 48 | static final TimelineType pathConstraintPosition = TimelineType(11); 49 | static final TimelineType pathConstraintSpacing = TimelineType(12); 50 | static final TimelineType pathConstraintMix = TimelineType(13); 51 | static final TimelineType twoColor = TimelineType(14); 52 | } 53 | -------------------------------------------------------------------------------- /lib/stagexl_spine.dart: -------------------------------------------------------------------------------- 1 | library stagexl_spine; 2 | 3 | import 'dart:convert'; 4 | import 'dart:math' as math; 5 | import 'dart:typed_data'; 6 | import 'package:stagexl/stagexl.dart'; 7 | import 'package:stagexl/stagexl.dart' as stagexl; 8 | 9 | part 'src/bone.dart'; 10 | part 'src/bone_data.dart'; 11 | part 'src/constraint.dart'; 12 | part 'src/event_data.dart'; 13 | part 'src/ik_constraint.dart'; 14 | part 'src/ik_constraint_data.dart'; 15 | part 'src/math_util.dart'; 16 | part 'src/path_constraint.dart'; 17 | part 'src/path_constraint_data.dart'; 18 | part 'src/position_mode.dart'; 19 | part 'src/rotate_mode.dart'; 20 | part 'src/skeleton.dart'; 21 | part 'src/skeleton_bounds.dart'; 22 | part 'src/skeleton_data.dart'; 23 | part 'src/skeleton_loader.dart'; 24 | part 'src/skin.dart'; 25 | part 'src/slot.dart'; 26 | part 'src/slot_data.dart'; 27 | part 'src/spacing_mode.dart'; 28 | part 'src/spine_color.dart'; 29 | part 'src/spine_event.dart'; 30 | part 'src/transform_constraint.dart'; 31 | part 'src/transform_constraint_data.dart'; 32 | part 'src/transform_mode.dart'; 33 | part 'src/updatable.dart'; 34 | 35 | part 'src/animation/animation.dart'; 36 | part 'src/animation/animation_state.dart'; 37 | part 'src/animation/animation_state_data.dart'; 38 | part 'src/animation/attachment_timeline.dart'; 39 | part 'src/animation/color_timeline.dart'; 40 | part 'src/animation/curve_timeline.dart'; 41 | part 'src/animation/deform_timeline.dart'; 42 | part 'src/animation/draw_order_timeline.dart'; 43 | part 'src/animation/event_timeline.dart'; 44 | part 'src/animation/ik_constraint_timeline.dart'; 45 | part 'src/animation/mix_direction.dart'; 46 | part 'src/animation/mix_pose.dart'; 47 | part 'src/animation/path_constraint_mix_timeline.dart'; 48 | part 'src/animation/path_constraint_position_timeline.dart'; 49 | part 'src/animation/path_constraint_spacing_timeline.dart'; 50 | part 'src/animation/rotate_timeline.dart'; 51 | part 'src/animation/scale_timeline.dart'; 52 | part 'src/animation/shear_timeline.dart'; 53 | part 'src/animation/timeline.dart'; 54 | part 'src/animation/timeline_type.dart'; 55 | part 'src/animation/track_entry.dart'; 56 | part 'src/animation/track_entry_event.dart'; 57 | part 'src/animation/transform_constraint_timeline.dart'; 58 | part 'src/animation/translate_timeline.dart'; 59 | part 'src/animation/two_color_timeline.dart'; 60 | 61 | part 'src/attachments/attachment.dart'; 62 | part 'src/attachments/attachment_loader.dart'; 63 | part 'src/attachments/attachment_type.dart'; 64 | part 'src/attachments/bounding_box_attachment.dart'; 65 | part 'src/attachments/clipping_attachment.dart'; 66 | part 'src/attachments/mesh_attachment.dart'; 67 | part 'src/attachments/path_attachment.dart'; 68 | part 'src/attachments/point_attachment.dart'; 69 | part 'src/attachments/region_attachment.dart'; 70 | part 'src/attachments/render_attachment.dart'; 71 | part 'src/attachments/vertex_attachment.dart'; 72 | 73 | part 'src/stagexl/skeleton_animation.dart'; 74 | part 'src/stagexl/skeleton_clipping.dart'; 75 | part 'src/stagexl/skeleton_display_object.dart'; 76 | part 'src/stagexl/texture_atlas_attachment_loader.dart'; 77 | -------------------------------------------------------------------------------- /lib/src/animation/animation_state_data.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class AnimationStateData { 34 | final SkeletonData skeletonData; 35 | final Map animationToMixTime = Map(); 36 | double defaultMix = 0.0; 37 | 38 | AnimationStateData(this.skeletonData); 39 | 40 | void setMixByName(String fromName, String toName, double duration) { 41 | Animation from = this.skeletonData.findAnimation(fromName); 42 | if (from == null) throw ArgumentError("Animation not found: $fromName"); 43 | Animation to = this.skeletonData.findAnimation(toName); 44 | if (to == null) throw ArgumentError("Animation not found: $toName"); 45 | setMix(from, to, duration); 46 | } 47 | 48 | void setMix(Animation from, Animation to, double duration) { 49 | if (from == null) throw ArgumentError("from cannot be null."); 50 | if (to == null) throw ArgumentError("to cannot be null."); 51 | animationToMixTime["${from.name}:${to.name}"] = duration; 52 | } 53 | 54 | double getMix(Animation from, Animation to) { 55 | double time = animationToMixTime["${from.name}:${to.name}"]; 56 | return time is double ? time : defaultMix; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/animation/track_entry_event.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | abstract class TrackEntryEvent extends stagexl.Event { 34 | final TrackEntry trackEntry; 35 | TrackEntryEvent(String type, this.trackEntry) : super(type); 36 | 37 | @override 38 | bool get captures => false; 39 | } 40 | 41 | class TrackEntryStartEvent extends TrackEntryEvent { 42 | TrackEntryStartEvent(TrackEntry trackEntry) : super("start", trackEntry); 43 | } 44 | 45 | class TrackEntryInterruptEvent extends TrackEntryEvent { 46 | TrackEntryInterruptEvent(TrackEntry trackEntry) : super("interrupt", trackEntry); 47 | } 48 | 49 | class TrackEntryEndEvent extends TrackEntryEvent { 50 | TrackEntryEndEvent(TrackEntry trackEntry) : super("end", trackEntry); 51 | } 52 | 53 | class TrackEntryDisposeEvent extends TrackEntryEvent { 54 | TrackEntryDisposeEvent(TrackEntry trackEntry) : super("dispose", trackEntry); 55 | } 56 | 57 | class TrackEntryCompleteEvent extends TrackEntryEvent { 58 | TrackEntryCompleteEvent(TrackEntry trackEntry) : super("complete", trackEntry); 59 | } 60 | 61 | class TrackEntryEventEvent extends TrackEntryEvent { 62 | final SpineEvent event; 63 | TrackEntryEventEvent(TrackEntry trackEntry, this.event) : super("event", trackEntry); 64 | } 65 | -------------------------------------------------------------------------------- /example/tank/spine/tank.atlas: -------------------------------------------------------------------------------- 1 | 2 | tank.png 3 | size: 1429,1543 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | antenna 8 | rotate: true 9 | xy: 2, 2 10 | size: 22, 303 11 | orig: 22, 303 12 | offset: 0, 0 13 | index: -1 14 | cannon 15 | rotate: true 16 | xy: 1355, 215 17 | size: 931, 58 18 | orig: 931, 58 19 | offset: 0, 0 20 | index: -1 21 | cannon-connector 22 | rotate: false 23 | xy: 1309, 78 24 | size: 112, 135 25 | orig: 112, 135 26 | offset: 0, 0 27 | index: -1 28 | ground 29 | rotate: true 30 | xy: 623, 2 31 | size: 1024, 353 32 | orig: 1024, 353 33 | offset: 0, 0 34 | index: -1 35 | guntower 36 | rotate: false 37 | xy: 623, 1028 38 | size: 730, 289 39 | orig: 730, 289 40 | offset: 0, 0 41 | index: -1 42 | machinegun 43 | rotate: true 44 | xy: 978, 229 45 | size: 331, 57 46 | orig: 331, 57 47 | offset: 0, 0 48 | index: -1 49 | machinegun-mount 50 | rotate: false 51 | xy: 1355, 1221 52 | size: 72, 96 53 | orig: 72, 96 54 | offset: 0, 0 55 | index: -1 56 | rock 57 | rotate: true 58 | xy: 1037, 309 59 | size: 529, 119 60 | orig: 580, 127 61 | offset: 14, 3 62 | index: -1 63 | smoke-glow 64 | rotate: false 65 | xy: 1158, 231 66 | size: 93, 93 67 | orig: 100, 100 68 | offset: 4, 4 69 | index: -1 70 | smoke-puff01-bg 71 | rotate: false 72 | xy: 1166, 783 73 | size: 184, 123 74 | orig: 184, 123 75 | offset: 0, 0 76 | index: -1 77 | smoke-puff01-fg 78 | rotate: false 79 | xy: 1171, 908 80 | size: 175, 118 81 | orig: 175, 118 82 | offset: 0, 0 83 | index: -1 84 | smoke-puff02-fg 85 | rotate: false 86 | xy: 1171, 671 87 | size: 175, 110 88 | orig: 184, 123 89 | offset: 5, 9 90 | index: -1 91 | smoke-puff03-fg 92 | rotate: false 93 | xy: 1171, 562 94 | size: 175, 107 95 | orig: 184, 123 96 | offset: 5, 12 97 | index: -1 98 | smoke-puff04-fg 99 | rotate: false 100 | xy: 1171, 464 101 | size: 155, 96 102 | orig: 155, 96 103 | offset: 0, 0 104 | index: -1 105 | tank-bottom 106 | rotate: true 107 | xy: 345, 32 108 | size: 1285, 276 109 | orig: 1285, 276 110 | offset: 0, 0 111 | index: -1 112 | tank-bottom-shadow 113 | rotate: true 114 | xy: 2, 26 115 | size: 1291, 341 116 | orig: 1291, 341 117 | offset: 0, 0 118 | index: -1 119 | tank-top 120 | rotate: false 121 | xy: 2, 1319 122 | size: 1407, 222 123 | orig: 1407, 222 124 | offset: 0, 0 125 | index: -1 126 | tread 127 | rotate: true 128 | xy: 978, 742 129 | size: 96, 30 130 | orig: 96, 30 131 | offset: 0, 0 132 | index: -1 133 | tread-inside 134 | rotate: false 135 | xy: 345, 2 136 | size: 25, 28 137 | orig: 25, 28 138 | offset: 0, 0 139 | index: -1 140 | wheel-big 141 | rotate: false 142 | xy: 978, 22 143 | size: 191, 191 144 | orig: 191, 191 145 | offset: 0, 0 146 | index: -1 147 | wheel-big-overlay 148 | rotate: false 149 | xy: 978, 840 150 | size: 186, 186 151 | orig: 186, 186 152 | offset: 0, 0 153 | index: -1 154 | wheel-mid 155 | rotate: false 156 | xy: 1171, 326 157 | size: 136, 136 158 | orig: 136, 136 159 | offset: 0, 0 160 | index: -1 161 | wheel-mid-overlay 162 | rotate: false 163 | xy: 1171, 93 164 | size: 136, 136 165 | orig: 136, 136 166 | offset: 0, 0 167 | index: -1 168 | wheel-small 169 | rotate: false 170 | xy: 1355, 1148 171 | size: 71, 71 172 | orig: 71, 71 173 | offset: 0, 0 174 | index: -1 175 | -------------------------------------------------------------------------------- /lib/src/slot.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class Slot { 34 | final SlotData data; 35 | final Bone bone; 36 | 37 | SpineColor color = SpineColor(1.0, 1.0, 1.0, 1.0); 38 | SpineColor darkColor; 39 | 40 | Attachment _attachment; 41 | double _attachmentTime = 0.0; 42 | Float32List attachmentVertices = Float32List(0); 43 | 44 | Slot(this.data, this.bone) { 45 | if (data == null) throw ArgumentError("data cannot be null."); 46 | if (bone == null) throw ArgumentError("bone cannot be null."); 47 | darkColor = data.darkColor == null ? null : SpineColor(1.0, 1.0, 1.0, 1.0); 48 | setToSetupPose(); 49 | } 50 | 51 | Skeleton get skeleton => bone.skeleton; 52 | 53 | Attachment get attachment => _attachment; 54 | 55 | set attachment(Attachment attachment) { 56 | if (_attachment == attachment) return; 57 | _attachment = attachment; 58 | _attachmentTime = bone.skeleton.time; 59 | attachmentVertices = Float32List(0); 60 | } 61 | 62 | /// Returns the time since the attachment was set. 63 | double get attachmentTime => bone.skeleton.time - _attachmentTime; 64 | 65 | set attachmentTime(double time) { 66 | _attachmentTime = bone.skeleton.time - time; 67 | } 68 | 69 | void setToSetupPose() { 70 | color.setFromColor(data.color); 71 | if (darkColor != null) darkColor.setFromColor(this.data.darkColor); 72 | if (data.attachmentName == null) { 73 | attachment = null; 74 | } else { 75 | _attachment = null; 76 | attachment = bone.skeleton.getAttachmentForSlotIndex(data.index, data.attachmentName); 77 | } 78 | } 79 | 80 | @override 81 | String toString() => data.name; 82 | } 83 | -------------------------------------------------------------------------------- /example/hero/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 400, height: 500); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "hero" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var libgdx = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("hero", "spine/hero.json"); 24 | resourceManager.addTextureAtlas("hero", "spine/hero.atlas", libgdx); 25 | await resourceManager.load(); 26 | 27 | // Add TextField to show user information 28 | 29 | var textField = TextField(); 30 | textField.defaultTextFormat = TextFormat("Arial", 24, Color.White); 31 | textField.defaultTextFormat.align = TextFormatAlign.CENTER; 32 | textField.width = 400; 33 | textField.x = 0; 34 | textField.y = 450; 35 | textField.text = "tap to change animation"; 36 | textField.addTo(stage); 37 | 38 | // load Spine skeleton 39 | 40 | var spineJson = resourceManager.getTextFile("hero"); 41 | var textureAtlas = resourceManager.getTextureAtlas("hero"); 42 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 43 | var skeletonLoader = SkeletonLoader(attachmentLoader); 44 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 45 | 46 | // configure Spine animation mix 47 | 48 | var animationStateData = AnimationStateData(skeletonData); 49 | animationStateData.setMixByName("idle", "walk", 0.2); 50 | animationStateData.setMixByName("walk", "run", 0.2); 51 | animationStateData.setMixByName("run", "attack", 0.2); 52 | animationStateData.setMixByName("attack", "crouch", 0.2); 53 | animationStateData.setMixByName("crouch", "idle", 0.2); 54 | 55 | // create the display object showing the skeleton animation 56 | 57 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 58 | skeletonAnimation.x = 180; 59 | skeletonAnimation.y = 400; 60 | skeletonAnimation.state.setAnimationByName(0, "idle", true); 61 | stage.addChild(skeletonAnimation); 62 | stage.juggler.add(skeletonAnimation); 63 | 64 | // change the animation on every mouse click 65 | 66 | var animations = ["idle", "walk", "run", "attack", "crouch"]; 67 | var animationIndex = 0; 68 | 69 | stage.onMouseClick.listen((me) { 70 | animationIndex = (animationIndex + 1) % animations.length; 71 | skeletonAnimation.state.setAnimationByName(0, animations[animationIndex], true); 72 | }); 73 | 74 | // register track events 75 | 76 | skeletonAnimation.state.onTrackStart.listen((TrackEntryStartEvent e) { 77 | print("${e.trackEntry.trackIndex} start: ${e.trackEntry}"); 78 | }); 79 | 80 | skeletonAnimation.state.onTrackEnd.listen((TrackEntryEndEvent e) { 81 | print("${e.trackEntry.trackIndex} end: ${e.trackEntry}"); 82 | }); 83 | 84 | skeletonAnimation.state.onTrackComplete.listen((TrackEntryCompleteEvent e) { 85 | print("${e.trackEntry.trackIndex} complete: ${e.trackEntry}"); 86 | }); 87 | 88 | skeletonAnimation.state.onTrackEvent.listen((TrackEntryEventEvent e) { 89 | var ev = e.event; 90 | var text = "${ev.data.name}: ${ev.intValue}, ${ev.floatValue}, ${ev.stringValue}"; 91 | print("${e.trackEntry.trackIndex} event: ${e.trackEntry}, $text"); 92 | }); 93 | } 94 | -------------------------------------------------------------------------------- /lib/src/skin.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | /// Stores attachments by slot index and attachment name. 34 | /// 35 | class Skin { 36 | final String name; 37 | final List attachments = List(); 38 | 39 | Skin(this.name) { 40 | if (name == null) throw ArgumentError("name cannot be null."); 41 | } 42 | 43 | void addAttachment(int slotIndex, String name, Attachment attachment) { 44 | if (attachment == null) throw ArgumentError("attachment cannot be null."); 45 | if (slotIndex >= attachments.length) attachments.length = slotIndex + 1; 46 | if (attachments[slotIndex] == null) attachments[slotIndex] = Map(); 47 | attachments[slotIndex][name] = attachment; 48 | } 49 | 50 | Attachment getAttachment(int slotIndex, String name) { 51 | if (slotIndex >= attachments.length) return null; 52 | Map map = attachments[slotIndex]; 53 | return map != null ? map[name] : null; 54 | } 55 | 56 | /// Attach each attachment in this skin if the corresponding attachment in 57 | /// the old skin is currently attached. 58 | /// 59 | void attachAll(Skeleton skeleton, Skin oldSkin) { 60 | int slotIndex = 0; 61 | for (Slot slot in skeleton.slots) { 62 | Attachment slotAttachment = slot.attachment; 63 | if (slotAttachment != null && slotIndex < oldSkin.attachments.length) { 64 | Map map = oldSkin.attachments[slotIndex] ?? {}; 65 | for (var name in map.keys) { 66 | Attachment skinAttachment = map[name]; 67 | if (slotAttachment == skinAttachment) { 68 | Attachment attachment = getAttachment(slotIndex, name); 69 | if (attachment != null) slot.attachment = attachment; 70 | break; 71 | } 72 | } 73 | } 74 | slotIndex++; 75 | } 76 | } 77 | 78 | @override 79 | String toString() => name; 80 | } 81 | -------------------------------------------------------------------------------- /example/texture_atlas/spine/speedy.atlas: -------------------------------------------------------------------------------- 1 | 2 | speedy.png 3 | size: 814,133 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | belt-ends 8 | rotate: true 9 | xy: 422, 2 10 | size: 45, 56 11 | orig: 45, 56 12 | offset: 0, 0 13 | index: -1 14 | hair-1 15 | rotate: true 16 | xy: 398, 49 17 | size: 82, 39 18 | orig: 82, 39 19 | offset: 0, 0 20 | index: -1 21 | hair-2 22 | rotate: true 23 | xy: 606, 57 24 | size: 74, 43 25 | orig: 74, 43 26 | offset: 0, 0 27 | index: -1 28 | head 29 | rotate: false 30 | xy: 2, 8 31 | size: 116, 123 32 | orig: 116, 124 33 | offset: 0, 1 34 | index: -1 35 | hood-end1a 36 | rotate: false 37 | xy: 298, 47 38 | size: 23, 84 39 | orig: 23, 84 40 | offset: 0, 0 41 | index: -1 42 | hood-end1b 43 | rotate: false 44 | xy: 519, 52 45 | size: 28, 79 46 | orig: 28, 79 47 | offset: 0, 0 48 | index: -1 49 | hood-end1c 50 | rotate: true 51 | xy: 200, 8 52 | size: 31, 70 53 | orig: 31, 70 54 | offset: 0, 0 55 | index: -1 56 | hood-end1d 57 | rotate: false 58 | xy: 439, 49 59 | size: 29, 82 60 | orig: 29, 82 61 | offset: 0, 0 62 | index: -1 63 | hood-end1e 64 | rotate: true 65 | xy: 120, 4 66 | size: 35, 78 67 | orig: 35, 78 68 | offset: 0, 0 69 | index: -1 70 | hood-end1f 71 | rotate: true 72 | xy: 616, 16 73 | size: 39, 71 74 | orig: 39, 71 75 | offset: 0, 0 76 | index: -1 77 | hood-end2a 78 | rotate: false 79 | xy: 549, 55 80 | size: 30, 76 81 | orig: 30, 76 82 | offset: 0, 0 83 | index: -1 84 | hood-end2b 85 | rotate: false 86 | xy: 681, 60 87 | size: 38, 71 88 | orig: 38, 71 89 | offset: 0, 0 90 | index: -1 91 | hood-end2c 92 | rotate: true 93 | xy: 272, 2 94 | size: 42, 64 95 | orig: 42, 64 96 | offset: 0, 0 97 | index: -1 98 | hood-end2d 99 | rotate: false 100 | xy: 581, 55 101 | size: 23, 76 102 | orig: 23, 76 103 | offset: 0, 0 104 | index: -1 105 | hood-end2e 106 | rotate: false 107 | xy: 651, 57 108 | size: 28, 74 109 | orig: 28, 74 110 | offset: 0, 0 111 | index: -1 112 | hood-end2f 113 | rotate: false 114 | xy: 721, 61 115 | size: 31, 70 116 | orig: 31, 70 117 | offset: 0, 0 118 | index: -1 119 | left-foot 120 | rotate: true 121 | xy: 470, 51 122 | size: 80, 47 123 | orig: 80, 47 124 | offset: 0, 0 125 | index: -1 126 | left-foot-bent01 127 | rotate: true 128 | xy: 208, 44 129 | size: 87, 43 130 | orig: 87, 43 131 | offset: 0, 0 132 | index: -1 133 | left-foot-bent02 134 | rotate: false 135 | xy: 338, 3 136 | size: 82, 43 137 | orig: 82, 43 138 | offset: 0, 0 139 | index: -1 140 | left-foot-side 141 | rotate: true 142 | xy: 120, 41 143 | size: 90, 42 144 | orig: 90, 42 145 | offset: 0, 0 146 | index: -1 147 | left-hand 148 | rotate: true 149 | xy: 561, 5 150 | size: 48, 53 151 | orig: 52, 53 152 | offset: 4, 0 153 | index: -1 154 | right-foot 155 | rotate: false 156 | xy: 689, 2 157 | size: 66, 56 158 | orig: 66, 56 159 | offset: 0, 0 160 | index: -1 161 | right-foot-bent01 162 | rotate: true 163 | xy: 253, 46 164 | size: 85, 43 165 | orig: 85, 43 166 | offset: 0, 0 167 | index: -1 168 | right-foot-bent02 169 | rotate: false 170 | xy: 480, 6 171 | size: 79, 43 172 | orig: 79, 43 173 | offset: 0, 0 174 | index: -1 175 | right-foot-side 176 | rotate: true 177 | xy: 164, 41 178 | size: 90, 42 179 | orig: 90, 42 180 | offset: 0, 0 181 | index: -1 182 | right-hand 183 | rotate: false 184 | xy: 757, 73 185 | size: 55, 58 186 | orig: 56, 58 187 | offset: 0, 0 188 | index: -1 189 | torso 190 | rotate: false 191 | xy: 323, 48 192 | size: 73, 83 193 | orig: 77, 85 194 | offset: 0, 0 195 | index: -1 196 | -------------------------------------------------------------------------------- /lib/src/animation/event_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class EventTimeline implements Timeline { 34 | final Float32List frames; // time, ... 35 | final List events; 36 | 37 | EventTimeline(int frameCount) 38 | : frames = Float32List(frameCount), 39 | events = List(frameCount); 40 | 41 | @override 42 | int getPropertyId() { 43 | return TimelineType.event.ordinal << 24; 44 | } 45 | 46 | int get frameCount => frames.length; 47 | 48 | /// Sets the time and value of the specified keyframe. 49 | /// 50 | void setFrame(int frameIndex, SpineEvent event) { 51 | frames[frameIndex] = event.time.toDouble(); 52 | events[frameIndex] = event; 53 | } 54 | 55 | /// Fires events for frames > lastTime and <= time. 56 | 57 | @override 58 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 59 | double alpha, MixPose pose, MixDirection direction) { 60 | if (firedEvents == null) return; 61 | 62 | if (lastTime > time) { 63 | // Fire events after last time for looped animations. 64 | apply(skeleton, lastTime, double.maxFinite, firedEvents, alpha, pose, direction); 65 | lastTime = -1.0; 66 | } else if (lastTime >= frames[frameCount - 1]) { 67 | // Last time is after last frame. 68 | return; 69 | } 70 | 71 | if (time < frames[0]) return; // Time is before first frame. 72 | 73 | int frame = 0; 74 | 75 | if (lastTime < frames[0]) { 76 | frame = 0; 77 | } else { 78 | frame = Animation.binarySearch1(frames, lastTime); 79 | double frameTime = frames[frame]; 80 | while (frame > 0) { 81 | // Fire multiple events with the same frame. 82 | if (frames[frame - 1] != frameTime) break; 83 | frame--; 84 | } 85 | } 86 | 87 | while (frame < frameCount && time >= frames[frame]) { 88 | firedEvents.add(events[frame]); 89 | frame++; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/src/animation/attachment_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class AttachmentTimeline implements Timeline { 34 | final Float32List frames; // time, ... 35 | final List attachmentNames; 36 | int slotIndex = 0; 37 | 38 | AttachmentTimeline(int frameCount) 39 | : frames = Float32List(frameCount), 40 | attachmentNames = List.filled(frameCount, null); 41 | 42 | int get frameCount => frames.length; 43 | 44 | @override 45 | int getPropertyId() { 46 | return (TimelineType.attachment.ordinal << 24) + slotIndex; 47 | } 48 | 49 | /// Sets the time and value of the specified keyframe. 50 | /// 51 | void setFrame(int frameIndex, double time, String attachmentName) { 52 | frames[frameIndex] = time.toDouble(); 53 | attachmentNames[frameIndex] = attachmentName; 54 | } 55 | 56 | @override 57 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 58 | double alpha, MixPose pose, MixDirection direction) { 59 | String attachmentName; 60 | Slot slot = skeleton.slots[slotIndex]; 61 | 62 | if (direction == MixDirection.Out && pose == MixPose.setup) { 63 | attachmentName = slot.data.attachmentName; 64 | slot.attachment = attachmentName == null 65 | ? null 66 | : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName); 67 | return; 68 | } 69 | 70 | if (time < frames[0]) { 71 | // Time is before first frame. 72 | if (pose == MixPose.setup) { 73 | attachmentName = slot.data.attachmentName; 74 | slot.attachment = attachmentName == null 75 | ? null 76 | : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName); 77 | } 78 | return; 79 | } 80 | 81 | int frameIndex = (time >= frames.last) 82 | ? frames.length - 1 // Time is after last frame. 83 | : Animation.binarySearch(frames, time, 1) - 1; 84 | 85 | attachmentName = attachmentNames[frameIndex]; 86 | skeleton.slots[slotIndex].attachment = (attachmentName != null) 87 | ? skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName) 88 | : null; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/src/attachments/mesh_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class MeshAttachment extends RenderAttachment { 34 | Float32List regionUVs; 35 | Int16List triangles; 36 | Int16List edges; 37 | 38 | bool inheritDeform = false; 39 | double width = 0.0; 40 | double height = 0.0; 41 | MeshAttachment _parentMesh; 42 | 43 | MeshAttachment(String name, String path, BitmapData bitmapData) : super(name, path, bitmapData); 44 | 45 | //--------------------------------------------------------------------------- 46 | 47 | MeshAttachment get parentMesh => _parentMesh; 48 | 49 | set parentMesh(MeshAttachment parentMesh) { 50 | _parentMesh = parentMesh; 51 | if (parentMesh != null) { 52 | bones = parentMesh.bones; 53 | vertices = parentMesh.vertices; 54 | worldVerticesLength = parentMesh.worldVerticesLength; 55 | regionUVs = parentMesh.regionUVs; 56 | triangles = parentMesh.triangles; 57 | hullLength = parentMesh.hullLength; 58 | edges = parentMesh.edges; 59 | width = parentMesh.width; 60 | height = parentMesh.height; 61 | } 62 | } 63 | 64 | @override 65 | bool applyDeform(VertexAttachment sourceAttachment) { 66 | if (sourceAttachment == this) return true; 67 | if (sourceAttachment == _parentMesh && inheritDeform) return true; 68 | return false; 69 | } 70 | 71 | //--------------------------------------------------------------------------- 72 | 73 | @override 74 | void initRenderGeometry() { 75 | ixList = Int16List.fromList(triangles); 76 | vxList = Float32List(regionUVs.length * 2); 77 | 78 | var matrix = bitmapData.renderTextureQuad.samplerMatrix; 79 | var ma = matrix.a * bitmapData.width; 80 | var mb = matrix.b * bitmapData.width; 81 | var mc = matrix.c * bitmapData.height; 82 | var md = matrix.d * bitmapData.height; 83 | var mx = matrix.tx; 84 | var my = matrix.ty; 85 | 86 | for (int i = 0, o = 0; i < regionUVs.length - 1; i += 2, o += 4) { 87 | var u = regionUVs[i + 0]; 88 | var v = regionUVs[i + 1]; 89 | vxList[o + 2] = u * ma + v * mc + mx; 90 | vxList[o + 3] = u * mb + v * md + my; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/src/animation/path_constraint_spacing_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline { 34 | static const int _ENTRIES = 2; 35 | static const int _PREV_TIME = -2; 36 | static const int _PREV_VALUE = -1; 37 | static const int _TIME = 0; 38 | static const int _VALUE = 1; 39 | 40 | PathConstraintSpacingTimeline(int frameCount) : super(frameCount); 41 | 42 | @override 43 | int getPropertyId() { 44 | return (TimelineType.pathConstraintSpacing.ordinal << 24) + pathConstraintIndex; 45 | } 46 | 47 | @override 48 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 49 | double alpha, MixPose pose, MixDirection direction) { 50 | PathConstraint constraint = skeleton.pathConstraints[pathConstraintIndex]; 51 | PathConstraintData data = constraint.data; 52 | double s = 0.0; 53 | 54 | if (time < frames[0]) { 55 | // Time is before first frame. 56 | if (pose == MixPose.setup) { 57 | constraint.spacing = data.spacing; 58 | } else if (pose == MixPose.current) { 59 | constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; 60 | } 61 | return; 62 | } 63 | 64 | if (time >= frames[frames.length + _PREV_TIME]) { 65 | // Time is after last frame. 66 | s = frames[frames.length + _PREV_VALUE]; 67 | } else { 68 | // Interpolate between the previous frame and the current frame. 69 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 70 | double t0 = frames[frame + _PREV_TIME]; 71 | double s0 = frames[frame + _PREV_VALUE]; 72 | double t1 = frames[frame + _TIME]; 73 | double s1 = frames[frame + _VALUE]; 74 | double between = 1.0 - (time - t1) / (t0 - t1); 75 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 76 | s = s0 + (s1 - s0) * percent; 77 | } 78 | 79 | if (pose == MixPose.setup) { 80 | constraint.spacing = data.spacing + (s - data.spacing) * alpha; 81 | } else { 82 | constraint.spacing = constraint.spacing + (s - constraint.spacing) * alpha; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/src/animation/draw_order_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class DrawOrderTimeline implements Timeline { 34 | final Float32List frames; // time, ... 35 | final List drawOrders; 36 | 37 | DrawOrderTimeline(int frameCount) 38 | : frames = Float32List(frameCount), 39 | drawOrders = List(frameCount); 40 | 41 | @override 42 | int getPropertyId() { 43 | return TimelineType.drawOrder.ordinal << 24; 44 | } 45 | 46 | int get frameCount => frames.length; 47 | 48 | /// Sets the time and value of the specified keyframe. 49 | 50 | void setFrame(int frameIndex, double time, Int16List drawOrder) { 51 | frames[frameIndex] = time.toDouble(); 52 | drawOrders[frameIndex] = drawOrder; 53 | } 54 | 55 | @override 56 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 57 | double alpha, MixPose pose, MixDirection direction) { 58 | List drawOrder = skeleton.drawOrder; 59 | List slots = skeleton.slots; 60 | 61 | if (direction == MixDirection.Out && pose == MixPose.setup) { 62 | for (int i = 0; i < slots.length; i++) { 63 | drawOrder[i] = slots[i]; 64 | } 65 | return; 66 | } 67 | 68 | if (time < frames[0]) { 69 | // Time is before first frame. 70 | if (pose == MixPose.setup) { 71 | for (int i = 0; i < slots.length; i++) { 72 | drawOrder[i] = slots[i]; 73 | } 74 | } 75 | return; 76 | } 77 | 78 | int frameIndex = 0; 79 | 80 | if (time >= frames[frames.length - 1]) { 81 | // Time is after last frame. 82 | frameIndex = frames.length - 1; 83 | } else { 84 | frameIndex = Animation.binarySearch1(frames, time) - 1; 85 | } 86 | 87 | Int16List drawOrderToSetupIndex = drawOrders[frameIndex]; 88 | 89 | if (drawOrderToSetupIndex == null) { 90 | for (int i = 0; i < slots.length; i++) { 91 | drawOrder[i] = slots[i]; 92 | } 93 | } else { 94 | for (int i = 0; i < drawOrderToSetupIndex.length; i++) { 95 | drawOrder[i] = slots[drawOrderToSetupIndex[i]]; 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/src/spine_color.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class SpineColor { 34 | //static final Color WHITE = new Color(1.0, 1.0, 1.0, 1.0); 35 | //static final Color RED = new Color(1.0, 0.0, 0.0, 1.0); 36 | //static final Color GREEN = new Color(0.0, 1.0, 0.0, 1.0); 37 | //static final Color BLUE = new Color(0.0, 0.0, 1.0, 1.0); 38 | //static final Color MAGENTA = new Color(1.0, 0.0, 1.0, 1.0); 39 | 40 | double r = 0.0; 41 | double g = 0.0; 42 | double b = 0.0; 43 | double a = 0.0; 44 | 45 | SpineColor(this.r, this.g, this.b, [this.a = 0.0]); 46 | 47 | SpineColor setFrom(double r, double g, double b, double a) { 48 | this.r = r; 49 | this.g = g; 50 | this.b = b; 51 | this.a = a; 52 | this.clamp(); 53 | return this; 54 | } 55 | 56 | SpineColor setFromColor(SpineColor c) { 57 | this.r = c.r; 58 | this.g = c.g; 59 | this.b = c.b; 60 | this.a = c.a; 61 | return this; 62 | } 63 | 64 | SpineColor setFromString(String hex) { 65 | hex = hex.startsWith('#') ? hex.substring(1) : hex; 66 | this.r = int.parse(hex.substring(0, 2), radix: 16) / 255.0; 67 | this.g = int.parse(hex.substring(2, 4), radix: 16) / 255.0; 68 | this.b = int.parse(hex.substring(4, 6), radix: 16) / 255.0; 69 | this.a = (hex.length != 8 ? 255 : int.parse(hex.substring(6, 8), radix: 16)) / 255.0; 70 | return this; 71 | } 72 | 73 | SpineColor add(double r, double g, double b, double a) { 74 | this.r += r; 75 | this.g += g; 76 | this.b += b; 77 | this.a += a; 78 | this.clamp(); 79 | return this; 80 | } 81 | 82 | SpineColor clamp() { 83 | if (this.r < 0.0) { 84 | this.r = 0.0; 85 | } else if (this.r > 1.0) { 86 | this.r = 1.0; 87 | } 88 | 89 | if (this.g < 0.0) { 90 | this.g = 0.0; 91 | } else if (this.g > 1.0) { 92 | this.g = 1.0; 93 | } 94 | 95 | if (this.b < 0.0) { 96 | this.b = 0.0; 97 | } else if (this.b > 1.0) { 98 | this.b = 1.0; 99 | } 100 | 101 | if (this.a < 0.0) { 102 | this.a = 0.0; 103 | } else if (this.a > 1.0) { 104 | this.a = 1.0; 105 | } 106 | 107 | return this; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/src/animation/shear_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class ShearTimeline extends TranslateTimeline { 34 | static const int _ENTRIES = 3; 35 | static const int _PREV_TIME = -3; 36 | static const int _PREV_X = -2; 37 | static const int _PREV_Y = -1; 38 | static const int _TIME = 0; 39 | static const int _X = 1; 40 | static const int _Y = 2; 41 | 42 | ShearTimeline(int frameCount) : super(frameCount); 43 | 44 | @override 45 | int getPropertyId() { 46 | return (TimelineType.shear.ordinal << 24) + boneIndex; 47 | } 48 | 49 | @override 50 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 51 | double alpha, MixPose pose, MixDirection direction) { 52 | Bone bone = skeleton.bones[boneIndex]; 53 | double x = 0.0; 54 | double y = 0.0; 55 | 56 | if (time < frames[0]) { 57 | // Time is before first frame. 58 | if (pose == MixPose.setup) { 59 | bone.shearX = bone.data.shearX; 60 | bone.shearY = bone.data.shearY; 61 | } else if (pose == MixPose.current) { 62 | bone.shearX += (bone.data.shearX - bone.shearX) * alpha; 63 | bone.shearY += (bone.data.shearY - bone.shearY) * alpha; 64 | } 65 | return; 66 | } 67 | 68 | if (time >= frames[frames.length + _PREV_TIME]) { 69 | // Time is after last frame. 70 | x = frames[frames.length + _PREV_X]; 71 | y = frames[frames.length + _PREV_Y]; 72 | } else { 73 | // Interpolate between the previous frame and the current frame. 74 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 75 | double t0 = frames[frame + _PREV_TIME]; 76 | double x0 = frames[frame + _PREV_X]; 77 | double y0 = frames[frame + _PREV_Y]; 78 | double t1 = frames[frame + _TIME]; 79 | double x1 = frames[frame + _X]; 80 | double y1 = frames[frame + _Y]; 81 | double between = 1.0 - (time - t1) / (t0 - t1); 82 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 83 | x = x0 + (x1 - x0) * percent; 84 | y = y0 + (y1 - y0) * percent; 85 | } 86 | 87 | if (pose == MixPose.setup) { 88 | bone.shearX = bone.data.shearX + x * alpha; 89 | bone.shearY = bone.data.shearY + y * alpha; 90 | } else { 91 | bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX + x) * alpha; 92 | bone.shearY = bone.shearY + (bone.data.shearY - bone.shearY + y) * alpha; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/src/animation/animation.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class Animation { 34 | final String name; 35 | final List timelines; 36 | final double duration; 37 | 38 | Animation(this.name, this.timelines, this.duration) { 39 | if (name == null) throw ArgumentError("name cannot be null."); 40 | if (timelines == null) throw ArgumentError("timelines cannot be null."); 41 | } 42 | 43 | /// Poses the skeleton at the specified time for this animation. 44 | /// 45 | void apply(Skeleton skeleton, double lastTime, double time, bool loop, List events, 46 | double alpha, MixPose pose, MixDirection direction) { 47 | if (skeleton == null) throw ArgumentError("skeleton cannot be null."); 48 | 49 | if (loop && duration != 0) { 50 | time = time.remainder(duration); 51 | if (lastTime > 0) lastTime %= duration; 52 | } 53 | 54 | for (int i = 0; i < timelines.length; i++) { 55 | timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction); 56 | } 57 | } 58 | 59 | /// target: After the first and before the last entry. 60 | static int binarySearch(Float32List values, double target, int step) { 61 | int low = 0; 62 | int high = values.length ~/ step - 2; 63 | int current = high >> 1; 64 | if (high == 0) return step; 65 | 66 | for (;;) { 67 | if (values[(current + 1) * step] <= target) { 68 | low = current + 1; 69 | } else { 70 | high = current; 71 | } 72 | 73 | if (low == high) { 74 | return (low + 1) * step; 75 | } else { 76 | current = (low + high) >> 1; 77 | } 78 | } 79 | } 80 | 81 | static int binarySearch1(Float32List values, double target) { 82 | int low = 0; 83 | int high = values.length - 2; 84 | if (high == 0) return 1; 85 | 86 | int current = high >> 1; 87 | for (;;) { 88 | if (values[current + 1] <= target) { 89 | low = current + 1; 90 | } else { 91 | high = current; 92 | } 93 | if (low == high) return low + 1; 94 | current = (low + high) >> 1; 95 | } 96 | } 97 | 98 | static int linearSearch(Float32List values, double target, int step) { 99 | for (int i = 0; i <= values.length - step; i += step) { 100 | if (values[i] > target) return i; 101 | } 102 | return -1; 103 | } 104 | 105 | @override 106 | String toString() => name; 107 | } 108 | -------------------------------------------------------------------------------- /lib/src/animation/rotate_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class RotateTimeline extends CurveTimeline { 34 | static const int _ENTRIES = 2; 35 | static const int _PREV_TIME = -2; 36 | static const int _PREV_ROTATION = -1; 37 | static const int _TIME = 0; 38 | static const int _ROTATION = 1; 39 | 40 | final Float32List frames; // time, degrees, ... 41 | int boneIndex = 0; 42 | 43 | RotateTimeline(int frameCount) 44 | : frames = Float32List(frameCount * _ENTRIES), 45 | super(frameCount); 46 | 47 | @override 48 | int getPropertyId() { 49 | return (TimelineType.rotate.ordinal << 24) + boneIndex; 50 | } 51 | 52 | /// Sets the time and angle of the specified keyframe. 53 | 54 | void setFrame(int frameIndex, double time, double degrees) { 55 | frameIndex = frameIndex << 1; 56 | frames[frameIndex + _TIME] = time.toDouble(); 57 | frames[frameIndex + _ROTATION] = degrees.toDouble(); 58 | } 59 | 60 | @override 61 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 62 | double alpha, MixPose pose, MixDirection direction) { 63 | Bone bone = skeleton.bones[boneIndex]; 64 | double rotation = 0.0; 65 | 66 | if (time < frames[0]) { 67 | // Time is before first frame. 68 | if (pose == MixPose.setup) { 69 | bone.rotation = bone.data.rotation; 70 | } else if (pose == MixPose.current) { 71 | rotation = bone.data.rotation - bone.rotation; 72 | bone.rotation += _wrapRotation(rotation) * alpha; 73 | } 74 | return; 75 | } 76 | 77 | if (time >= frames[frames.length + _PREV_TIME]) { 78 | // Time is after last frame. 79 | rotation = frames[frames.length + _PREV_ROTATION]; 80 | } else { 81 | // Interpolate between the previous frame and the current frame. 82 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 83 | double t0 = frames[frame + _PREV_TIME]; 84 | double r0 = frames[frame + _PREV_ROTATION]; 85 | double t1 = frames[frame + _TIME]; 86 | double r1 = frames[frame + _ROTATION]; 87 | double between = 1.0 - (time - t1) / (t0 - t1); 88 | double percent = getCurvePercent((frame >> 1) - 1, between); 89 | rotation = r0 + _wrapRotation(r1 - r0) * percent; 90 | } 91 | 92 | if (pose == MixPose.setup) { 93 | bone.rotation = bone.data.rotation + _wrapRotation(rotation) * alpha; 94 | } else { 95 | rotation = bone.data.rotation - bone.rotation + rotation; 96 | bone.rotation = bone.rotation + _wrapRotation(rotation) * alpha; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/src/animation/path_constraint_position_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class PathConstraintPositionTimeline extends CurveTimeline { 34 | static const int _ENTRIES = 2; 35 | static const int _PREV_TIME = -2; 36 | static const int _PREV_VALUE = -1; 37 | static const int _TIME = 0; 38 | static const int _VALUE = 1; 39 | 40 | int pathConstraintIndex = 0; 41 | 42 | final Float32List frames; // time, position, ... 43 | 44 | PathConstraintPositionTimeline(int frameCount) 45 | : frames = Float32List(frameCount * _ENTRIES), 46 | super(frameCount); 47 | 48 | @override 49 | int getPropertyId() { 50 | return (TimelineType.pathConstraintPosition.ordinal << 24) + pathConstraintIndex; 51 | } 52 | 53 | /// Sets the time and value of the specified keyframe. 54 | 55 | void setFrame(int frameIndex, double time, double value) { 56 | frameIndex *= _ENTRIES; 57 | frames[frameIndex + _TIME] = time; 58 | frames[frameIndex + _VALUE] = value; 59 | } 60 | 61 | @override 62 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 63 | double alpha, MixPose pose, MixDirection direction) { 64 | PathConstraint constraint = skeleton.pathConstraints[pathConstraintIndex]; 65 | PathConstraintData data = constraint.data; 66 | double p = 0.0; 67 | 68 | if (time < frames[0]) { 69 | // Time is before first frame. 70 | if (pose == MixPose.setup) { 71 | constraint.position = data.position; 72 | } else if (pose == MixPose.current) { 73 | constraint.position += (constraint.data.position - constraint.position) * alpha; 74 | } 75 | return; 76 | } 77 | 78 | if (time >= frames[frames.length + _PREV_TIME]) { 79 | // Time is after last frame. 80 | p = frames[frames.length + _PREV_VALUE]; 81 | } else { 82 | // Interpolate between the previous frame and the current frame. 83 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 84 | double t0 = frames[frame + _PREV_TIME]; 85 | double p0 = frames[frame + _PREV_VALUE]; 86 | double t1 = frames[frame + _TIME]; 87 | double p1 = frames[frame + _VALUE]; 88 | double between = 1.0 - (time - t1) / (t0 - t1); 89 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 90 | p = p0 + (p1 - p0) * percent; 91 | } 92 | 93 | if (pose == MixPose.setup) { 94 | constraint.position = data.position + (p - data.position) * alpha; 95 | } else { 96 | constraint.position = constraint.position + (p - constraint.position) * alpha; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /example/spineboy/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.DarkSlateGray; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 480, height: 600); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | 19 | // load "spineboy" skeleton resources 20 | 21 | var resourceManager = ResourceManager(); 22 | var libgdxx = TextureAtlasFormat.LIBGDX; 23 | resourceManager.addTextFile("spineboy", "spine/spineboy.json"); 24 | resourceManager.addTextureAtlas("spineboy", "spine/spineboy.atlas", libgdxx); 25 | await resourceManager.load(); 26 | 27 | // add TextField to show user information 28 | 29 | var textField = TextField(); 30 | textField.defaultTextFormat = TextFormat("Arial", 24, Color.White); 31 | textField.defaultTextFormat.align = TextFormatAlign.CENTER; 32 | textField.width = 480; 33 | textField.x = 0; 34 | textField.y = 550; 35 | textField.text = "tap to change animation"; 36 | textField.addTo(stage); 37 | 38 | // load Spine skeleton 39 | 40 | var spineJson = resourceManager.getTextFile("spineboy"); 41 | var textureAtlas = resourceManager.getTextureAtlas("spineboy"); 42 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 43 | var skeletonLoader = SkeletonLoader(attachmentLoader); 44 | var skeletonData = skeletonLoader.readSkeletonData(spineJson); 45 | 46 | // configure Spine animation mix 47 | 48 | var animationStateData = AnimationStateData(skeletonData); 49 | animationStateData.setMixByName("portal", "idle", 0.2); 50 | animationStateData.setMixByName("idle", "walk", 0.2); 51 | animationStateData.setMixByName("walk", "run", 0.2); 52 | animationStateData.setMixByName("run", "walk", 0.2); 53 | animationStateData.setMixByName("walk", "idle", 0.2); 54 | 55 | // create the display object showing the skeleton animation 56 | 57 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 58 | skeletonAnimation.x = 240; 59 | skeletonAnimation.y = 520; 60 | skeletonAnimation.scaleX = skeletonAnimation.scaleY = 0.7; 61 | skeletonAnimation.boundsCalculation = SkeletonBoundsCalculation.Hull; 62 | 63 | var mouseContainer = Sprite(); 64 | mouseContainer.addChild(skeletonAnimation); 65 | mouseContainer.mouseCursor = MouseCursor.CROSSHAIR; 66 | stage.juggler.add(skeletonAnimation); 67 | stage.addChild(mouseContainer); 68 | 69 | // register track events 70 | 71 | skeletonAnimation.state.onTrackStart.listen((TrackEntryStartEvent e) { 72 | print("${e.trackEntry.trackIndex} start: ${e.trackEntry}"); 73 | }); 74 | 75 | skeletonAnimation.state.onTrackEnd.listen((TrackEntryEndEvent e) { 76 | print("${e.trackEntry.trackIndex} end: ${e.trackEntry}"); 77 | }); 78 | 79 | skeletonAnimation.state.onTrackComplete.listen((TrackEntryCompleteEvent e) { 80 | print("${e.trackEntry.trackIndex} complete: ${e.trackEntry}"); 81 | }); 82 | 83 | skeletonAnimation.state.onTrackEvent.listen((TrackEntryEventEvent e) { 84 | var ev = e.event; 85 | var text = "${ev.data.name}: ${ev.intValue}, ${ev.floatValue}, ${ev.stringValue}"; 86 | print("${e.trackEntry.trackIndex} event: ${e.trackEntry}, $text"); 87 | }); 88 | 89 | // start with the "portal" animation continue with the "idle" animation 90 | 91 | var portalAnimation = skeletonAnimation.state.setAnimationByName(0, "portal", false); 92 | skeletonAnimation.state.addAnimationByName(0, "idle", true, portalAnimation.animation.duration); 93 | await portalAnimation.onTrackComplete.first; 94 | 95 | // change the animation on every mouse click 96 | 97 | var animationNames = ["idle", "idle", "walk", "run", "walk"]; 98 | var animationState = skeletonAnimation.state; 99 | var animationIndex = 0; 100 | 101 | stage.onMouseClick.listen((me) { 102 | animationIndex = (animationIndex + 1) % animationNames.length; 103 | if (animationIndex == 1) { 104 | animationState.setEmptyAnimation(1, 0.0); 105 | animationState.addAnimationByName(1, "shoot", false, 0.0).mixDuration = 0.2; 106 | animationState.addEmptyAnimation(1, 0.2, 0.5); 107 | } else { 108 | var animationName = animationNames[animationIndex]; 109 | animationState.setAnimationByName(0, animationName, true); 110 | } 111 | }); 112 | } 113 | -------------------------------------------------------------------------------- /lib/src/animation/scale_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class ScaleTimeline extends TranslateTimeline { 34 | static const int _ENTRIES = 3; 35 | static const int _PREV_TIME = -3; 36 | static const int _PREV_X = -2; 37 | static const int _PREV_Y = -1; 38 | static const int _TIME = 0; 39 | static const int _X = 1; 40 | static const int _Y = 2; 41 | 42 | ScaleTimeline(int frameCount) : super(frameCount); 43 | 44 | @override 45 | int getPropertyId() { 46 | return (TimelineType.scale.ordinal << 24) + boneIndex; 47 | } 48 | 49 | @override 50 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 51 | double alpha, MixPose pose, MixDirection direction) { 52 | Bone bone = skeleton.bones[boneIndex]; 53 | double x = 0.0; 54 | double y = 0.0; 55 | 56 | if (time < frames[0]) { 57 | // Time is before first frame. 58 | if (pose == MixPose.setup) { 59 | bone.scaleX = bone.data.scaleX; 60 | bone.scaleY = bone.data.scaleY; 61 | } else if (pose == MixPose.current) { 62 | bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; 63 | bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; 64 | } 65 | return; 66 | } 67 | 68 | if (time >= frames[frames.length + _PREV_TIME]) { 69 | // Time is after last frame. 70 | x = frames[frames.length + _PREV_X]; 71 | y = frames[frames.length + _PREV_Y]; 72 | } else { 73 | // Interpolate between the previous frame and the current frame. 74 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 75 | double t0 = frames[frame + _PREV_TIME]; 76 | double x0 = frames[frame + _PREV_X]; 77 | double y0 = frames[frame + _PREV_Y]; 78 | double t1 = frames[frame + _TIME]; 79 | double x1 = frames[frame + _X]; 80 | double y1 = frames[frame + _Y]; 81 | double between = 1.0 - (time - t1) / (t0 - t1); 82 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 83 | x = x0 + (x1 - x0) * percent; 84 | y = y0 + (y1 - y0) * percent; 85 | } 86 | 87 | if (alpha == 1.0) { 88 | bone.scaleX = x * bone.data.scaleX; 89 | bone.scaleY = y * bone.data.scaleY; 90 | } else { 91 | x = x * bone.data.scaleX; 92 | y = y * bone.data.scaleY; 93 | double bx = pose == MixPose.setup ? bone.data.scaleX : bone.scaleX; 94 | double by = pose == MixPose.setup ? bone.data.scaleY : bone.scaleY; 95 | double mx = direction == MixDirection.Out ? x.abs() * bx.sign : bx.abs() * x.sign; 96 | double my = direction == MixDirection.Out ? y.abs() * by.sign : by.abs() * y.sign; 97 | bone.scaleX = bx + (mx - bx) * alpha; 98 | bone.scaleY = by + (my - by) * alpha; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/src/animation/translate_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class TranslateTimeline extends CurveTimeline { 34 | static const int _ENTRIES = 3; 35 | static const int _PREV_TIME = -3; 36 | static const int _PREV_X = -2; 37 | static const int _PREV_Y = -1; 38 | static const int _TIME = 0; 39 | static const int _X = 1; 40 | static const int _Y = 2; 41 | 42 | final Float32List frames; // time, value, value, ... 43 | int boneIndex = 0; 44 | 45 | TranslateTimeline(int frameCount) 46 | : frames = Float32List(frameCount * 3), 47 | super(frameCount); 48 | 49 | @override 50 | int getPropertyId() { 51 | return (TimelineType.translate.ordinal << 24) + boneIndex; 52 | } 53 | 54 | /// Sets the time and value of the specified keyframe. 55 | 56 | void setFrame(int frameIndex, double time, double x, double y) { 57 | frameIndex *= 3; 58 | frames[frameIndex + 0] = time.toDouble(); 59 | frames[frameIndex + 1] = x.toDouble(); 60 | frames[frameIndex + 2] = y.toDouble(); 61 | } 62 | 63 | @override 64 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 65 | double alpha, MixPose pose, MixDirection direction) { 66 | Bone bone = skeleton.bones[boneIndex]; 67 | double x = 0.0; 68 | double y = 0.0; 69 | 70 | if (time < frames[0]) { 71 | // Time is before first frame. 72 | if (pose == MixPose.setup) { 73 | bone.x = bone.data.x; 74 | bone.y = bone.data.y; 75 | } else if (pose == MixPose.current) { 76 | bone.x += (bone.data.x - bone.x) * alpha; 77 | bone.y += (bone.data.y - bone.y) * alpha; 78 | } 79 | return; 80 | } 81 | 82 | if (time >= frames[frames.length + _PREV_TIME]) { 83 | // Time is after last frame. 84 | x = frames[frames.length + _PREV_X]; 85 | y = frames[frames.length + _PREV_Y]; 86 | } else { 87 | // Interpolate between the previous frame and the current frame. 88 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 89 | double t0 = frames[frame + _PREV_TIME]; 90 | double x0 = frames[frame + _PREV_X]; 91 | double y0 = frames[frame + _PREV_Y]; 92 | double t1 = frames[frame + _TIME]; 93 | double x1 = frames[frame + _X]; 94 | double y1 = frames[frame + _Y]; 95 | double between = 1.0 - (time - t1) / (t0 - t1); 96 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 97 | x = x0 + (x1 - x0) * percent; 98 | y = y0 + (y1 - y0) * percent; 99 | } 100 | 101 | if (pose == MixPose.setup) { 102 | bone.x = bone.data.x + x * alpha; 103 | bone.y = bone.data.y + y * alpha; 104 | } else { 105 | bone.x = bone.x + (bone.data.x - bone.x + x) * alpha; 106 | bone.y = bone.y + (bone.data.y - bone.y + y) * alpha; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/src/attachments/region_attachment.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class RegionAttachment extends RenderAttachment { 34 | double x = 0.0; 35 | double y = 0.0; 36 | double width = 0.0; 37 | double height = 0.0; 38 | double scaleX = 1.0; 39 | double scaleY = 1.0; 40 | double rotation = 0.0; 41 | 42 | final Matrix transformationMatrix = Matrix.fromIdentity(); 43 | 44 | RegionAttachment(String name, String path, BitmapData bitmapData) 45 | : super(name, path, bitmapData) { 46 | this.initRenderGeometry(); 47 | } 48 | 49 | //--------------------------------------------------------------------------- 50 | 51 | /// The update method will update the [transformationMatrix] based on the 52 | /// x, y, width, height, scaleX, scaleY and rotation fields. Therefore you 53 | /// have to call this method after you have changed one of those fields. 54 | 55 | void update() { 56 | num sw = scaleX * width; 57 | num sh = scaleY * height; 58 | num bw = bitmapData.width; 59 | num bh = bitmapData.height; 60 | num cosR = _cosDeg(rotation); 61 | num sinR = _sinDeg(rotation); 62 | 63 | num ma = cosR * sw / bw; 64 | num mb = sinR * sh / bh; 65 | num mc = sinR * sw / bw; 66 | num md = 0.0 - cosR * sh / bh; 67 | num mx = x - 0.5 * (sw * cosR + sh * sinR); 68 | num my = y - 0.5 * (sw * sinR - sh * cosR); 69 | transformationMatrix.setTo(ma, mc, mb, md, mx, my); 70 | 71 | Float32List vxList = bitmapData.renderTextureQuad.vxList; 72 | 73 | for (int o = 0; o <= vertices.length - 2; o += 2) { 74 | double x = vxList[o * 2 + 0]; 75 | double y = vxList[o * 2 + 1]; 76 | vertices[o + 0] = x * ma + y * mb + mx; 77 | vertices[o + 1] = x * mc + y * md + my; 78 | } 79 | } 80 | 81 | //--------------------------------------------------------------------------- 82 | 83 | @override 84 | void computeWorldVertices2( 85 | Slot slot, int start, int count, Float32List worldVertices, int offset, int stride) { 86 | var ma = slot.bone.a; 87 | var mb = slot.bone.b; 88 | var mc = slot.bone.c; 89 | var md = slot.bone.d; 90 | var mx = slot.bone.worldX; 91 | var my = slot.bone.worldY; 92 | var length = count >> 1; 93 | 94 | for (int i = 0; i < length; i++, start += 2, offset += stride) { 95 | double x = vertices[start + 0]; 96 | double y = vertices[start + 1]; 97 | worldVertices[offset + 0] = x * ma + y * mb + mx; 98 | worldVertices[offset + 1] = x * mc + y * md + my; 99 | } 100 | } 101 | 102 | @override 103 | void initRenderGeometry() { 104 | var renderTextureQuad = bitmapData.renderTextureQuad; 105 | this.ixList = Int16List.fromList(renderTextureQuad.ixList); 106 | this.vxList = Float32List.fromList(renderTextureQuad.vxList); 107 | this.worldVerticesLength = this.hullLength = vxList.length >> 1; 108 | this.vertices = Float32List(worldVerticesLength); 109 | this.update(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/src/animation/curve_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | /// Base class for frames that use an interpolation bezier curve. 34 | /// 35 | class CurveTimeline implements Timeline { 36 | static const double _LINEAR = 0.0; 37 | static const double _STEPPED = 1.0; 38 | static const double _BEZIER = 2.0; 39 | static const int _BEZIER_SIZE = 10 * 2 - 1; 40 | 41 | final Float32List _curves; // type, x, y, ... 42 | 43 | CurveTimeline(int frameCount) : _curves = Float32List((frameCount - 1) * _BEZIER_SIZE); 44 | 45 | @override 46 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 47 | double alpha, MixPose pose, MixDirection direction) {} 48 | 49 | @override 50 | int getPropertyId() => 0; 51 | 52 | int get frameCount => _curves.length ~/ _BEZIER_SIZE + 1; 53 | 54 | void setLinear(int frameIndex) { 55 | _curves[frameIndex * _BEZIER_SIZE] = _LINEAR; 56 | } 57 | 58 | void setStepped(int frameIndex) { 59 | _curves[frameIndex * _BEZIER_SIZE] = _STEPPED; 60 | } 61 | 62 | /// Sets the control handle positions for an interpolation bezier curve 63 | /// used to transition from this keyframe to the next. 64 | /// 65 | /// cx1 and cx2 are from 0 to 1, representing the percent of time between 66 | /// the two keyframes. cy1 and cy2 are the percent of the difference between 67 | /// the keyframe's values. 68 | 69 | void setCurve(int frameIndex, double cx1, double cy1, double cx2, double cy2) { 70 | double tmpx = (-cx1 * 2 + cx2) * 0.03; 71 | double tmpy = (-cy1 * 2 + cy2) * 0.03; 72 | double dddfx = ((cx1 - cx2) * 3 + 1) * 0.006; 73 | double dddfy = ((cy1 - cy2) * 3 + 1) * 0.006; 74 | double ddfx = tmpx * 2 + dddfx; 75 | double ddfy = tmpy * 2 + dddfy; 76 | double dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667; 77 | double dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667; 78 | 79 | int i = frameIndex * _BEZIER_SIZE; 80 | _curves[i++] = _BEZIER; 81 | 82 | double x = dfx; 83 | double y = dfy; 84 | 85 | for (int n = i + _BEZIER_SIZE - 1; i < n; i += 2) { 86 | _curves[i + 0] = x; 87 | _curves[i + 1] = y; 88 | dfx += ddfx; 89 | dfy += ddfy; 90 | ddfx += dddfx; 91 | ddfy += dddfy; 92 | x += dfx; 93 | y += dfy; 94 | } 95 | } 96 | 97 | double getCurvePercent(int frameIndex, double percent) { 98 | if (percent < 0.0) percent = 0.0; 99 | if (percent > 1.0) percent = 1.0; 100 | 101 | int i = frameIndex * _BEZIER_SIZE; 102 | double type = _curves[i]; 103 | if (type == _LINEAR) return percent; 104 | if (type == _STEPPED) return 0.0; 105 | i++; 106 | 107 | double x = 0.0; 108 | for (int start = i, n = i + _BEZIER_SIZE - 1; i < n; i += 2) { 109 | x = _curves[i]; 110 | if (x >= percent) { 111 | double prevX = (i == start) ? 0.0 : _curves[i - 2]; 112 | double prevY = (i == start) ? 0.0 : _curves[i - 1]; 113 | return prevY + (_curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); 114 | } 115 | } 116 | 117 | double y = _curves[i - 1]; 118 | return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /example/texture_atlas/example.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:html' as html; 3 | import 'package:stagexl/stagexl.dart'; 4 | import 'package:stagexl_spine/stagexl_spine.dart'; 5 | 6 | Future main() async { 7 | // configure StageXL default options 8 | 9 | StageXL.stageOptions.renderEngine = RenderEngine.WebGL; 10 | StageXL.stageOptions.backgroundColor = Color.Azure; 11 | 12 | // init Stage and RenderLoop 13 | 14 | var canvas = html.querySelector('#stage'); 15 | var stage = Stage(canvas, width: 800, height: 400); 16 | var renderLoop = RenderLoop(); 17 | renderLoop.addStage(stage); 18 | stage.console.visible = true; 19 | stage.console.alpha = 0.75; 20 | 21 | // load "raptor" skeleton resources 22 | 23 | var resourceManager = ResourceManager(); 24 | resourceManager.addTextureAtlas("combined", "atlas/combined.json"); 25 | resourceManager.addTextFile("goblins-spine", "spine/goblins.json"); 26 | resourceManager.addTextFile("goblins-atlas", "spine/goblins.atlas"); 27 | resourceManager.addTextFile("hero-spine", "spine/hero.json"); 28 | resourceManager.addTextFile("hero-atlas", "spine/hero.atlas"); 29 | resourceManager.addTextFile("raptor-spine", "spine/raptor.json"); 30 | resourceManager.addTextFile("raptor-atlas", "spine/raptor.atlas"); 31 | resourceManager.addTextFile("speedy-spine", "spine/speedy.json"); 32 | resourceManager.addTextFile("speedy-atlas", "spine/speedy.atlas"); 33 | resourceManager.addTextFile("spineboy-spine", "spine/spineboy.json"); 34 | resourceManager.addTextFile("spineboy-atlas", "spine/spineboy.atlas"); 35 | await resourceManager.load(); 36 | 37 | //--------------------------------------------------------------------------- 38 | // load Spine skeletons from combined texture and the individual definitions 39 | 40 | var names = ["goblins", "hero", "raptor", "speedy", "spineboy"]; 41 | var skeletonAnimations = List(); 42 | 43 | for (var name in names) { 44 | // get spine texture atlases from combined texture atlas 45 | 46 | var bitmapData = resourceManager.getTextureAtlas("combined").getBitmapData(name); 47 | var spine = resourceManager.getTextFile("$name-spine"); 48 | var atlas = resourceManager.getTextFile("$name-atlas"); 49 | var format = TextureAtlasFormat.LIBGDX; 50 | var textureAtlas = await TextureAtlas.fromBitmapData(bitmapData, atlas, format); 51 | 52 | // create spine skeleton data 53 | 54 | var attachmentLoader = TextureAtlasAttachmentLoader(textureAtlas); 55 | var skeletonLoader = SkeletonLoader(attachmentLoader); 56 | var skeletonData = skeletonLoader.readSkeletonData(spine); 57 | 58 | // create spine skeleton animation 59 | 60 | var animationStateData = AnimationStateData(skeletonData); 61 | var skeletonAnimation = SkeletonAnimation(skeletonData, animationStateData); 62 | skeletonAnimations.add(skeletonAnimation); 63 | } 64 | 65 | //--------------------------------------------------------------------------- 66 | // setup the skeleton animations 67 | 68 | skeletonAnimations[0] // goblins-mesh 69 | ..state.setAnimationByName(0, "walk", true) 70 | ..skeleton.skinName = "goblin" 71 | ..scaleX = 1.0 72 | ..scaleY = 1.0 73 | ..x = 150 74 | ..y = 320; 75 | 76 | skeletonAnimations[1] // hero-mesh 77 | ..state.setAnimationByName(0, "walk", true) 78 | ..scaleX = 0.7 79 | ..scaleY = 0.7 80 | ..x = 260 81 | ..y = 390; 82 | 83 | skeletonAnimations[2] // raptor 84 | ..state.setAnimationByName(0, "walk", true) 85 | ..scaleX = 0.28 86 | ..scaleY = 0.28 87 | ..x = 380 88 | ..y = 320; 89 | 90 | skeletonAnimations[3] // speedy 91 | ..state.setAnimationByName(0, "run", true) 92 | ..scaleX = 0.65 93 | ..scaleY = 0.65 94 | ..x = 550 95 | ..y = 390; 96 | 97 | skeletonAnimations[4] // spineboy 98 | ..state.setAnimationByName(0, "hoverboard", true) 99 | ..scaleX = 0.32 100 | ..scaleY = 0.32 101 | ..x = 660 102 | ..y = 320; 103 | 104 | // add the skeleton animations to the Stage and the Juggler 105 | 106 | stage.addChild(skeletonAnimations[0]); 107 | stage.addChild(skeletonAnimations[2]); 108 | stage.addChild(skeletonAnimations[4]); 109 | stage.addChild(skeletonAnimations[1]); 110 | stage.addChild(skeletonAnimations[3]); 111 | 112 | stage.juggler.add(skeletonAnimations[0]); 113 | stage.juggler.add(skeletonAnimations[1]); 114 | stage.juggler.add(skeletonAnimations[2]); 115 | stage.juggler.add(skeletonAnimations[3]); 116 | stage.juggler.add(skeletonAnimations[4]); 117 | /* 118 | var shape = new Shape(); 119 | shape.addTo(stage); 120 | shape.onExitFrame.listen((e) { 121 | var animation = skeletonAnimations[4]; 122 | animation.boundsCalculation = SkeletonBoundsCalculation.Hull; 123 | var r = animation.bounds; 124 | shape.x = animation.x; 125 | shape.y = animation.y; 126 | shape.scaleX = animation.scaleX; 127 | shape.scaleY = animation.scaleY; 128 | shape.graphics.clear(); 129 | shape.graphics.rect(r.left, r.top, r.width, r.height); 130 | shape.graphics.strokeColor(Color.Red, 2.0); 131 | });*/ 132 | } 133 | -------------------------------------------------------------------------------- /lib/src/animation/ik_constraint_timeline.dart: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License v2.5 3 | * 4 | * Copyright (c) 2013-2016, Esoteric Software 5 | * All rights reserved. 6 | * 7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and 8 | * non-transferable license to use, install, execute, and perform the Spine 9 | * Runtimes software and derivative works solely for personal or internal 10 | * use. Without the written permission of Esoteric Software (see Section 2 of 11 | * the Spine Software License Agreement), you may not (a) modify, translate, 12 | * adapt, or develop new applications using the Spine Runtimes or otherwise 13 | * create derivative works or improvements of the Spine Runtimes or (b) remove, 14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent, 15 | * or other intellectual property or proprietary rights notices on or in the 16 | * Software, including any copy thereof. Redistributions in binary or source 17 | * form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF 25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | part of stagexl_spine; 32 | 33 | class IkConstraintTimeline extends CurveTimeline { 34 | static const int _ENTRIES = 3; 35 | static const int _PREV_TIME = -3; 36 | static const int _PREV_MIX = -2; 37 | static const int _PREV_BEND_DIRECTION = -1; 38 | static const int _TIME = 0; 39 | static const int _MIX = 1; 40 | static const int _BEND_DIRECTION = 2; 41 | 42 | final Float32List frames; // time, mix, bendDirection, ... 43 | int ikConstraintIndex = 0; 44 | 45 | IkConstraintTimeline(int frameCount) 46 | : frames = Float32List(frameCount * _ENTRIES), 47 | super(frameCount); 48 | 49 | @override 50 | int getPropertyId() { 51 | return (TimelineType.ikConstraint.ordinal << 24) + ikConstraintIndex; 52 | } 53 | 54 | /// Sets the time, mix and bend direction of the specified keyframe. 55 | 56 | void setFrame(int frameIndex, double time, double mix, int bendDirection) { 57 | frameIndex *= _ENTRIES; 58 | frames[frameIndex + _TIME] = time; 59 | frames[frameIndex + _MIX] = mix; 60 | frames[frameIndex + _BEND_DIRECTION] = bendDirection.toDouble(); 61 | } 62 | 63 | @override 64 | void apply(Skeleton skeleton, double lastTime, double time, List firedEvents, 65 | double alpha, MixPose pose, MixDirection direction) { 66 | IkConstraint constraint = skeleton.ikConstraints[ikConstraintIndex]; 67 | IkConstraintData data = constraint.data; 68 | double m = 0.0; 69 | double b = 0.0; 70 | 71 | if (time < frames[0]) { 72 | // Time is before first frame. 73 | if (pose == MixPose.setup) { 74 | constraint.mix = data.mix; 75 | constraint.bendDirection = data.bendDirection; 76 | } else if (pose == MixPose.current) { 77 | constraint.mix += (constraint.data.mix - constraint.mix) * alpha; 78 | constraint.bendDirection = constraint.data.bendDirection; 79 | } 80 | return; 81 | } 82 | 83 | if (time >= frames[frames.length + _PREV_TIME]) { 84 | // Time is after last frame. 85 | m = frames[frames.length + _PREV_MIX]; 86 | b = frames[frames.length + _PREV_BEND_DIRECTION]; 87 | } else { 88 | // Interpolate between the previous frame and the current frame. 89 | int frame = Animation.binarySearch(frames, time, _ENTRIES); 90 | double t0 = frames[frame + _PREV_TIME]; 91 | double m0 = frames[frame + _PREV_MIX]; 92 | double b0 = frames[frame + _PREV_BEND_DIRECTION]; 93 | double t1 = frames[frame + _TIME]; 94 | double m1 = frames[frame + _MIX]; 95 | double between = 1.0 - (time - t1) / (t0 - t1); 96 | double percent = getCurvePercent(frame ~/ _ENTRIES - 1, between); 97 | m = m0 + (m1 - m0) * percent; 98 | b = b0; 99 | } 100 | 101 | if (pose == MixPose.setup) { 102 | constraint.mix = data.mix + (m - data.mix) * alpha; 103 | constraint.bendDirection = direction == MixDirection.Out ? data.bendDirection : b.toInt(); 104 | } else { 105 | constraint.mix = constraint.mix + (m - constraint.mix) * alpha; 106 | if (direction == MixDirection.In) constraint.bendDirection = b.toInt(); 107 | } 108 | } 109 | } 110 | --------------------------------------------------------------------------------