unity_asset_core/
constants.rs

1//! Constants and type definitions for Unity YAML parsing
2//!
3//! This module contains Unity-specific constants, tags, and type definitions
4//! that are used throughout the parsing process.
5
6use std::collections::HashMap;
7use std::sync::{Arc, RwLock};
8
9/// Unity YAML tag URI
10pub const UNITY_TAG_URI: &str = "tag:unity3d.com,2011:";
11
12/// Unity YAML version
13pub const UNITY_YAML_VERSION: (u32, u32) = (1, 1);
14
15/// Line ending types
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum LineEnding {
18    Unix,    // \n
19    Windows, // \r\n
20    Mac,     // \r
21}
22
23impl Default for LineEnding {
24    fn default() -> Self {
25        #[cfg(windows)]
26        return LineEnding::Windows;
27        #[cfg(not(windows))]
28        return LineEnding::Unix;
29    }
30}
31
32impl LineEnding {
33    pub fn as_str(&self) -> &'static str {
34        match self {
35            LineEnding::Unix => "\n",
36            LineEnding::Windows => "\r\n",
37            LineEnding::Mac => "\r",
38        }
39    }
40
41    /// Create LineEnding from string representation
42    pub fn from_string(s: &str) -> Self {
43        match s {
44            "\n" => LineEnding::Unix,
45            "\r\n" => LineEnding::Windows,
46            "\r" => LineEnding::Mac,
47            _ => LineEnding::default(),
48        }
49    }
50}
51
52/// Unity class ID to name mapping
53/// This is a global registry that maps class IDs to class names
54pub struct UnityClassIdMap {
55    map: Arc<RwLock<HashMap<String, String>>>,
56}
57
58impl UnityClassIdMap {
59    pub fn new() -> Self {
60        Self {
61            map: Arc::new(RwLock::new(HashMap::new())),
62        }
63    }
64
65    /// Get or create a class mapping
66    pub fn get_or_create(&self, class_id: &str, class_name: &str) -> String {
67        let key = format!("{}-{}", class_id, class_name);
68
69        // Try to read first
70        if let Ok(map) = self.map.read()
71            && let Some(existing) = map.get(&key)
72        {
73            return existing.clone();
74        }
75
76        // Need to write
77        if let Ok(mut map) = self.map.write() {
78            map.insert(key.clone(), class_name.to_string());
79        }
80
81        class_name.to_string()
82    }
83
84    /// Clear all mappings
85    pub fn clear(&self) {
86        if let Ok(mut map) = self.map.write() {
87            map.clear();
88        }
89    }
90
91    /// Get class name from class ID
92    pub fn get_class_name(&self, class_id: i32) -> Option<String> {
93        // Unity class ID to name mapping (based on UnityPy and unity-rs)
94        match class_id {
95            // Core Unity objects
96            0 => Some("Object".to_string()),
97            1 => Some("GameObject".to_string()),
98            2 => Some("Component".to_string()),
99            4 => Some("Transform".to_string()),
100            8 => Some("Behaviour".to_string()),
101
102            // Managers
103            3 => Some("LevelGameManager".to_string()),
104            5 => Some("TimeManager".to_string()),
105            6 => Some("GlobalGameManager".to_string()),
106            9 => Some("GameManager".to_string()),
107            11 => Some("AudioManager".to_string()),
108            13 => Some("InputManager".to_string()),
109
110            // Rendering
111            20 => Some("Camera".to_string()),
112            21 => Some("Material".to_string()),
113            23 => Some("MeshRenderer".to_string()),
114            25 => Some("Renderer".to_string()),
115            27 => Some("Texture".to_string()),
116            28 => Some("Texture2D".to_string()),
117            33 => Some("MeshFilter".to_string()),
118            43 => Some("Mesh".to_string()),
119            48 => Some("Shader".to_string()),
120
121            // Text and Assets
122            49 => Some("TextAsset".to_string()),
123            74 => Some("AnimationClip".to_string()),
124            83 => Some("AudioClip".to_string()),
125            89 => Some("CubemapArray".to_string()),
126            90 => Some("Avatar".to_string()),
127            91 => Some("AnimatorController".to_string()),
128            95 => Some("Animator".to_string()),
129            108 => Some("Light".to_string()),
130            114 => Some("MonoBehaviour".to_string()),
131            115 => Some("MonoScript".to_string()),
132            128 => Some("Font".to_string()),
133            142 => Some("AssetBundle".to_string()),
134            152 => Some("MovieTexture".to_string()),
135            184 => Some("RenderTexture".to_string()),
136            212 => Some("SpriteRenderer".to_string()),
137            213 => Some("Sprite".to_string()),
138
139            // Physics
140            50 => Some("Rigidbody2D".to_string()),
141            54 => Some("Rigidbody".to_string()),
142            56 => Some("Collider".to_string()),
143
144            // Special/Unknown types that we've encountered
145            687078895 => Some("SpriteAtlas".to_string()), // This is the unknown class we found
146
147            // Additional mappings based on our test results
148            256 => Some("Texture2D".to_string()), // Class_256 is likely Texture2D
149            512 => Some("SpriteAtlas".to_string()), // Class_512 is likely SpriteAtlas
150            768 => Some("Sprite".to_string()),    // Class_768 is likely Sprite
151
152            _ => None,
153        }
154    }
155}
156
157impl Default for UnityClassIdMap {
158    fn default() -> Self {
159        Self::new()
160    }
161}
162
163lazy_static::lazy_static! {
164    /// Global class ID map instance
165    pub static ref GLOBAL_CLASS_ID_MAP: UnityClassIdMap = UnityClassIdMap::new();
166}
167
168/// Common Unity class IDs
169pub mod class_ids {
170    pub const OBJECT: i32 = 0;
171    pub const GAME_OBJECT: i32 = 1;
172    pub const COMPONENT: i32 = 2;
173    pub const TRANSFORM: i32 = 4;
174    pub const CAMERA: i32 = 20;
175    pub const MATERIAL: i32 = 21;
176    pub const MESH_RENDERER: i32 = 23;
177    pub const TEXTURE_2D: i32 = 28;
178    pub const MESH: i32 = 43;
179    pub const SHADER: i32 = 48;
180    pub const TEXTURE: i32 = 27;
181    pub const SPRITE: i32 = 212;
182    pub const MONO_BEHAVIOUR: i32 = 114;
183    pub const MONO_SCRIPT: i32 = 115;
184    pub const PREFAB: i32 = 1001;
185    pub const PREFAB_INSTANCE: i32 = 1001; // Same as PREFAB in some versions
186}
187
188/// Common Unity class names
189pub mod class_names {
190    pub const OBJECT: &str = "Object";
191    pub const GAME_OBJECT: &str = "GameObject";
192    pub const COMPONENT: &str = "Component";
193    pub const TRANSFORM: &str = "Transform";
194    pub const CAMERA: &str = "Camera";
195    pub const MATERIAL: &str = "Material";
196    pub const MESH_RENDERER: &str = "MeshRenderer";
197    pub const TEXTURE_2D: &str = "Texture2D";
198    pub const MESH: &str = "Mesh";
199    pub const SHADER: &str = "Shader";
200    pub const TEXTURE: &str = "Texture";
201    pub const SPRITE: &str = "Sprite";
202    pub const MONO_BEHAVIOUR: &str = "MonoBehaviour";
203    pub const MONO_SCRIPT: &str = "MonoScript";
204    pub const PREFAB: &str = "Prefab";
205    pub const PREFAB_INSTANCE: &str = "PrefabInstance";
206}
207
208#[cfg(test)]
209mod tests {
210    use super::*;
211
212    #[test]
213    fn test_line_ending() {
214        assert_eq!(LineEnding::Unix.as_str(), "\n");
215        assert_eq!(LineEnding::Windows.as_str(), "\r\n");
216        assert_eq!(LineEnding::Mac.as_str(), "\r");
217    }
218
219    #[test]
220    fn test_class_id_map() {
221        let map = UnityClassIdMap::new();
222        let result = map.get_or_create("1", "GameObject");
223        assert_eq!(result, "GameObject");
224
225        // Should return the same result
226        let result2 = map.get_or_create("1", "GameObject");
227        assert_eq!(result2, "GameObject");
228    }
229}