pulse_pixelstream_types/
shot.rs1use myko::prelude::*;
2use myko::TS;
3use serde::{Deserialize, Serialize};
4
5use crate::ShotEntryMode;
6
7pub const DEFAULT_SHOT_LIBRARY_ID: &str = "shared";
9pub const DEFAULT_SHOT_TRANSLATION_SPEED_CM_S: f32 = 10.0;
10pub const DEFAULT_SHOT_ROTATION_SPEED_DEG_S: f32 = 2.0;
11pub const DEFAULT_SHOT_HOLD_DURATION_MS: u64 = 5_000;
12pub const DEFAULT_SHOT_TRAVEL_DURATION_MS: u64 = 30_000;
17
18pub fn default_shot_travel_duration_ms() -> u64 {
19 DEFAULT_SHOT_TRAVEL_DURATION_MS
20}
21
22#[derive(
23 Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, TS, PartialOrd, Ord, Hash,
24)]
25#[serde(rename_all = "snake_case")]
26pub enum ShotKind {
27 #[serde(alias = "rig", alias = "rig_move", alias = "moving")]
28 Moving,
29 #[default]
30 #[serde(alias = "preset", alias = "preset_hold", alias = "stationary")]
31 Static,
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TS)]
38#[serde(rename_all = "camelCase")]
39pub struct ShotDiscovery {
40 pub name: String,
41 pub kind: ShotKind,
42 pub target_name: String,
43}
44
45#[myko_macros::myko_item]
49pub struct Shot {
50 #[serde(default)]
53 pub library_id: String,
54 #[serde(default)]
57 pub streamer_id: String,
58 pub name: String,
59 #[serde(alias = "target_kind")]
60 pub kind: ShotKind,
61 pub target_name: String,
62 pub translation_speed_cm_s: f32,
63 pub rotation_speed_deg_s: f32,
64 pub hold_duration_ms: u64,
65 #[serde(default)]
66 pub travel_duration_ms: u64,
67 #[serde(
70 default,
71 alias = "defaultClipMode",
72 alias = "defaultListMode",
73 alias = "batchMode"
74 )]
75 pub default_entry_mode: ShotEntryMode,
76 #[serde(rename = "sortOrder", alias = "shotIndex")]
79 pub shot_index: u32,
80}
81
82impl Shot {
83 pub fn stable_id(library_id: &str, kind: &ShotKind, target_name: &str) -> String {
84 let kind = match kind {
85 ShotKind::Moving => "moving",
86 ShotKind::Static => "static",
87 };
88 format!("{library_id}:shot:{kind}:{target_name}")
89 }
90
91 pub fn effective_library_id(&self) -> &str {
92 effective_library_id(&self.library_id)
93 }
94
95 pub fn effective_travel_duration_ms(&self) -> u64 {
96 if self.travel_duration_ms == 0 {
97 DEFAULT_SHOT_TRAVEL_DURATION_MS
98 } else {
99 self.travel_duration_ms
100 }
101 }
102}
103
104pub fn effective_library_id(library_id: &str) -> &str {
105 if library_id.trim().is_empty() {
106 DEFAULT_SHOT_LIBRARY_ID
107 } else {
108 library_id
109 }
110}