use super::types::{ExtResource, GodotScene, SceneNode, SubResource};
use anyhow::Result;
use std::collections::HashMap;
impl GodotScene {
pub fn parse(content: &str) -> Result<Self> {
let mut scene = Self::new();
let mut current_section = String::new();
let mut current_properties: HashMap<String, String> = HashMap::new();
for line in content.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with(';') {
continue;
}
if line.starts_with('[') && line.ends_with(']') {
if !current_section.is_empty() {
process_section(¤t_section, ¤t_properties, &mut scene)?;
}
let section_content = &line[1..line.len() - 1];
let parts: Vec<&str> = section_content.split_whitespace().collect();
current_section = parts[0].to_string();
current_properties.clear();
for part in &parts[1..] {
if let Some(eq_pos) = part.find('=') {
let key = part[..eq_pos].to_string();
let value = part[eq_pos + 1..].to_string();
current_properties.insert(key, value);
}
}
continue;
}
if let Some(eq_pos) = line.find('=') {
let key = line[..eq_pos].trim().to_string();
let value = line[eq_pos + 1..].trim().to_string();
current_properties.insert(key, value);
}
}
if !current_section.is_empty() {
process_section(¤t_section, ¤t_properties, &mut scene)?;
}
Ok(scene)
}
}
fn process_section(section: &str, properties: &HashMap<String, String>, scene: &mut GodotScene) -> Result<()> {
if section.starts_with("gd_scene") {
if let Some(format_str) = properties.get("format") {
scene.format_version = format_str.parse().unwrap_or(3);
}
if let Some(load_steps_str) = properties.get("load_steps") {
scene.load_steps = load_steps_str.parse().unwrap_or(1);
}
scene.uid = properties.get("uid").map(|s| s.trim_matches('"').to_string());
} else if section.starts_with("ext_resource") {
let resource_type = properties
.get("type")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let path = properties
.get("path")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let id = properties
.get("id")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
scene.ext_resources.push(ExtResource {
id,
resource_type,
path,
});
} else if section.starts_with("sub_resource") {
let resource_type = properties
.get("type")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let id = properties
.get("id")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let mut props = properties.clone();
props.remove("type");
props.remove("id");
scene.sub_resources.push(SubResource {
id,
resource_type,
properties: props,
});
} else if section.starts_with("node") {
let name = properties
.get("name")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let node_type = properties
.get("type")
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_default();
let parent = properties.get("parent").map(|s| s.trim_matches('"').to_string());
let instance = properties.get("instance").map(|s| s.trim_matches('"').to_string());
let script = properties.get("script").map(|s| s.to_string());
let mut props = properties.clone();
props.remove("name");
props.remove("type");
props.remove("parent");
props.remove("instance");
props.remove("script");
scene.nodes.push(SceneNode {
name,
node_type,
parent,
instance,
script,
properties: props,
});
}
Ok(())
}