141 lines
5.3 KiB
GDScript
141 lines
5.3 KiB
GDScript
extends SceneTree
|
|
|
|
const PythonUISurface = preload("res://python_ui_surface.gd")
|
|
const Python3DSurface = preload("res://python_3d_surface.gd")
|
|
|
|
var ui: Control
|
|
var world: Node3D
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run")
|
|
|
|
func _py(source: String) -> bool:
|
|
return Metin2PythonHost.run_line(source) == ""
|
|
|
|
func _pump_until(seconds: float, condition: Callable) -> bool:
|
|
var deadline := Time.get_ticks_msec() + int(seconds * 1000.0)
|
|
while Time.get_ticks_msec() < deadline:
|
|
if condition.call():
|
|
return true
|
|
await process_frame
|
|
return condition.call()
|
|
|
|
func run() -> void:
|
|
root.size = Vector2i(1024, 768)
|
|
world = Python3DSurface.new()
|
|
world.name = "Python3DSurface"
|
|
ui = PythonUISurface.new()
|
|
ui.name = "PythonUISurface"
|
|
root.add_child(ui)
|
|
root.add_child(world)
|
|
|
|
var err: String = ui.run_app()
|
|
if err != "":
|
|
print("ERROR: run_app: ", err)
|
|
quit(1)
|
|
return
|
|
|
|
await _pump_until(15, func(): return _py(
|
|
"import __main__, os, networkModule, introLogin, introSelect, game, player, background, chr, chrmgr\n"
|
|
+ "__main__._stream = [o for o in __import__('gc').get_objects() if isinstance(o, networkModule.MainStream)][0]"
|
|
))
|
|
|
|
await _pump_until(20, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, introLogin.LoginWindow)"
|
|
))
|
|
|
|
var host = OS.get_environment("MT_LIVE_HOST")
|
|
var login = OS.get_environment("MT_LIVE_LOGIN")
|
|
var pwd = OS.get_environment("MT_LIVE_PASSWORD")
|
|
var auth_port = int(OS.get_environment("MT_LIVE_AUTH_PORT"))
|
|
var game_port = int(OS.get_environment("MT_LIVE_GAME_PORT"))
|
|
|
|
_py("_stream.SetConnectInfo('%s', %d, '%s', %d)\n" % [host, game_port, host, auth_port]
|
|
+ "_stream.curPhaseWindow.Connect('%s', '%s')" % [login, pwd])
|
|
|
|
await _pump_until(30, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, introSelect.SelectCharacterWindow)"
|
|
))
|
|
|
|
_py("_stream.curPhaseWindow.SelectSlot(0)\n_stream.curPhaseWindow.StartGame()")
|
|
|
|
await _pump_until(30, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, game.GameWindow) and _stream.curPhaseWindow.IsShow()"
|
|
))
|
|
|
|
for i in 60:
|
|
await process_frame
|
|
|
|
print("=== CAMERA WORLD & HEIGHT PROFILE ===")
|
|
var draws: Array = Metin2PythonHost.render3d_draws()
|
|
if not draws.is_empty():
|
|
var vm: PackedFloat32Array = draws[0]["view"]
|
|
var cam_inv: Transform3D = Python3DSurface.d3d_transform(vm).affine_inverse()
|
|
print("Camera world origin: ", cam_inv.origin)
|
|
print("Camera world basis: ", cam_inv.basis)
|
|
print("Camera looking direction: ", -cam_inv.basis.z)
|
|
|
|
for y in range(68200, 66200, -100):
|
|
var bg_h = Metin2PythonHost.evaluate("str(background.GetHeight(59700.0, %f))" % float(y))
|
|
var terrain_h = float(world.terrain.call("sample_height", 597.0, float(y) / 100.0)) * 100.0 if world.terrain else 0.0
|
|
print("Profile y=%d: bg_h=%s terrain_h=%.2f" % [y, bg_h, terrain_h])
|
|
|
|
print("Total draws: ", draws.size())
|
|
|
|
for d in draws:
|
|
var tex: String = d.get("texture0", "")
|
|
if tex.contains("warrior") or tex.contains("stray_dog") or tex.contains("goods"):
|
|
var wm: PackedFloat32Array = d["world"]
|
|
var vm: PackedFloat32Array = d["view"]
|
|
var xform: Transform3D = Python3DSurface.d3d_transform(wm)
|
|
var cam_xform: Transform3D = Python3DSurface.d3d_transform(Python3DSurface.multiply(wm, vm))
|
|
|
|
var min_z := 1e9
|
|
var max_z := -1e9
|
|
var min_local_z := 1e9
|
|
var max_local_z := -1e9
|
|
for pos in d["positions"]:
|
|
min_local_z = minf(min_local_z, pos.z)
|
|
max_local_z = maxf(max_local_z, pos.z)
|
|
var wp: Vector3 = xform * pos
|
|
min_z = minf(min_z, wp.z)
|
|
max_z = maxf(max_z, wp.z)
|
|
|
|
# Map position: (xform.origin.x, -xform.origin.y)
|
|
var map_x := xform.origin.x
|
|
var map_y := -xform.origin.y
|
|
var actor_z := xform.origin.z
|
|
|
|
var bg_h = Metin2PythonHost.evaluate("str(background.GetHeight(%f, %f))" % [map_x, map_y])
|
|
var terrain_h = float(world.terrain.call("sample_height", map_x / 100.0, map_y / 100.0)) * 100.0 if world.terrain else 0.0
|
|
|
|
print("Actor [%s]:" % tex.get_file())
|
|
print(" World origin: ", xform.origin, " (map_x=%.1f, map_y=%.1f, origin_z=%.1f)" % [map_x, map_y, actor_z])
|
|
print(" Local vert Z range: [%.2f, %.2f]" % [min_local_z, max_local_z])
|
|
print(" World vert Z range: [%.2f, %.2f]" % [min_z, max_z])
|
|
print(" Background Height: %s, Terrain Height: %.2f" % [bg_h, terrain_h])
|
|
print(" Vert_Z min vs Height: diff = %.2f cm" % (min_z - float(bg_h)))
|
|
print(" Origin_Z vs Height: diff = %.2f cm" % (actor_z - float(bg_h)))
|
|
print(" Camera-space origin: ", cam_xform.origin)
|
|
|
|
if tex.contains("stray_dog"):
|
|
print("--- DOG TERRAIN DETAIL ---")
|
|
var from_map := Transform3D(Basis(Vector3(100, 0, 0), Vector3(0, 0, 100), Vector3(0, -100, 0)), Vector3.ZERO)
|
|
var dog_world := xform.origin # (59700, -66400, 19851.5)
|
|
print("Dog 40250 world: ", dog_world)
|
|
for child in world.terrain.find_children("*", "MeshInstance3D", true, false):
|
|
var mi := child as MeshInstance3D
|
|
if mi.mesh is ArrayMesh:
|
|
var am := mi.mesh as ArrayMesh
|
|
var arrays := am.surface_get_arrays(0)
|
|
var verts: PackedVector3Array = arrays[Mesh.ARRAY_VERTEX]
|
|
for v in verts:
|
|
var world_v: Vector3 = from_map * (mi.transform * v)
|
|
if abs(world_v.x - dog_world.x) < 300.0 and abs(world_v.y - dog_world.y) < 300.0:
|
|
print("Terrain local vert: ", v, " -> mi.xform*v: ", mi.transform * v, " -> from_map: ", world_v)
|
|
print("Diff Z (terrain world Z - dog world Z): ", world_v.z - dog_world.z)
|
|
break
|
|
|
|
|
|
quit(0)
|