1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Bevy 0.19 plugin for [`spine_runtime`]: load, animate and draw Spine 4.3
//! skeletons.
//!
//! Add [`SpinePlugin`], load a `.skel` or `.json` export as a
//! [`SpineSkeletonAsset`], and spawn a [`SpineSkeleton`] with it. The plugin
//! builds the runtime state once the asset loads, advances it every frame,
//! and draws it as child mesh entities.
//!
//! # Quick start (2D)
//!
//! ```no_run
//! use bevy::prelude::*;
//! use spine_bevy::{SpinePlugin, SpineSkeleton, SpineSkeletonAsset, SpineSkeletonLoaderSettings};
//!
//! fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
//! commands.spawn(Camera2d);
//! let skel: Handle<SpineSkeletonAsset> = asset_server
//! .load_builder()
//! .with_settings(|s: &mut SpineSkeletonLoaderSettings| {
//! s.atlas_path = Some("spineboy/export/spineboy-pma.atlas".into());
//! })
//! .load("spineboy/export/spineboy-pro.skel");
//! commands.spawn(SpineSkeleton::new(skel).with_initial_animation(0, "walk", true));
//! }
//!
//! App::new()
//! .add_plugins(DefaultPlugins)
//! .add_plugins(SpinePlugin)
//! .add_systems(Startup, setup)
//! .run();
//! ```
//!
//! # Quick start (3D)
//!
//! Spawn a [`SpineRender3d`] marker alongside the [`SpineSkeleton`] and use a
//! `Camera3d`. The rig is laid out in the entity's local XY plane (z = 0),
//! y-up and facing +Z, so it stands upright with an identity rotation. Spine
//! units are usually pixels; scale the `Transform` down to scene units. See
//! `examples/spineboy_walk_3d.rs`.
//!
//! # Controlling playback
//!
//! [`SpineSkeleton::play`], [`SpineSkeleton::set_skin`], and the
//! [`time_scale`](SpineSkeleton::time_scale), [`paused`](SpineSkeleton::paused)
//! and [`physics`](SpineSkeleton::physics) fields cover the common cases. Calls
//! made before the asset loads are queued. For queueing, mixing and track
//! entries, use [`SpineSkeleton::animation_state_mut`]; for bones and slots,
//! [`SpineSkeleton::skeleton_mut`]. Both return `None` until the asset loads.
//!
//! Animation events arrive as messages. [`SpineKeyframeEvent`] carries
//! keyframe events only; [`SpineStateEvent`] carries those plus track-entry
//! lifecycle events (start, interrupt, end, complete, dispose).
//!
//! ```no_run
//! use bevy::prelude::*;
//! use spine_bevy::{SpineKeyframeEvent, SpineSkeleton};
//!
//! fn log_events(mut events: MessageReader<SpineKeyframeEvent>, skeletons: Query<&SpineSkeleton>) {
//! for ev in events.read() {
//! let Some(skeleton) = skeletons.get(ev.entity).ok().and_then(|s| s.skeleton()) else {
//! continue;
//! };
//! let name = &skeleton.data().events[ev.event.data.index()].name;
//! info!("{name} at {}s", ev.event.time);
//! }
//! }
//! ```
//!
//! # How it fits together
//!
//! [`SpinePlugin`] registers the asset loaders, the [`SpineMaterial`]
//! (`Material2d`) and [`SpineMaterial3d`] (`Material`) plugins, the two event
//! messages, and five chained system sets in `Update`:
//!
//! 1. [`SpineSet::EnsureMarkers`]: inserts [`SpineRender2d`] on skeletons
//! that carry no render-mode marker.
//! 2. [`SpineSet::Init`]: builds runtime state for skeletons whose asset
//! has loaded.
//! 3. [`SpineSet::Tick`]: advances and applies animations, updates world
//! transforms, and renders each skeleton's `RenderCommand` list. Runs in
//! parallel over skeletons.
//! 4. [`SpineSet::BuildMeshes`]: writes those commands into child mesh
//! entities with a [`SpineMaterial`] or [`SpineMaterial3d`], depending on
//! the render-mode marker.
//! 5. [`SpineSet::Events`]: forwards lifecycle and keyframe events as
//! [`SpineStateEvent`] and [`SpineKeyframeEvent`] messages.
//!
//! Systems ordered `.before(SpineSet::Tick)` can change `time_scale` or
//! queue animations and see the result the same frame. Systems that read
//! bone positions should run `.after(SpineSet::Tick)`.
//!
//! # Atlas expectations
//!
//! The materials assume premultiplied-alpha textures. Spine exports usually
//! include a `*-pma.atlas` / `*-pma.png` pair beside the straight-alpha one.
//! The loaders derive `spineboy.atlas` from `spineboy-pro.skel`, which in
//! Spine's examples is the straight-alpha atlas; set
//! [`SpineSkeletonLoaderSettings::atlas_path`] to the PMA variant.
use AssetApp;
use MaterialPlugin;
use *;
use Material2dPlugin;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Registers Spine assets, loaders, materials, messages and systems. Add
/// once, then spawn [`SpineSkeleton`] components.
;