use crate::data::{AttachmentId, AttachmentRef, BoneId, SlotData, SlotId};
use crate::math::Color;
use crate::skeleton::pose::{Pose, Posed};
#[derive(Debug, Clone, PartialEq)]
pub struct SlotPose {
pub color: Color,
pub dark_color: Color,
pub has_dark_color: bool,
pub attachment: Option<AttachmentRef>,
pub timeline_attachment: Option<AttachmentId>,
pub sequence_index: i32,
pub deform: Vec<f32>,
}
impl Default for SlotPose {
fn default() -> Self {
Self {
color: Color::WHITE,
dark_color: Color::new(0.0, 0.0, 0.0, 0.0),
has_dark_color: false,
attachment: None,
timeline_attachment: None,
sequence_index: 0,
deform: Vec::new(),
}
}
}
impl Pose for SlotPose {
fn set_from(&mut self, other: &Self) {
self.color = other.color;
if other.has_dark_color {
self.dark_color = other.dark_color;
}
self.has_dark_color = other.has_dark_color;
self.attachment = other.attachment;
self.timeline_attachment = other.timeline_attachment;
self.sequence_index = other.sequence_index;
self.deform.clone_from(&other.deform);
}
}
impl SlotPose {
pub fn set_attachment(
&mut self,
attachment: Option<AttachmentRef>,
timeline: Option<AttachmentId>,
) {
if self.attachment == attachment {
return;
}
self.replace_attachment(attachment, timeline);
}
pub(crate) fn replace_attachment(
&mut self,
attachment: Option<AttachmentRef>,
timeline: Option<AttachmentId>,
) {
if attachment.is_none() || timeline.is_none() || timeline != self.timeline_attachment {
self.deform.clear();
}
self.attachment = attachment;
self.timeline_attachment = timeline;
self.sequence_index = -1;
}
}
#[derive(Debug, Clone)]
pub struct Slot {
pub data: SlotId,
pub bone: BoneId,
pub posed: Posed<SlotPose>,
pub(crate) attachment_state: i32,
}
impl Slot {
#[must_use]
pub fn new(data: &SlotData) -> Self {
let pose = SlotPose {
has_dark_color: data.dark_color.is_some(),
..SlotPose::default()
};
Self {
data: data.index,
bone: data.bone,
posed: Posed::new(pose.clone(), pose),
attachment_state: 0,
}
}
#[inline]
#[must_use]
pub fn applied(&self) -> &SlotPose {
self.posed.applied()
}
pub fn setup_pose(
&mut self,
data: &SlotData,
attachment: Option<AttachmentRef>,
timeline: Option<AttachmentId>,
) {
let pose = &mut self.posed.pose;
pose.color = data.color;
if pose.has_dark_color
&& let Some(dark) = data.dark_color
{
pose.dark_color = dark;
}
pose.sequence_index = 0;
if data.attachment_name.is_none() {
pose.set_attachment(None, None);
} else {
pose.attachment = None;
pose.set_attachment(attachment, timeline);
}
}
}
#[derive(Debug, Clone, Default)]
pub struct DrawOrder {
pub pose: Vec<SlotId>,
pub constrained: Vec<SlotId>,
is_constrained: bool,
}
impl DrawOrder {
#[must_use]
pub fn applied(&self) -> &[SlotId] {
if self.is_constrained {
&self.constrained
} else {
&self.pose
}
}
pub fn select_mut(&mut self, applied: bool) -> &mut Vec<SlotId> {
if applied && self.is_constrained {
&mut self.constrained
} else {
&mut self.pose
}
}
pub fn setup_pose(&mut self, slot_count: usize) {
self.pose.clear();
self.pose.extend((0..slot_count).map(|i| SlotId(i as u16)));
}
pub(crate) fn constrain(&mut self) {
self.is_constrained = true;
}
pub(crate) fn unconstrain(&mut self) {
self.is_constrained = false;
}
#[must_use]
pub fn is_constrained(&self) -> bool {
self.is_constrained
}
pub(crate) fn reset(&mut self) {
self.constrained.clone_from(&self.pose);
}
}