project restructure

This commit is contained in:
2026-01-03 14:04:12 +00:00
parent ff3c092d9e
commit bfd451aca9
45 changed files with 93 additions and 80 deletions

View File

@@ -11,7 +11,8 @@
"Bash(cargo check:*)",
"Bash(ls:*)",
"Bash(find:*)",
"Bash(grep:*)"
"Bash(grep:*)",
"Bash(wc:*)"
],
"additionalDirectories": [
"/home/connor/repos/CBAssets/"

56
Cargo.lock generated
View File

@@ -23,34 +23,6 @@ version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c"
[[package]]
name = "cursebreaker-parser"
version = "0.1.0"
dependencies = [
"cursebreaker-parser-macros",
"glam",
"indexmap",
"inventory",
"lru",
"once_cell",
"pretty_assertions",
"regex",
"serde",
"serde_yaml",
"sparsey",
"thiserror",
"walkdir",
]
[[package]]
name = "cursebreaker-parser-macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
@@ -318,6 +290,34 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unity-parser"
version = "0.1.0"
dependencies = [
"glam",
"indexmap",
"inventory",
"lru",
"once_cell",
"pretty_assertions",
"regex",
"serde",
"serde_yaml",
"sparsey",
"thiserror",
"unity-parser-macros",
"walkdir",
]
[[package]]
name = "unity-parser-macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"

View File

@@ -1,5 +1,5 @@
[workspace]
members = ["cursebreaker-parser", "cursebreaker-parser-macros"]
members = ["unity-parser", "unity-parser-macros"]
resolver = "2"
[workspace.package]
@@ -7,4 +7,4 @@ version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/yourusername/cursebreaker-parser-rust"
repository = "https://github.com/yourusername/unity-parser-rust"

View File

@@ -1,4 +1,4 @@
# Cursebreaker Parser
# Unity Parser
A high-performance Rust library for parsing Unity project files (.unity scenes, .prefab prefabs, and .asset ScriptableObjects) with automatic MonoBehaviour component discovery and ECS integration.
@@ -32,7 +32,7 @@ Add to your `Cargo.toml`:
```toml
[dependencies]
cursebreaker-parser = "0.1"
unity-parser = "0.1"
sparsey = "0.13" # For ECS queries
```
@@ -41,7 +41,7 @@ sparsey = "0.13" # For ECS queries
### Parse a Unity Scene
```rust
use cursebreaker_parser::UnityFile;
use unity_parser::UnityFile;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = UnityFile::from_path("Scene.unity")?;
@@ -51,7 +51,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Scene with {} entities", scene.entity_map.len());
// Query transforms
let transforms = scene.world.borrow::<cursebreaker_parser::Transform>();
let transforms = scene.world.borrow::<unity_parser::Transform>();
for (file_id, entity) in &scene.entity_map {
if let Some(transform) = transforms.get(*entity) {
println!("Entity {} at {:?}", file_id, transform.local_position());
@@ -73,7 +73,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
### Define Custom Components
```rust
use cursebreaker_parser::UnityComponent;
use unity_parser::UnityComponent;
#[derive(Debug, Clone, UnityComponent)]
#[unity_class("PlaySFX")]
@@ -133,7 +133,7 @@ Parse only scenes matching specific patterns:
```rust
use regex::Regex;
use cursebreaker_parser::parse_unity_file_filtered;
use unity_parser::parse_unity_file_filtered;
// Only parse production scenes
let filter = Regex::new(r"Assets/Scenes/Production/")?;
@@ -161,7 +161,7 @@ let filter = Regex::new(r"Level[1-5]\.unity$")?;
Selectively parse components for better performance:
```rust
use cursebreaker_parser::{TypeFilter, parse_with_types};
use unity_parser::{TypeFilter, parse_with_types};
// Parse only transforms and custom components
let filter = TypeFilter::parse_with_types(&["Transform", "PlaySFX"]);
@@ -232,7 +232,7 @@ Raw YAML Documents
### Find All Components of a Type
```rust
use cursebreaker_parser::UnityFile;
use unity_parser::UnityFile;
let scene = UnityFile::from_path("Scene.unity")?;
@@ -378,7 +378,7 @@ Benchmarks on VR Horror project (21 scenes, 77 C# scripts):
## Project Structure
```
cursebreaker-parser/
unity-parser/
├── src/
│ ├── ecs/ # ECS world building
│ ├── model/ # UnityFile, Scene, Prefab models
@@ -387,11 +387,15 @@ cursebreaker-parser/
│ │ ├── meta.rs # .meta file parsing
│ │ └── yaml.rs # YAML document splitting
│ ├── types/ # Unity types and components
│ │ ├── unity_types/ # Unity-specific types
│ │ │ ├── game_object.rs
│ │ │ ├── prefab_instance.rs
│ │ │ └── transform.rs
│ │ ├── guid.rs # 128-bit GUID type
│ │ ├── component.rs # Component trait system
│ │ └── ...
│ └── lib.rs
├── cursebreaker-parser-macros/ # Derive macro crate
├── unity-parser-macros/ # Derive macro crate
├── examples/ # Usage examples
├── tests/ # Integration tests
└── test_data/ # Test Unity projects

View File

@@ -1,11 +1,11 @@
[package]
name = "cursebreaker-parser-macros"
name = "unity-parser-macros"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
description = "Procedural macros for cursebreaker-parser"
repository = "https://github.com/yourusername/cursebreaker-parser-rust"
description = "Procedural macros for unity-parser"
repository = "https://github.com/yourusername/unity-parser-rust"
[lib]
proc-macro = true

View File

@@ -1,4 +1,4 @@
//! Procedural macros for cursebreaker-parser
//! Procedural macros for unity-parser
//!
//! This crate provides the `#[derive(UnityComponent)]` macro for automatically
//! generating Unity component parsing code.

View File

@@ -1,17 +1,17 @@
[package]
name = "cursebreaker-parser"
name = "unity-parser"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
description = "A high-performance Rust library for parsing Unity project files (.unity, .prefab, .asset)"
repository = "https://github.com/yourusername/cursebreaker-parser-rust"
repository = "https://github.com/yourusername/unity-parser-rust"
keywords = ["unity", "parser", "yaml", "gamedev"]
categories = ["parser-implementations", "game-development"]
rust-version = "1.70"
[lib]
name = "cursebreaker_parser"
name = "unity_parser"
path = "src/lib.rs"
[dependencies]
@@ -47,7 +47,7 @@ once_cell = "1.19"
inventory = "0.3"
# Procedural macro for derive(UnityComponent)
cursebreaker-parser-macros = { path = "../cursebreaker-parser-macros" }
unity-parser-macros = { path = "../unity-parser-macros" }
[dev-dependencies]
# Testing utilities

View File

@@ -1,4 +1,4 @@
use cursebreaker_parser::UnityFile;
use unity_parser::UnityFile;
use std::path::Path;
fn main() {

View File

@@ -1,7 +1,7 @@
//! Example demonstrating how to define custom Unity MonoBehaviour components
//! using the #[derive(UnityComponent)] macro.
use cursebreaker_parser::{yaml_helpers, ComponentContext, UnityComponent};
use unity_parser::{yaml_helpers, ComponentContext, UnityComponent};
/// Custom Unity MonoBehaviour component for playing sound effects
///
@@ -71,7 +71,7 @@ isLoop: 1
let mapping = yaml.as_mapping().unwrap();
// Create a dummy context
use cursebreaker_parser::{ComponentContext, FileID};
use unity_parser::{ComponentContext, FileID};
let ctx = ComponentContext {
type_id: 114,
file_id: FileID::from_i64(12345),

View File

@@ -5,7 +5,7 @@
//! 2. Using the parse_with_types! macro for selective parsing
//! 3. Querying the ECS world for components
use cursebreaker_parser::{parse_with_types, ComponentContext, EcsInsertable, FileID, TypeFilter, UnityComponent};
use unity_parser::{parse_with_types, ComponentContext, EcsInsertable, FileID, TypeFilter, UnityComponent};
/// Custom Unity MonoBehaviour component
#[derive(Debug, Clone, UnityComponent)]

View File

@@ -6,7 +6,7 @@
//! 3. Querying the ECS world for components
//! 4. Accessing Transform data for component locations
use cursebreaker_parser::{UnityComponent, UnityFile};
use unity_parser::{UnityComponent, UnityFile};
use std::path::Path;
/// PlaySFX component from VR_Horror_YouCantRun
@@ -71,9 +71,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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::<cursebreaker_parser::Transform>();
let rect_transform_view = scene.world.borrow::<cursebreaker_parser::RectTransform>();
let gameobject_view = scene.world.borrow::<cursebreaker_parser::GameObject>();
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;

View File

@@ -10,7 +10,7 @@
//! doesn't yet support resolving components from nested prefabs. This example
//! parses the prefab files directly instead.
use cursebreaker_parser::{GuidResolver, UnityComponent, UnityFile};
use unity_parser::{GuidResolver, UnityComponent, UnityFile};
use std::fs::File;
use std::io::Write;
use std::path::Path;

View File

@@ -6,7 +6,7 @@
//! 3. Extracting typeId and transform positions
//! 4. Writing resource data to an output file
use cursebreaker_parser::{UnityComponent, UnityFile};
use unity_parser::{UnityComponent, UnityFile};
use std::fs::File;
use std::io::Write;
use std::path::Path;
@@ -58,8 +58,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get views for component types we need
let resource_view = scene.world.borrow::<InteractableResource>();
let transform_view = scene.world.borrow::<cursebreaker_parser::Transform>();
let gameobject_view = scene.world.borrow::<cursebreaker_parser::GameObject>();
let transform_view = scene.world.borrow::<unity_parser::Transform>();
let gameobject_view = scene.world.borrow::<unity_parser::GameObject>();
// Find all entities that have Interactable_Resource
let mut found_resources = Vec::new();

View File

@@ -6,7 +6,7 @@
//! # Example
//!
//! ```no_run
//! use cursebreaker_parser::UnityFile;
//! use unity_parser::UnityFile;
//!
//! let file = UnityFile::from_path("Scene.unity")?;
//! match file {
@@ -21,7 +21,7 @@
//! println!("Asset with {} documents", asset.documents.len());
//! }
//! }
//! # Ok::<(), cursebreaker_parser::Error>(())
//! # Ok::<(), unity_parser::Error>(())
//! ```
// Public modules
@@ -53,4 +53,4 @@ pub use types::{
};
// Re-export the derive macro from the macro crate
pub use cursebreaker_parser_macros::UnityComponent;
pub use unity_parser_macros::UnityComponent;

View File

@@ -5,28 +5,25 @@
//! wrappers for GameObjects and Components.
mod component;
mod game_object;
mod guid;
mod ids;
mod prefab_instance;
mod reference;
mod transform;
mod type_filter;
mod type_registry;
mod unity_types;
mod values;
pub use component::{
yaml_helpers, ComponentContext, ComponentRegistration, EcsInsertable, LinkCallback,
LinkingContext, UnityComponent,
};
pub use game_object::GameObject;
pub use guid::Guid;
pub use ids::{FileID, LocalID};
pub use prefab_instance::{
PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
};
pub use reference::UnityReference;
pub use transform::{RectTransform, Transform};
pub use type_filter::TypeFilter;
pub use type_registry::{get_class_name, get_type_id};
pub use unity_types::{
GameObject, PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
RectTransform, Transform,
};
pub use values::{Color, ExternalRef, FileRef, Quaternion, Vector2, Vector3};

View File

@@ -0,0 +1,11 @@
//! Unity-specific types (GameObjects, Transforms, PrefabInstances)
pub mod game_object;
pub mod prefab_instance;
pub mod transform;
pub use game_object::GameObject;
pub use prefab_instance::{
PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
};
pub use transform::{RectTransform, Transform};

View File

@@ -1,6 +1,6 @@
//! Integration tests for parsing real Unity projects
use cursebreaker_parser::{GuidResolver, UnityFile};
use unity_parser::{GuidResolver, UnityFile};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::Instant;
@@ -449,7 +449,7 @@ fn test_guid_resolution() {
}
// Test resolution by Guid type
use cursebreaker_parser::Guid;
use unity_parser::Guid;
let playsfx_guid = Guid::from_hex(playsfx_guid_str).unwrap();
match resolver.resolve_class_name(&playsfx_guid) {
Some(class_name) => {
@@ -478,7 +478,7 @@ fn test_guid_resolution() {
/// Test parsing PlaySFX components from actual scene file
#[test]
fn test_playsfx_parsing() {
use cursebreaker_parser::UnityComponent;
use unity_parser::UnityComponent;
/// PlaySFX component from VR_Horror_YouCantRun
#[derive(Debug, Clone, UnityComponent)]
@@ -520,8 +520,8 @@ fn test_playsfx_parsing() {
println!("\n Parsing scene: {}", scene_path.display());
match cursebreaker_parser::UnityFile::from_path(&scene_path) {
Ok(cursebreaker_parser::UnityFile::Scene(scene)) => {
match unity_parser::UnityFile::from_path(&scene_path) {
Ok(unity_parser::UnityFile::Scene(scene)) => {
println!(" ✓ Scene parsed successfully");
println!(" - Total entities: {}", scene.entity_map.len());

View File

@@ -1,6 +1,6 @@
//! Tests for the #[derive(UnityComponent)] macro
use cursebreaker_parser::{ComponentContext, FileID, UnityComponent};
use unity_parser::{ComponentContext, FileID, UnityComponent};
/// Test component matching the PlaySFX script from VR_Horror_YouCantRun
#[derive(Debug, Clone, UnityComponent)]
@@ -133,7 +133,7 @@ fn test_component_registration() {
let mut found_play_sfx = false;
let mut found_test_component = false;
for reg in inventory::iter::<cursebreaker_parser::ComponentRegistration> {
for reg in inventory::iter::<unity_parser::ComponentRegistration> {
if reg.class_name == "PlaySFX" {
found_play_sfx = true;
assert_eq!(reg.type_id, 114);
@@ -177,7 +177,7 @@ isLoop: 0
};
// Find the PlaySFX registration and call its parser
for reg in inventory::iter::<cursebreaker_parser::ComponentRegistration> {
for reg in inventory::iter::<unity_parser::ComponentRegistration> {
if reg.class_name == "PlaySFX" {
let result = (reg.parser)(mapping, &ctx);
assert!(result.is_some(), "Registered parser failed to parse");