1#![allow(dead_code)]
2
3use std::collections::HashMap;
4use std::fmt;
5
6use crate::nodes::node::InoxNodeUuid;
7use crate::nodes::node_data::InoxData;
8use crate::nodes::node_tree::InoxNodeTree;
9use crate::params::{Param, ParamUuid};
10use crate::render::RenderCtx;
11
12#[derive(Clone, Copy, Debug, Default)]
14pub enum PuppetAllowedUsers {
15 #[default]
17 OnlyAuthor,
18 OnlyLicensee,
20 Everyone,
22}
23
24impl fmt::Display for PuppetAllowedUsers {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
26 write!(
27 f,
28 "{}",
29 match self {
30 PuppetAllowedUsers::OnlyAuthor => "only author",
31 PuppetAllowedUsers::OnlyLicensee => "only licensee",
32 PuppetAllowedUsers::Everyone => "Everyone",
33 }
34 )
35 }
36}
37
38#[derive(Debug, Clone, thiserror::Error)]
39#[error("Unknown allowed users {0:?}")]
40pub struct UnknownPuppetAllowedUsersError(String);
41
42impl TryFrom<&str> for PuppetAllowedUsers {
43 type Error = UnknownPuppetAllowedUsersError;
44
45 fn try_from(value: &str) -> Result<Self, Self::Error> {
46 match value {
47 "OnlyAuthor" => Ok(PuppetAllowedUsers::OnlyAuthor),
48 "OnlyLicensee" => Ok(PuppetAllowedUsers::OnlyLicensee),
49 "Everyone" => Ok(PuppetAllowedUsers::Everyone),
50 unknown => Err(UnknownPuppetAllowedUsersError(unknown.to_owned())),
51 }
52 }
53}
54
55#[derive(Clone, Copy, Debug, Default)]
57pub enum PuppetAllowedRedistribution {
58 #[default]
60 Prohibited,
61 ViralLicense,
64 CopyleftLicense,
69}
70
71impl fmt::Display for PuppetAllowedRedistribution {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
73 write!(
74 f,
75 "{}",
76 match self {
77 PuppetAllowedRedistribution::Prohibited => "prohibited",
78 PuppetAllowedRedistribution::ViralLicense => "viral license",
79 PuppetAllowedRedistribution::CopyleftLicense => "copyleft license",
80 }
81 )
82 }
83}
84
85#[derive(Debug, Clone, thiserror::Error)]
86#[error("Unknown allowed redistribution {0:?}")]
87pub struct UnknownPuppetAllowedRedistributionError(String);
88
89impl TryFrom<&str> for PuppetAllowedRedistribution {
90 type Error = UnknownPuppetAllowedRedistributionError;
91
92 fn try_from(value: &str) -> Result<Self, Self::Error> {
93 match value {
94 "Prohibited" => Ok(PuppetAllowedRedistribution::Prohibited),
95 "ViralLicense" => Ok(PuppetAllowedRedistribution::ViralLicense),
96 "CopyleftLicense" => Ok(PuppetAllowedRedistribution::CopyleftLicense),
97 unknown => Err(UnknownPuppetAllowedRedistributionError(unknown.to_owned())),
98 }
99 }
100}
101
102#[derive(Clone, Copy, Debug, Default)]
104pub enum PuppetAllowedModification {
105 #[default]
107 Prohibited,
108 AllowPersonal,
110 AllowRedistribute,
113}
114
115impl fmt::Display for PuppetAllowedModification {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
117 write!(
118 f,
119 "{}",
120 match self {
121 PuppetAllowedModification::Prohibited => "prohibited",
122 PuppetAllowedModification::AllowPersonal => "allow personal",
123 PuppetAllowedModification::AllowRedistribute => "allow redistribute",
124 }
125 )
126 }
127}
128
129#[derive(Debug, Clone, thiserror::Error)]
130#[error("Unknown allowed users {0:?}")]
131pub struct UnknownPuppetAllowedModificationError(String);
132
133impl TryFrom<&str> for PuppetAllowedModification {
134 type Error = UnknownPuppetAllowedModificationError;
135
136 fn try_from(value: &str) -> Result<Self, Self::Error> {
137 match value {
138 "Prohibited" => Ok(PuppetAllowedModification::Prohibited),
139 "AllowPersonal" => Ok(PuppetAllowedModification::AllowPersonal),
140 "AllowRedistribute" => Ok(PuppetAllowedModification::AllowRedistribute),
141 unknown => Err(UnknownPuppetAllowedModificationError(unknown.to_owned())),
142 }
143 }
144}
145
146#[derive(Clone, Debug, Default)]
148pub struct PuppetUsageRights {
149 pub allowed_users: PuppetAllowedUsers,
151 pub allow_violence: bool,
153 pub allow_sexual: bool,
155 pub allow_commercial: bool,
157 pub allow_redistribution: PuppetAllowedRedistribution,
159 pub allow_modification: PuppetAllowedModification,
161 pub require_attribution: bool,
163}
164
165fn allowed_bool(value: bool) -> &'static str {
166 if value {
167 "allowed"
168 } else {
169 "prohibited"
170 }
171}
172
173impl fmt::Display for PuppetUsageRights {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
175 writeln!(f, "| allowed users: {}", self.allowed_users)?;
176 writeln!(f, "| violence: {}", allowed_bool(self.allow_violence))?;
177 writeln!(f, "| sexual: {}", allowed_bool(self.allow_sexual))?;
178 writeln!(f, "| commercial: {}", allowed_bool(self.allow_commercial))?;
179 writeln!(f, "| redistribution: {}", self.allow_redistribution)?;
180 writeln!(f, "| modification: {}", self.allow_modification)?;
181 writeln!(
182 f,
183 "| attribution: {}",
184 if self.require_attribution {
185 "required"
186 } else {
187 "not required"
188 }
189 )
190 }
191}
192
193#[derive(Clone, Debug)]
195pub struct PuppetMeta {
196 pub name: Option<String>,
198 pub version: String,
200 pub rigger: Option<String>,
202 pub artist: Option<String>,
204 pub rights: Option<PuppetUsageRights>,
206 pub copyright: Option<String>,
208 pub license_url: Option<String>,
210 pub contact: Option<String>,
212 pub reference: Option<String>,
214 pub thumbnail_id: Option<u32>,
216 pub preserve_pixels: bool,
219}
220
221fn writeln_opt<T: fmt::Display>(f: &mut fmt::Formatter<'_>, field_name: &str, opt: &Option<T>) -> fmt::Result {
222 let field_name = format!("{:<17}", format!("{field_name}:"));
223 if let Some(ref value) = opt {
224 #[cfg(feature = "owo")]
225 let value = {
226 use owo_colors::OwoColorize;
227 value.green()
228 };
229 writeln!(f, "{field_name}{value}")?;
230 }
231 Ok(())
232}
233
234impl fmt::Display for PuppetMeta {
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 match self.name {
237 Some(ref name) => writeln_opt(f, "Name", &Some(name))?,
238 None => {
239 let no_name = "(No Name)";
240 #[cfg(feature = "owo")]
241 let no_name = {
242 use owo_colors::OwoColorize;
243 no_name.dimmed()
244 };
245 writeln!(f, "{no_name}")?
246 }
247 }
248
249 writeln_opt(f, "Version", &Some(&self.version))?;
250 writeln_opt(f, "Rigger", &self.rigger)?;
251 writeln_opt(f, "Artist", &self.artist)?;
252
253 if let Some(ref rights) = self.rights {
254 writeln!(f, "Rights:")?;
255 #[cfg(feature = "owo")]
256 let rights = {
257 use owo_colors::OwoColorize;
258 rights.yellow()
259 };
260 writeln!(f, "{rights}")?;
261 }
262
263 writeln_opt(f, "Copyright", &self.copyright)?;
264 writeln_opt(f, "License URL", &self.license_url)?;
265 writeln_opt(f, "Contact", &self.contact)?;
266 writeln_opt(f, "Reference", &self.reference)?;
267 writeln_opt(f, "Thumbnail ID", &self.thumbnail_id)?;
268
269 writeln_opt(
270 f,
271 "Preserve pixels",
272 &Some(if self.preserve_pixels { "yes" } else { "no" }),
273 )
274 }
275}
276
277impl Default for PuppetMeta {
278 fn default() -> Self {
279 Self {
280 name: Default::default(),
281 version: crate::INOCHI2D_SPEC_VERSION.to_owned(),
282 rigger: Default::default(),
283 artist: Default::default(),
284 rights: Default::default(),
285 copyright: Default::default(),
286 license_url: Default::default(),
287 contact: Default::default(),
288 reference: Default::default(),
289 thumbnail_id: Default::default(),
290 preserve_pixels: Default::default(),
291 }
292 }
293}
294
295#[derive(Clone, Copy, Debug)]
297pub struct PuppetPhysics {
298 pub pixels_per_meter: f32,
299 pub gravity: f32,
300}
301
302#[derive(Clone, Debug)]
304pub struct Puppet<T = ()> {
305 pub meta: PuppetMeta,
306 pub physics: PuppetPhysics,
307 pub nodes: InoxNodeTree<T>,
308 pub drivers: Vec<InoxNodeUuid>,
309 pub(crate) params: HashMap<ParamUuid, Param>,
310 pub(crate) param_names: HashMap<String, ParamUuid>,
311 pub render_ctx: RenderCtx,
312}
313
314impl<T> Puppet<T> {
315 pub fn new(
316 meta: PuppetMeta,
317 physics: PuppetPhysics,
318 nodes: InoxNodeTree<T>,
319 named_params: HashMap<String, Param>,
320 ) -> Self {
321 let render_ctx = RenderCtx::new(&nodes);
322
323 let drivers = (nodes.arena.iter())
324 .filter_map(|node| {
325 let node = node.get();
326
327 match node.data {
328 InoxData::SimplePhysics(_) => Some(node.uuid),
329 _ => None,
330 }
331 })
332 .collect::<Vec<_>>();
333
334 let mut params = HashMap::new();
335 let mut param_names = HashMap::new();
336 for (name, param) in named_params {
337 param_names.insert(name, param.uuid);
338 params.insert(param.uuid, param);
339 }
340
341 Self {
342 meta,
343 physics,
344 nodes,
345 drivers,
346 params,
347 param_names,
348 render_ctx,
349 }
350 }
351}