162 lines
5.2 KiB
GDScript
162 lines
5.2 KiB
GDScript
extends SceneTree
|
|
|
|
const ADT_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/adt_builder.gd")
|
|
const BAKED_TILE_SCRIPT := preload("res://resources/baked_adt_tile.gd")
|
|
|
|
var _builder
|
|
var _loader
|
|
var _image_cache: Dictionary = {}
|
|
|
|
|
|
func _initialize() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
var map_name := _get_arg_value(args, "--map", "Azeroth")
|
|
var extracted_dir := _normalize_res_path(_get_arg_value(args, "--extracted", "res://extracted"))
|
|
var output_dir := _normalize_res_path(_get_arg_value(args, "--output", "res://cache/baked_terrain_v2"))
|
|
var legacy_texture_size = _get_optional_int_arg(args, "--texture-size")
|
|
var full_texture_size := maxi(
|
|
256,
|
|
_get_arg_value(
|
|
args,
|
|
"--full-texture-size",
|
|
str(legacy_texture_size if legacy_texture_size != null else 2048)
|
|
).to_int()
|
|
)
|
|
var coarse_texture_size := maxi(
|
|
128,
|
|
_get_arg_value(
|
|
args,
|
|
"--coarse-texture-size",
|
|
str(legacy_texture_size if legacy_texture_size != null else 512)
|
|
).to_int()
|
|
)
|
|
var tile_x: Variant = _get_optional_int_arg(args, "--tile-x")
|
|
var tile_y: Variant = _get_optional_int_arg(args, "--tile-y")
|
|
var force := args.has("--force")
|
|
|
|
_builder = ADT_BUILDER_SCRIPT.new()
|
|
if not ClassDB.class_exists("ADTLoader"):
|
|
push_error("ADTLoader not found. Rebuild GDExtension first.")
|
|
quit(1)
|
|
return
|
|
|
|
_loader = ClassDB.instantiate("ADTLoader")
|
|
if _loader == null:
|
|
push_error("Failed to instantiate ADTLoader.")
|
|
quit(1)
|
|
return
|
|
|
|
var map_dir := extracted_dir.path_join("World/Maps/%s" % map_name)
|
|
var dir := DirAccess.open(map_dir)
|
|
if dir == null:
|
|
push_error("Cannot open map directory: %s" % map_dir)
|
|
quit(1)
|
|
return
|
|
|
|
DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(output_dir.path_join(map_name)))
|
|
|
|
var baked := 0
|
|
var skipped := 0
|
|
var failed := 0
|
|
var started_ms := Time.get_ticks_msec()
|
|
|
|
for file_name in dir.get_files():
|
|
if not file_name.ends_with(".adt"):
|
|
continue
|
|
|
|
var stem := file_name.trim_suffix(".adt")
|
|
var parts := stem.split("_")
|
|
if parts.size() != 3 or parts[0] != map_name:
|
|
continue
|
|
if not parts[1].is_valid_int() or not parts[2].is_valid_int():
|
|
continue
|
|
|
|
var tx := parts[1].to_int()
|
|
var ty := parts[2].to_int()
|
|
if tile_x != null and tx != tile_x:
|
|
continue
|
|
if tile_y != null and ty != tile_y:
|
|
continue
|
|
var source_res_path := map_dir.path_join(file_name)
|
|
var source_abs_path := ProjectSettings.globalize_path(source_res_path)
|
|
var output_res_path := output_dir.path_join(map_name).path_join("%s_%d_%d.res" % [map_name, tx, ty])
|
|
var output_abs_path := ProjectSettings.globalize_path(output_res_path)
|
|
|
|
if not force and FileAccess.file_exists(output_abs_path):
|
|
skipped += 1
|
|
continue
|
|
|
|
var data: Dictionary = _loader.call("load_adt", source_abs_path)
|
|
if data.is_empty() or not data.has("chunks"):
|
|
push_warning("Bake failed to parse ADT: %s" % source_res_path)
|
|
failed += 1
|
|
continue
|
|
|
|
var full_payload: Dictionary = _builder.build_baked_tile_render_payload(
|
|
data,
|
|
_image_cache,
|
|
ProjectSettings.globalize_path(extracted_dir),
|
|
0,
|
|
full_texture_size)
|
|
var coarse_payload: Dictionary = _builder.build_baked_tile_render_payload(
|
|
data,
|
|
_image_cache,
|
|
ProjectSettings.globalize_path(extracted_dir),
|
|
3,
|
|
coarse_texture_size)
|
|
|
|
if full_payload.is_empty():
|
|
push_warning("Bake produced empty full mesh: %s" % source_res_path)
|
|
failed += 1
|
|
continue
|
|
|
|
var baked_tile: Resource = BAKED_TILE_SCRIPT.new()
|
|
baked_tile.set("format_version", BAKED_TILE_SCRIPT.FORMAT_VERSION)
|
|
baked_tile.set("map_name", map_name)
|
|
baked_tile.set("tile_x", tx)
|
|
baked_tile.set("tile_y", ty)
|
|
baked_tile.set("tile_origin", _builder.get_tile_origin_for_data(data))
|
|
baked_tile.set("full_texture_size", full_texture_size)
|
|
baked_tile.set("coarse_texture_size", coarse_texture_size)
|
|
baked_tile.set("wmo_names", data.get("wmo_names", PackedStringArray()))
|
|
baked_tile.set("wmo_placements", data.get("wmo_placements", []))
|
|
baked_tile.set("m2_names", data.get("m2_names", PackedStringArray()))
|
|
baked_tile.set("m2_placements", data.get("m2_placements", []))
|
|
baked_tile.set("full_mesh", full_payload.get("mesh", null))
|
|
baked_tile.set("coarse_mesh", coarse_payload.get("mesh", null))
|
|
|
|
var save_err := ResourceSaver.save(baked_tile, output_res_path)
|
|
if save_err != OK:
|
|
push_warning("Failed to save baked tile: %s (err=%d)" % [output_res_path, save_err])
|
|
failed += 1
|
|
continue
|
|
|
|
baked += 1
|
|
if baked % 25 == 0:
|
|
print("Baked %d tiles..." % baked)
|
|
|
|
var elapsed_ms := Time.get_ticks_msec() - started_ms
|
|
print("Bake finished. baked=%d skipped=%d failed=%d elapsed=%.2fs" % [
|
|
baked, skipped, failed, float(elapsed_ms) / 1000.0])
|
|
quit(0 if failed == 0 else 2)
|
|
|
|
|
|
func _get_arg_value(args: PackedStringArray, name: String, default_value: String) -> String:
|
|
var index := args.find(name)
|
|
if index >= 0 and index + 1 < args.size():
|
|
return args[index + 1]
|
|
return default_value
|
|
|
|
|
|
func _get_optional_int_arg(args: PackedStringArray, name: String):
|
|
var index := args.find(name)
|
|
if index >= 0 and index + 1 < args.size() and args[index + 1].is_valid_int():
|
|
return args[index + 1].to_int()
|
|
return null
|
|
|
|
|
|
func _normalize_res_path(path: String) -> String:
|
|
if path.begins_with("res://"):
|
|
return path
|
|
return "res://%s" % path.trim_prefix("./").trim_prefix("/")
|