Files
mtgodot-poc/project/python_ui_surface.gd
T
2026-09-22 20:34:45 -07:00

114 lines
4.2 KiB
GDScript

# Canvas adapter for the 40250 CWindowManager. The window tree remains native;
# this Control forwards Godot input and draws the native UI command stream.
extends Control
const AssetRoot = preload("res://asset_root.gd")
const UiAssets = preload("res://ui/ui_assets.gd")
const KEY_TO_DIK := {
KEY_ESCAPE: 0x01, KEY_1: 0x02, KEY_2: 0x03, KEY_3: 0x04,
KEY_4: 0x05, KEY_5: 0x06, KEY_6: 0x07, KEY_7: 0x08,
KEY_8: 0x09, KEY_9: 0x0a, KEY_0: 0x0b, KEY_BACKSPACE: 0x0e,
KEY_TAB: 0x0f, KEY_Q: 0x10, KEY_W: 0x11, KEY_E: 0x12,
KEY_R: 0x13, KEY_T: 0x14, KEY_Y: 0x15, KEY_U: 0x16,
KEY_I: 0x17, KEY_O: 0x18, KEY_P: 0x19, KEY_ENTER: 0x1c,
KEY_A: 0x1e, KEY_S: 0x1f, KEY_D: 0x20, KEY_F: 0x21,
KEY_G: 0x22, KEY_H: 0x23, KEY_J: 0x24, KEY_K: 0x25,
KEY_L: 0x26, KEY_Z: 0x2c, KEY_X: 0x2d, KEY_C: 0x2e,
KEY_V: 0x2f, KEY_B: 0x30, KEY_N: 0x31, KEY_M: 0x32,
KEY_SPACE: 0x39, KEY_UP: 0xc8, KEY_LEFT: 0xcb,
KEY_RIGHT: 0xcd, KEY_DOWN: 0xd0,
}
func _ready() -> void:
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
mouse_filter = Control.MOUSE_FILTER_STOP
_sync_size()
func _notification(what: int) -> void:
if what == NOTIFICATION_RESIZED and is_inside_tree():
_sync_size()
func _sync_size() -> void:
if ClassDB.class_exists("Metin2PythonHost"):
Metin2PythonHost.set_ui_size(int(size.x), int(size.y))
func _process(_delta: float) -> void:
if Metin2PythonHost.is_running():
Metin2PythonHost.ui_update()
queue_redraw()
func _gui_input(event: InputEvent) -> void:
if not Metin2PythonHost.is_running():
return
if event is InputEventMouseMotion:
Metin2PythonHost.ui_mouse_move(int(event.position.x), int(event.position.y))
elif event is InputEventMouseButton:
if event.button_index >= MOUSE_BUTTON_LEFT and event.button_index <= MOUSE_BUTTON_MIDDLE:
Metin2PythonHost.ui_mouse_button(event.button_index, event.pressed,
int(event.position.x), int(event.position.y))
func _unhandled_key_input(event: InputEvent) -> void:
if event is InputEventKey and Metin2PythonHost.is_running():
var dik: int = KEY_TO_DIK.get(event.physical_keycode, 0)
if dik != 0:
Metin2PythonHost.ui_key(dik, event.pressed)
func _draw() -> void:
if not Metin2PythonHost.is_running():
return
for command in Metin2PythonHost.ui_render_commands():
var argb: int = command["argb"]
var color := Color8((argb >> 16) & 255, (argb >> 8) & 255,
argb & 255, (argb >> 24) & 255)
var p1 := Vector2(command["x1"], command["y1"])
var p2 := Vector2(command["x2"], command["y2"])
var clip := Rect2(Vector2(command["clip_x1"], command["clip_y1"]),
Vector2(command["clip_x2"] - command["clip_x1"],
command["clip_y2"] - command["clip_y1"]))
if command["kind"] == "bar":
var visible := Rect2(p1, p2 - p1).intersection(clip)
if visible.has_area():
draw_rect(visible, color, true)
elif command["kind"] == "line":
var segment := _clip_line(p1, p2, clip)
if segment.size() == 2:
draw_line(segment[0], segment[1], color)
elif command["kind"] == "text":
var font: Font = ThemeDB.fallback_font
if font != null:
var baseline := p1 + Vector2(0, font.get_ascent(14))
if clip.has_point(p1):
draw_string(font, baseline, command["text"], HORIZONTAL_ALIGNMENT_LEFT,
clip.end.x - p1.x, 14, color)
elif command["kind"] == "image":
var texture: Texture2D = UiAssets.load_tex(AssetRoot.path(), command["text"])
if texture != null:
var dest := Rect2(p1, p2 - p1)
var visible := dest.intersection(clip)
if visible.has_area() and dest.has_area():
var scale := texture.get_size() / dest.size
var source := Rect2((visible.position - dest.position) * scale, visible.size * scale)
draw_texture_rect_region(texture, visible, source, color)
func _clip_line(a: Vector2, b: Vector2, clip: Rect2) -> PackedVector2Array:
var delta := b - a
var p := [-delta.x, delta.x, -delta.y, delta.y]
var q := [a.x - clip.position.x, clip.end.x - a.x,
a.y - clip.position.y, clip.end.y - a.y]
var enter := 0.0
var leave := 1.0
for i in range(4):
if is_zero_approx(p[i]):
if q[i] < 0.0:
return PackedVector2Array()
else:
var t: float = q[i] / p[i]
if p[i] < 0.0:
enter = maxf(enter, t)
else:
leave = minf(leave, t)
if enter > leave:
return PackedVector2Array()
return PackedVector2Array([a + delta * enter, a + delta * leave])