aboutsummaryrefslogtreecommitdiff
path: root/tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs')
-rw-r--r--tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs185
1 files changed, 0 insertions, 185 deletions
diff --git a/tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs b/tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs
deleted file mode 100644
index 660caf1..0000000
--- a/tools/tscn-to-bsn/src/cmd/cmd_build_cache.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-use std::collections::BTreeMap;
-use std::io;
-use std::path::{Path, PathBuf};
-
-use mingling::macros::routeify;
-use mingling::{
- Grouped,
- macros::{buffer, command, pack_err, r_println, renderer},
-};
-
-use crate::{
- Next,
- gd_res_structure::{TscnValue, parse},
- res::gd_proj_dir::ResGodotProjectDirectory,
-};
-
-pack_err!(ErrorGodotProjectNotFound);
-
-/// Build result
-#[derive(Grouped)]
-pub struct ResultCacheBuilt {
- path: PathBuf,
- len: usize,
-}
-
-#[command(node = "build-cache", routeify)]
-pub fn build_cache(proj: &ResGodotProjectDirectory) -> Next {
- let Some(ref dir) = proj.dir else {
- return ErrorGodotProjectNotFound::default().into();
- };
-
- // 1. Scan uid → res:// paths
- let map = scan_project(dir)?;
-
- // 2. Write .godot/tscn2bsn.cache.json
- let cache_path = dir.join(".godot").join("tscn2bsn.cache.json");
- if let Some(parent) = cache_path.parent() {
- std::fs::create_dir_all(parent)?;
- }
- let json = serde_json::to_string_pretty(&map)?;
- std::fs::write(&cache_path, json)?;
-
- ResultCacheBuilt {
- path: cache_path,
- len: map.len(),
- }
- .into()
-}
-
-/// Recursively collect all files in the project, skipping `.godot` / `.git`
-fn collect_files(dir: &Path, out: &mut Vec<PathBuf>) -> io::Result<()> {
- for entry in std::fs::read_dir(dir)? {
- let entry = entry?;
- let path = entry.path();
- if path.is_dir() {
- let name = entry.file_name().to_string_lossy().into_owned();
- if name == ".godot" || name == ".git" {
- continue;
- }
- collect_files(&path, out)?;
- } else if path.is_file() {
- out.push(path);
- }
- }
- Ok(())
-}
-
-/// Project relative path → `res://` form (Godot's standard in-project path)
-fn to_res_path(project_dir: &Path, file: &Path) -> String {
- let rel = file.strip_prefix(project_dir).unwrap_or(file);
- let rel = rel.to_string_lossy().replace('\\', "/");
- format!("res://{rel}")
-}
-
-/// Scan all uid sources, aggregate the mapping
-fn scan_project(project_dir: &Path) -> io::Result<BTreeMap<String, String>> {
- let mut files = Vec::new();
- collect_files(project_dir, &mut files)?;
-
- let mut map = BTreeMap::new();
- for file in files {
- let ext = file
- .extension()
- .and_then(|e| e.to_str())
- .unwrap_or("")
- .to_lowercase();
- match ext.as_str() {
- // scenes/foo.glb.import → resource path res://scenes/foo.glb
- "import" => {
- if let Some(uid) = parse_import_uid(&file) {
- let res_path = to_res_path(project_dir, &file);
- insert_unique(
- &mut map,
- uid,
- res_path.trim_end_matches(".import").to_string(),
- );
- }
- }
- "tscn" | "tres" => {
- if let Some(uid) = parse_scene_uid(&file) {
- insert_unique(&mut map, uid, to_res_path(project_dir, &file));
- }
- }
- // foo.gd.uid → resource path res://foo.gd
- "uid" => {
- if let Some(uid) = parse_sidecar_uid(&file) {
- let res_path = to_res_path(project_dir, &file);
- insert_unique(&mut map, uid, res_path.trim_end_matches(".uid").to_string());
- }
- }
- _ => {}
- }
- }
- Ok(map)
-}
-
-fn insert_unique(map: &mut BTreeMap<String, String>, uid: String, res_path: String) {
- match map.entry(uid.clone()) {
- std::collections::btree_map::Entry::Vacant(v) => {
- v.insert(res_path);
- }
- std::collections::btree_map::Entry::Occupied(o) => {
- eprintln!("Warning: duplicate uid {uid}: {} vs {res_path}", o.get());
- }
- }
-}
-
-/// `.import` file: `uid="uid://..."` in the `[remap]` section (writer: editor_file_system.cpp L2693)
-fn parse_import_uid(file: &Path) -> Option<String> {
- let content = std::fs::read_to_string(file).ok()?;
- let mut in_remap = false;
- for line in content.lines() {
- let line = line.trim();
- if line.starts_with('[') {
- in_remap = line == "[remap]";
- continue;
- }
- if in_remap && let Some(v) = line.strip_prefix("uid=") {
- let uid = v.trim().trim_matches('"');
- if uid.starts_with("uid://") {
- return Some(uid.to_string());
- }
- }
- }
- None
-}
-
-/// `.tscn` / `.tres`: reuse the tscn parser, extract the `uid` field from the header tag
-fn parse_scene_uid(file: &Path) -> Option<String> {
- let content = std::fs::read_to_string(file).ok()?;
- let doc = parse(&content).ok()?;
- for (key, value) in &doc.header.fields {
- if key == "uid"
- && let TscnValue::Str(s) = value
- {
- return Some(s.clone());
- }
- }
- None
-}
-
-/// `.uid` sidecar file: the first line is `uid://...` (writer: editor_file_system.cpp L939)
-fn parse_sidecar_uid(file: &Path) -> Option<String> {
- let content = std::fs::read_to_string(file).ok()?;
- let first = content.lines().next()?.trim();
- if first.starts_with("uid://") {
- Some(first.to_string())
- } else {
- None
- }
-}
-
-#[renderer(buffer)]
-pub fn render_cache_built(r: ResultCacheBuilt) {
- r_println!("OK: wrote {} ({} uids)", r.path.display(), r.len);
-}
-
-#[renderer(buffer)]
-pub fn render_error_godot_project_not_found(_: ErrorGodotProjectNotFound) {
- r_println!("Error: Godot project not found. ");
- r_println!("");
- r_println!(
- "Please specify the project directory with `/P` or run this command in the project directory!"
- )
-}