//! Demo: Find all PlaySFX components and their locations in VR_Horror_YouCantRun //! //! This example demonstrates: //! 1. Parsing a real Unity project //! 2. Finding custom MonoBehaviour components (PlaySFX) //! 3. Querying the ECS world for components //! 4. Accessing Transform data for component locations use unity_parser::{UnityComponent, UnityFile}; use std::path::Path; /// PlaySFX component from VR_Horror_YouCantRun /// /// C# definition: /// ```csharp /// public class PlaySFX : MonoBehaviour /// { /// [SerializeField] float volume; /// [SerializeField] float startTime; /// [SerializeField] float endTime; /// [SerializeField] bool isLoop; /// } /// ``` #[derive(Debug, Clone, UnityComponent)] #[unity_class("PlaySFX")] pub struct PlaySFX { #[unity_field("volume")] pub volume: f64, #[unity_field("startTime")] pub start_time: f64, #[unity_field("endTime")] pub end_time: f64, #[unity_field("isLoop")] pub is_loop: bool, } fn main() -> Result<(), Box> { println!("🎮 VR Horror - PlaySFX Component Finder"); println!("{}", "=".repeat(70)); println!(); let project_path = Path::new("test_data/VR_Horror_YouCantRun"); // Check if project exists if !project_path.exists() { eprintln!("❌ Error: VR_Horror_YouCantRun project not found at {}", project_path.display()); eprintln!(" Run the integration tests first to download it:"); eprintln!(" cargo test test_vr_horror_project"); return Ok(()); } println!("📁 Scanning project: {}", project_path.display()); println!(); // Find all Unity scene files let scene_files = find_unity_files(project_path, "unity"); println!("📄 Found {} scene file(s)", scene_files.len()); println!(); let mut total_playsfx = 0; // Parse each scene for scene_path in scene_files { println!("🔍 Parsing: {}", scene_path.file_name().unwrap().to_string_lossy()); match UnityFile::from_path(&scene_path) { Ok(UnityFile::Scene(scene)) => { // Get views for all component types we need let playsfx_view = scene.world.borrow::(); let transform_view = scene.world.borrow::(); let rect_transform_view = scene.world.borrow::(); let gameobject_view = scene.world.borrow::(); // Find all entities that have PlaySFX let mut found_count = 0; let mut found_entities = Vec::new(); // Iterate through all entities in the entity_map for entity in scene.entity_map.values() { if let Some(playsfx) = playsfx_view.get(*entity) { found_entities.push((*entity, playsfx.clone())); found_count += 1; } } if found_count > 0 { println!(" ✅ Found {} PlaySFX component(s)", found_count); total_playsfx += found_count; // Process each found PlaySFX component for (entity, playsfx) in found_entities { let transform = transform_view.get(entity); let rect_transform = rect_transform_view.get(entity); let game_object = gameobject_view.get(entity); let name = game_object .and_then(|go| go.name()) .unwrap_or("(unnamed)"); println!(); println!(" 🔊 PlaySFX on GameObject: \"{}\"", name); println!(" Entity: {:?}", entity); println!(" Properties:"); println!(" • volume: {}", playsfx.volume); println!(" • startTime: {}", playsfx.start_time); println!(" • endTime: {}", playsfx.end_time); println!(" • isLoop: {}", playsfx.is_loop); // Print position if available if let Some(transform) = transform { if let Some(pos) = transform.local_position() { println!(" Transform:"); println!(" • Position: ({:.2}, {:.2}, {:.2})", pos.x, pos.y, pos.z); } if let Some(rot) = transform.local_rotation() { println!(" • Rotation: ({:.2}, {:.2}, {:.2}, {:.2})", rot.x, rot.y, rot.z, rot.w); } if let Some(scale) = transform.local_scale() { println!(" • Scale: ({:.2}, {:.2}, {:.2})", scale.x, scale.y, scale.z); } } else if let Some(rect_transform) = rect_transform { let transform = rect_transform.transform(); if let Some(pos) = transform.local_position() { println!(" RectTransform (UI):"); println!(" • Position: ({:.2}, {:.2}, {:.2})", pos.x, pos.y, pos.z); } } else { println!(" ⚠️ No Transform found"); } } } else { println!(" ⊘ No PlaySFX components found"); } println!(); } Ok(_) => { println!(" ⊘ Skipped (not a scene file)"); println!(); } Err(e) => { println!(" ❌ Parse error: {}", e); println!(); } } } println!("{}", "=".repeat(70)); println!("📊 Summary:"); println!(" Total PlaySFX components found: {}", total_playsfx); println!("{}", "=".repeat(70)); Ok(()) } /// Find all Unity files with a specific extension in a directory fn find_unity_files(dir: &Path, extension: &str) -> Vec { let mut files = Vec::new(); fn visit_dir(dir: &Path, extension: &str, files: &mut Vec) { if let Ok(entries) = std::fs::read_dir(dir) { for entry in entries.flatten() { let path = entry.path(); // Skip Library, Temp, Builds, and .git directories if let Some(name) = path.file_name().and_then(|n| n.to_str()) { if name == "Library" || name == "Temp" || name == "Builds" || name == ".git" { continue; } } if path.is_dir() { visit_dir(&path, extension, files); } else if let Some(ext) = path.extension().and_then(|e| e.to_str()) { if ext == extension { files.push(path); } } } } } visit_dir(dir, extension, &mut files); files.sort(); files }