победа над водопадами, шейдеры m2

This commit is contained in:
2026-07-07 10:45:43 +04:00
parent 8738c2495d
commit 44614a79e4
38 changed files with 4820 additions and 192 deletions
+81 -7
View File
@@ -3,6 +3,8 @@
## Usage:
## godot --headless --path <project> --script res://src/tools/bake_m2_cache.gd -- \
## --map Azeroth --extracted res://data/extracted --output res://data/cache/m2_glb --force
## Add --only-pattern waterfall to rebuild only matching model paths.
## Add --glb-animations to also emit animated GLB scenes through src/tools/m2_to_gltf.py.
extends SceneTree
const M2_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/m2_builder.gd")
@@ -13,6 +15,10 @@ func _initialize() -> void:
var extracted := _res(_arg(args, "--extracted", "res://data/extracted"))
var output_dir := _res(_arg(args, "--output", "res://data/cache/m2_glb"))
var force := args.has("--force")
var glb_animations := args.has("--glb-animations")
var only_patterns := _arg_values(args, "--only-pattern")
var python_exe := _arg(args, "--python", "python")
var converter := _res(_arg(args, "--converter", "res://src/tools/m2_to_gltf.py"))
if not ClassDB.class_exists("ADTLoader") or not ClassDB.class_exists("M2Loader"):
push_error("GDExtension not loaded. Rebuild first.")
@@ -47,7 +53,7 @@ func _initialize() -> void:
var norm := str(rel).replace("\\", "/").to_lower()
if norm.ends_with(".mdx") or norm.ends_with(".mdl"):
norm = norm.get_basename() + ".m2"
if not norm.is_empty():
if not norm.is_empty() and _matches_only_patterns(norm, only_patterns):
unique[norm] = true
scanned += 1
@@ -55,8 +61,10 @@ func _initialize() -> void:
var m2_loader = ClassDB.instantiate("M2Loader")
var baked := 0
var baked_glb := 0
var skipped := 0
var failed := 0
var failed_glb := 0
var total := unique.size()
var i := 0
@@ -64,16 +72,22 @@ func _initialize() -> void:
i += 1
var stem: String = rel_path.get_basename()
var out_path := output_dir.path_join(stem + ".tscn")
if not force and ResourceLoader.exists(out_path):
skipped += 1
continue
var out_glb_path := output_dir.path_join(stem + ".glb")
var abs_m2 := ProjectSettings.globalize_path(extracted.path_join(rel_path))
if not FileAccess.file_exists(abs_m2):
failed += 1
continue
if not force and ResourceLoader.exists(out_path):
if glb_animations:
if _bake_glb_animation_cache(python_exe, converter, abs_m2, output_dir, out_glb_path, false):
baked_glb += 1
else:
failed_glb += 1
skipped += 1
continue
var data: Dictionary = m2_loader.call("load_m2", abs_m2)
if data.is_empty() or data.get("vertices", PackedVector3Array()).is_empty():
failed += 1
@@ -102,10 +116,17 @@ func _initialize() -> void:
continue
baked += 1
if glb_animations:
if _bake_glb_animation_cache(python_exe, converter, abs_m2, output_dir, out_glb_path, force):
baked_glb += 1
else:
failed_glb += 1
if i % 50 == 0 or i == total:
print("[%d/%d] baked=%d skipped=%d failed=%d" % [i, total, baked, skipped, failed])
print("[%d/%d] baked=%d glb=%d skipped=%d failed=%d glb_failed=%d" % [
i, total, baked, baked_glb, skipped, failed, failed_glb])
print("Done. baked=%d skipped=%d failed=%d" % [baked, skipped, failed])
print("Done. baked=%d glb=%d skipped=%d failed=%d glb_failed=%d" % [
baked, baked_glb, skipped, failed, failed_glb])
quit(0)
@@ -116,12 +137,65 @@ func _arg(args: PackedStringArray, name: String, default: String) -> String:
return default
func _arg_values(args: PackedStringArray, name: String) -> PackedStringArray:
var result := PackedStringArray()
for i in args.size():
if args[i] != name or i + 1 >= args.size():
continue
for part in String(args[i + 1]).split(",", false):
var value := part.strip_edges().to_lower()
if not value.is_empty():
result.append(value)
return result
func _matches_only_patterns(path: String, patterns: PackedStringArray) -> bool:
if patterns.is_empty():
return true
var lower := path.to_lower()
for pattern in patterns:
if lower.contains(pattern):
return true
return false
func _res(path: String) -> String:
if path.begins_with("res://") or path.begins_with("user://"):
return path
return "res://" + path.trim_prefix("./").trim_prefix("/")
func _bake_glb_animation_cache(
python_exe: String,
converter: String,
abs_m2: String,
output_dir: String,
out_glb_path: String,
force: bool) -> bool:
var abs_out_glb := ProjectSettings.globalize_path(out_glb_path)
if not force and FileAccess.file_exists(abs_out_glb):
return true
var abs_converter := ProjectSettings.globalize_path(converter)
var abs_output := ProjectSettings.globalize_path(output_dir)
if not FileAccess.file_exists(abs_converter):
push_warning("M2 GLB converter not found: %s" % converter)
return false
var stdout := []
var exit_code := OS.execute(
python_exe,
[abs_converter, abs_m2, abs_output],
stdout,
true,
false)
if exit_code != 0:
push_warning("animated GLB bake failed for %s exit=%d\n%s" % [
abs_m2,
exit_code,
"\n".join(stdout)])
return false
return FileAccess.file_exists(abs_out_glb)
func _set_owner_recursive(node: Node, owner_root: Node) -> void:
for child in node.get_children():
child.owner = owner_root