195 lines
7.4 KiB
Rust
195 lines
7.4 KiB
Rust
//! 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<dyn std::error::Error>> {
|
|
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::<PlaySFX>();
|
|
let transform_view = scene.world.borrow::<unity_parser::Transform>();
|
|
let rect_transform_view = scene.world.borrow::<unity_parser::RectTransform>();
|
|
let gameobject_view = scene.world.borrow::<unity_parser::GameObject>();
|
|
|
|
// 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<std::path::PathBuf> {
|
|
let mut files = Vec::new();
|
|
|
|
fn visit_dir(dir: &Path, extension: &str, files: &mut Vec<std::path::PathBuf>) {
|
|
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
|
|
}
|