use myko::prelude::*;
use myko::TS;
use serde::{Deserialize, Serialize};
use crate::ShotEntryMode;
pub const DEFAULT_SHOT_LIBRARY_ID: &str = "shared";
pub const DEFAULT_SHOT_TRANSLATION_SPEED_CM_S: f32 = 10.0;
pub const DEFAULT_SHOT_ROTATION_SPEED_DEG_S: f32 = 2.0;
pub const DEFAULT_SHOT_HOLD_DURATION_MS: u64 = 5_000;
pub const DEFAULT_SHOT_TRAVEL_DURATION_MS: u64 = 30_000;
pub fn default_shot_travel_duration_ms() -> u64 {
DEFAULT_SHOT_TRAVEL_DURATION_MS
}
#[derive(
Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, TS, PartialOrd, Ord, Hash,
)]
#[serde(rename_all = "snake_case")]
pub enum ShotKind {
#[serde(alias = "rig", alias = "rig_move", alias = "moving")]
Moving,
#[default]
#[serde(alias = "preset", alias = "preset_hold", alias = "stationary")]
Static,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
pub struct ShotDiscovery {
pub name: String,
pub kind: ShotKind,
pub target_name: String,
}
#[myko_macros::myko_item]
pub struct Shot {
#[serde(default)]
pub library_id: String,
#[serde(default)]
pub streamer_id: String,
pub name: String,
#[serde(alias = "target_kind")]
pub kind: ShotKind,
pub target_name: String,
pub translation_speed_cm_s: f32,
pub rotation_speed_deg_s: f32,
pub hold_duration_ms: u64,
#[serde(default)]
pub travel_duration_ms: u64,
#[serde(
default,
alias = "defaultClipMode",
alias = "defaultListMode",
alias = "batchMode"
)]
pub default_entry_mode: ShotEntryMode,
#[serde(rename = "sortOrder", alias = "shotIndex")]
pub shot_index: u32,
}
impl Shot {
pub fn stable_id(library_id: &str, kind: &ShotKind, target_name: &str) -> String {
let kind = match kind {
ShotKind::Moving => "moving",
ShotKind::Static => "static",
};
format!("{library_id}:shot:{kind}:{target_name}")
}
pub fn effective_library_id(&self) -> &str {
effective_library_id(&self.library_id)
}
pub fn effective_travel_duration_ms(&self) -> u64 {
if self.travel_duration_ms == 0 {
DEFAULT_SHOT_TRAVEL_DURATION_MS
} else {
self.travel_duration_ms
}
}
}
pub fn effective_library_id(library_id: &str) -> &str {
if library_id.trim().is_empty() {
DEFAULT_SHOT_LIBRARY_ID
} else {
library_id
}
}