1use core::fmt;
2
3macro_rules! id_type {
4 ($name:ident, $doc:literal) => {
5 #[doc = $doc]
6 #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
7 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8 pub struct $name(u64);
9
10 impl $name {
11 #[inline]
13 pub const fn new(value: u64) -> Self {
14 Self(value)
15 }
16
17 #[inline]
19 pub const fn get(self) -> u64 {
20 self.0
21 }
22
23 #[inline]
25 pub const fn is_null(self) -> bool {
26 self.0 == 0
27 }
28 }
29
30 impl fmt::Debug for $name {
31 #[inline]
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{}({})", stringify!($name), self.0)
34 }
35 }
36
37 impl From<u64> for $name {
38 #[inline]
39 fn from(value: u64) -> Self {
40 Self::new(value)
41 }
42 }
43
44 impl From<$name> for u64 {
45 #[inline]
46 fn from(value: $name) -> Self {
47 value.get()
48 }
49 }
50 };
51}
52
53id_type!(NodeId, "Typed identifier for a scene node.");
54id_type!(MeshId, "Typed identifier for a mesh resource.");
55id_type!(MaterialId, "Typed identifier for a material resource.");
56id_type!(TextureId, "Typed identifier for a texture resource.");
57id_type!(LightId, "Typed identifier for a light resource.");
58id_type!(CameraId, "Typed identifier for a camera resource.");
59id_type!(AssetId, "Typed identifier for an imported asset package.");
60id_type!(SkinId, "Typed identifier for imported skinning metadata.");
61id_type!(
62 AnimationClipId,
63 "Typed identifier for an imported animation clip."
64);
65id_type!(
66 ParticleSystemId,
67 "Typed identifier for a registered particle system."
68);
69id_type!(
70 TerrainId,
71 "Typed identifier for a registered terrain system."
72);
73id_type!(SkyId, "Typed identifier for a registered sky.");
74id_type!(WaterId, "Typed identifier for a registered water surface.");
75id_type!(
76 XrSessionId,
77 "Typed identifier for a registered XR session plan."
78);
79id_type!(XrAnchorId, "Typed identifier for a tracked XR anchor.");
80id_type!(
81 AudioListenerId,
82 "Typed identifier for a registered audio listener."
83);
84id_type!(
85 AudioSourceId,
86 "Typed identifier for a registered audio source."
87);
88id_type!(
89 PhysicsWorldId,
90 "Typed identifier for a registered physics world."
91);
92id_type!(
93 PhysicsBodyId,
94 "Typed identifier for a registered physics body."
95);
96id_type!(
97 ColliderId,
98 "Typed identifier for a registered physics collider."
99);
100
101#[cfg(all(test, feature = "std"))]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn id_newtypes_are_copy_hashable_and_debuggable() {
107 let id = NodeId::new(42);
108 let copied = id;
109 assert_eq!(copied.get(), 42);
110 assert_eq!(format!("{id:?}"), "NodeId(42)");
111 }
112}