use std::collections::BTreeMap;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::ids::{
ArticulationId, BodyId, ColliderId, OccurrenceId, PhysicalMaterialId, PhysicsSceneId,
ProductDefinitionId, SolverSettingsId,
};
use crate::products::JointId;
use crate::scalar::FiniteReal;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
pub enum SolverTarget {
Scene {
scene: PhysicsSceneId,
},
Occurrence {
occurrence: OccurrenceId,
},
Definition {
definition: ProductDefinitionId,
},
Body {
body: BodyId,
},
Collider {
collider: ColliderId,
},
Joint {
joint: JointId,
},
PhysicalMaterial {
material: PhysicalMaterialId,
},
Articulation {
articulation: ArticulationId,
},
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct Dimension {
#[serde(default)]
pub length: i8,
#[serde(default)]
pub mass: i8,
#[serde(default)]
pub angle: i8,
}
impl Dimension {
pub const NONE: Self = Self {
length: 0,
mass: 0,
angle: 0,
};
#[must_use]
pub const fn new(length: i8, mass: i8, angle: i8) -> Self {
Self {
length,
mass,
angle,
}
}
#[must_use]
pub fn is_none(&self) -> bool {
*self == Self::NONE
}
#[must_use]
pub fn factor(&self, millimetres: f64, kilograms: f64, radians: f64) -> f64 {
millimetres.powi(i32::from(self.length))
* kilograms.powi(i32::from(self.mass))
* radians.powi(i32::from(self.angle))
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
pub enum SolverValue {
Bool {
value: bool,
},
Integer {
value: i64,
},
Real {
value: FiniteReal,
#[serde(default, skip_serializing_if = "Dimension::is_none")]
dimension: Dimension,
},
Unbounded {
negative: bool,
},
Reals {
values: Vec<FiniteReal>,
#[serde(default, skip_serializing_if = "Dimension::is_none")]
dimension: Dimension,
},
Token {
value: String,
},
Tokens {
values: Vec<String>,
},
Targets {
targets: Vec<SolverTarget>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct SolverSettings {
pub id: SolverSettingsId,
pub solver: String,
pub schema: String,
pub target: SolverTarget,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub values: BTreeMap<String, SolverValue>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_native_ref"
)]
pub native_ref: Option<String>,
}
cadmpeg_core::named_optional_field!(deserialize_native_ref, String, "native_ref");
mod identity_rewrite;
#[cfg(test)]
mod tests;