lua: select, log, body, on, get_text, set_text, subscribtions, events (keyup, keydown, keypress, mouseover, mouseup, mousedown, mouseenter, mouseexit, click, focusin, focusout)
This commit is contained in:
161
flumi/Scripts/Utils/Lua/Event.gd
Normal file
161
flumi/Scripts/Utils/Lua/Event.gd
Normal file
@@ -0,0 +1,161 @@
|
||||
class_name LuaEventUtils
|
||||
extends RefCounted
|
||||
|
||||
static func connect_element_event(signal_node: Node, event_name: String, subscription) -> bool:
|
||||
if not signal_node:
|
||||
return false
|
||||
|
||||
match event_name:
|
||||
"click":
|
||||
if signal_node.has_signal("pressed"):
|
||||
signal_node.pressed.connect(subscription.lua_api._on_event_triggered.bind(subscription))
|
||||
subscription.connected_signal = "pressed"
|
||||
subscription.connected_node = signal_node if signal_node != subscription.lua_api.get_dom_node(signal_node.get_parent(), "signal") else null
|
||||
return true
|
||||
elif signal_node is Control:
|
||||
signal_node.gui_input.connect(subscription.lua_api._on_gui_input_click.bind(subscription))
|
||||
subscription.connected_signal = "gui_input"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"mousedown", "mouseup":
|
||||
if signal_node is Control:
|
||||
# Check if we already have a mouse handler connected to this node
|
||||
var already_connected = false
|
||||
for existing_id in subscription.lua_api.event_subscriptions:
|
||||
var existing_sub = subscription.lua_api.event_subscriptions[existing_id]
|
||||
if existing_sub.connected_node == signal_node and existing_sub.connected_signal == "gui_input_mouse":
|
||||
already_connected = true
|
||||
break
|
||||
|
||||
if not already_connected:
|
||||
signal_node.gui_input.connect(subscription.lua_api._on_gui_input_mouse_universal.bind(signal_node))
|
||||
|
||||
subscription.connected_signal = "gui_input_mouse"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"mousemove":
|
||||
if signal_node is Control:
|
||||
signal_node.gui_input.connect(subscription.lua_api._on_gui_input_mousemove.bind(subscription))
|
||||
subscription.connected_signal = "gui_input_mousemove"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"mouseenter":
|
||||
if signal_node is Control and signal_node.has_signal("mouse_entered"):
|
||||
signal_node.mouse_entered.connect(subscription.lua_api._on_event_triggered.bind(subscription))
|
||||
subscription.connected_signal = "mouse_entered"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"mouseexit":
|
||||
if signal_node is Control and signal_node.has_signal("mouse_exited"):
|
||||
signal_node.mouse_exited.connect(subscription.lua_api._on_event_triggered.bind(subscription))
|
||||
subscription.connected_signal = "mouse_exited"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"focusin":
|
||||
if signal_node is Control:
|
||||
signal_node.focus_mode = Control.FOCUS_ALL
|
||||
if signal_node.has_signal("focus_entered"):
|
||||
signal_node.focus_entered.connect(subscription.lua_api._on_event_triggered.bind(subscription))
|
||||
subscription.connected_signal = "focus_entered"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
else:
|
||||
signal_node.gui_input.connect(subscription.lua_api._on_focus_gui_input.bind(subscription))
|
||||
subscription.connected_signal = "gui_input_focus"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
"focusout":
|
||||
if signal_node is Control and signal_node.has_signal("focus_exited"):
|
||||
signal_node.focus_exited.connect(subscription.lua_api._on_event_triggered.bind(subscription))
|
||||
subscription.connected_signal = "focus_exited"
|
||||
subscription.connected_node = signal_node
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
static func connect_body_event(event_name: String, subscription, lua_api) -> bool:
|
||||
match event_name:
|
||||
"keydown", "keypress", "keyup":
|
||||
lua_api.set_process_input(true)
|
||||
subscription.connected_signal = "input"
|
||||
subscription.connected_node = lua_api
|
||||
return true
|
||||
"mousemove":
|
||||
lua_api.set_process_input(true)
|
||||
subscription.connected_signal = "input_mousemove"
|
||||
subscription.connected_node = lua_api
|
||||
return true
|
||||
"mouseenter", "mouseexit":
|
||||
var main_container = lua_api.dom_parser.parse_result.dom_nodes.get("body", null)
|
||||
if main_container:
|
||||
if event_name == "mouseenter":
|
||||
main_container.mouse_entered.connect(lua_api._on_body_mouse_enter.bind(subscription))
|
||||
subscription.connected_signal = "mouse_entered"
|
||||
elif event_name == "mouseexit":
|
||||
main_container.mouse_exited.connect(lua_api._on_body_mouse_exit.bind(subscription))
|
||||
subscription.connected_signal = "mouse_exited"
|
||||
subscription.connected_node = main_container
|
||||
return true
|
||||
"focusin", "focusout":
|
||||
subscription.connected_signal = "focus_events"
|
||||
subscription.connected_node = lua_api
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
static func _count_active_input_subscriptions(lua_api) -> int:
|
||||
var count = 0
|
||||
for sub_id in lua_api.event_subscriptions:
|
||||
var sub = lua_api.event_subscriptions[sub_id]
|
||||
if sub.connected_signal in ["input", "input_mousemove"]:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
static func disconnect_subscription(subscription, lua_api) -> void:
|
||||
var target_node = subscription.connected_node if subscription.connected_node else lua_api.dom_parser.parse_result.dom_nodes.get(subscription.element_id, null)
|
||||
|
||||
if target_node and subscription.connected_signal:
|
||||
match subscription.connected_signal:
|
||||
"pressed":
|
||||
if target_node.has_signal("pressed"):
|
||||
target_node.pressed.disconnect(lua_api._on_event_triggered.bind(subscription))
|
||||
"gui_input":
|
||||
if target_node.has_signal("gui_input"):
|
||||
target_node.gui_input.disconnect(lua_api._on_gui_input_click.bind(subscription))
|
||||
"gui_input_mouse":
|
||||
if target_node.has_signal("gui_input"):
|
||||
target_node.gui_input.disconnect(lua_api._on_gui_input_mouse_universal.bind(target_node))
|
||||
"gui_input_mousemove":
|
||||
if target_node.has_signal("gui_input"):
|
||||
target_node.gui_input.disconnect(lua_api._on_gui_input_mousemove.bind(subscription))
|
||||
"gui_input_focus":
|
||||
if target_node.has_signal("gui_input"):
|
||||
target_node.gui_input.disconnect(lua_api._on_focus_gui_input.bind(subscription))
|
||||
"mouse_entered":
|
||||
if target_node.has_signal("mouse_entered"):
|
||||
# Check if this is a body event or element event
|
||||
if subscription.element_id == "body":
|
||||
target_node.mouse_entered.disconnect(lua_api._on_body_mouse_enter.bind(subscription))
|
||||
else:
|
||||
target_node.mouse_entered.disconnect(lua_api._on_event_triggered.bind(subscription))
|
||||
"mouse_exited":
|
||||
if target_node.has_signal("mouse_exited"):
|
||||
# Check if this is a body event or element event
|
||||
if subscription.element_id == "body":
|
||||
target_node.mouse_exited.disconnect(lua_api._on_body_mouse_exit.bind(subscription))
|
||||
else:
|
||||
target_node.mouse_exited.disconnect(lua_api._on_event_triggered.bind(subscription))
|
||||
"focus_entered":
|
||||
if target_node.has_signal("focus_entered"):
|
||||
target_node.focus_entered.disconnect(lua_api._on_event_triggered.bind(subscription))
|
||||
"focus_exited":
|
||||
if target_node.has_signal("focus_exited"):
|
||||
target_node.focus_exited.disconnect(lua_api._on_event_triggered.bind(subscription))
|
||||
"input":
|
||||
# Only disable input processing if no other input subscriptions remain
|
||||
if _count_active_input_subscriptions(lua_api) <= 1:
|
||||
lua_api.set_process_input(false)
|
||||
"input_mousemove":
|
||||
# Only disable input processing if no other input subscriptions remain
|
||||
if _count_active_input_subscriptions(lua_api) <= 1:
|
||||
lua_api.set_process_input(false)
|
||||
1
flumi/Scripts/Utils/Lua/Event.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/Event.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b7bck02xxt0u6
|
||||
57
flumi/Scripts/Utils/Lua/Function.gd
Normal file
57
flumi/Scripts/Utils/Lua/Function.gd
Normal file
@@ -0,0 +1,57 @@
|
||||
class_name LuaFunctionUtils
|
||||
extends RefCounted
|
||||
|
||||
# Core Lua handler functions that extend Lua functionality
|
||||
|
||||
static func table_tostring_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var table_string = LuaPrintUtils.table_to_string(vm, 1)
|
||||
vm.lua_pushstring(table_string)
|
||||
return 1
|
||||
|
||||
static func setup_gurt_api(vm: LuauVM, lua_api, dom_parser: HTMLParser) -> void:
|
||||
# override global print
|
||||
# This makes print() behave like gurt.log()
|
||||
vm.lua_pushcallable(LuaPrintUtils.lua_print, "print")
|
||||
vm.lua_setglobal("print")
|
||||
|
||||
# Add table.tostring utility
|
||||
vm.lua_getglobal("table")
|
||||
if vm.lua_isnil(-1):
|
||||
vm.lua_pop(1)
|
||||
vm.lua_newtable()
|
||||
vm.lua_setglobal("table")
|
||||
vm.lua_getglobal("table")
|
||||
|
||||
vm.lua_pushcallable(LuaFunctionUtils.table_tostring_handler, "table.tostring")
|
||||
vm.lua_setfield(-2, "tostring")
|
||||
vm.lua_pop(1) # Pop table from stack
|
||||
|
||||
vm.lua_newtable()
|
||||
|
||||
vm.lua_pushcallable(LuaPrintUtils.lua_print, "gurt.log")
|
||||
vm.lua_setfield(-2, "log")
|
||||
|
||||
vm.lua_pushcallable(lua_api._gurt_select_handler, "gurt.select")
|
||||
vm.lua_setfield(-2, "select")
|
||||
|
||||
# Add body element access
|
||||
var body_element = dom_parser.find_first("body")
|
||||
if body_element:
|
||||
vm.lua_newtable()
|
||||
vm.lua_pushstring("body")
|
||||
vm.lua_setfield(-2, "_element_id")
|
||||
|
||||
# NOTE: same code as add_element_methods, but lazy to handle body.xxxx prop
|
||||
vm.lua_pushcallable(lua_api._element_set_text_handler, "body.set_text")
|
||||
vm.lua_setfield(-2, "set_text")
|
||||
|
||||
vm.lua_pushcallable(lua_api._element_get_text_handler, "body.get_text")
|
||||
vm.lua_setfield(-2, "get_text")
|
||||
|
||||
vm.lua_pushcallable(lua_api._body_on_event_handler, "body.on")
|
||||
vm.lua_setfield(-2, "on")
|
||||
|
||||
vm.lua_setfield(-2, "body")
|
||||
|
||||
vm.lua_setglobal("gurt")
|
||||
1
flumi/Scripts/Utils/Lua/Function.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/Function.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dbsrdfnhv4h16
|
||||
87
flumi/Scripts/Utils/Lua/Print.gd
Normal file
87
flumi/Scripts/Utils/Lua/Print.gd
Normal file
@@ -0,0 +1,87 @@
|
||||
class_name LuaPrintUtils
|
||||
extends RefCounted
|
||||
|
||||
static func lua_print(vm: LuauVM) -> int:
|
||||
var message_parts: Array[String] = []
|
||||
var num_args: int = vm.lua_gettop()
|
||||
|
||||
for i in range(1, num_args + 1):
|
||||
var value_str = lua_value_to_string(vm, i)
|
||||
message_parts.append(value_str)
|
||||
|
||||
var final_message = "\t".join(message_parts)
|
||||
print("GURT LOG: ", final_message)
|
||||
return 0
|
||||
|
||||
static func lua_value_to_string(vm: LuauVM, index: int) -> String:
|
||||
var lua_type = vm.lua_type(index)
|
||||
|
||||
match lua_type:
|
||||
vm.LUA_TNIL:
|
||||
return "nil"
|
||||
vm.LUA_TBOOLEAN:
|
||||
return "true" if vm.lua_toboolean(index) else "false"
|
||||
vm.LUA_TNUMBER:
|
||||
return str(vm.lua_tonumber(index))
|
||||
vm.LUA_TSTRING:
|
||||
return vm.lua_tostring(index)
|
||||
vm.LUA_TTABLE:
|
||||
return table_to_string(vm, index)
|
||||
vm.LUA_TFUNCTION:
|
||||
return "[function]"
|
||||
vm.LUA_TUSERDATA:
|
||||
return "[userdata]"
|
||||
vm.LUA_TVECTOR:
|
||||
var vec = vm.lua_tovector(index)
|
||||
return "vector(" + str(vec.x) + ", " + str(vec.y) + ", " + str(vec.z) + ", " + str(vec.w) + ")"
|
||||
_:
|
||||
return "[" + vm.lua_typename(lua_type) + "]"
|
||||
|
||||
static func table_to_string(vm: LuauVM, index: int, max_depth: int = 3, current_depth: int = 0) -> String:
|
||||
if current_depth >= max_depth:
|
||||
return "{...}"
|
||||
|
||||
var result = "{"
|
||||
var first = true
|
||||
var count = 0
|
||||
var max_items = 10
|
||||
|
||||
# Convert negative index to positive
|
||||
if index < 0:
|
||||
index = vm.lua_gettop() + index + 1
|
||||
|
||||
# Iterate through table
|
||||
vm.lua_pushnil() # First key
|
||||
while vm.lua_next(index):
|
||||
if count >= max_items:
|
||||
# We need to pop the value and key before breaking
|
||||
vm.lua_pop(2) # Remove value and key
|
||||
break
|
||||
|
||||
if not first:
|
||||
result += ", "
|
||||
first = false
|
||||
|
||||
# Get key
|
||||
var key_str = lua_value_to_string(vm, -2)
|
||||
# Get value
|
||||
var value_str = ""
|
||||
if vm.lua_type(-1) == vm.LUA_TTABLE:
|
||||
value_str = table_to_string(vm, -1, max_depth, current_depth + 1)
|
||||
else:
|
||||
value_str = lua_value_to_string(vm, -1)
|
||||
|
||||
# Check if key is a valid identifier (for shorthand)
|
||||
if key_str.is_valid_identifier():
|
||||
result += key_str + ": " + value_str
|
||||
else:
|
||||
result += "[" + key_str + "]: " + value_str
|
||||
|
||||
vm.lua_pop(1) # Remove value, keep key for next iteration
|
||||
count += 1
|
||||
|
||||
if count >= max_items:
|
||||
result += ", ..."
|
||||
|
||||
result += "}"
|
||||
return result
|
||||
1
flumi/Scripts/Utils/Lua/Print.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/Print.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dvdnveday3ev1
|
||||
1
flumi/Scripts/Utils/LuaEventUtils.gd.uid
Normal file
1
flumi/Scripts/Utils/LuaEventUtils.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bt0njoa0olpb7
|
||||
1
flumi/Scripts/Utils/LuaFunctionUtils.gd.uid
Normal file
1
flumi/Scripts/Utils/LuaFunctionUtils.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dxti5hc236dcp
|
||||
1
flumi/Scripts/Utils/LuaPrintUtils.gd.uid
Normal file
1
flumi/Scripts/Utils/LuaPrintUtils.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bwbbe8r7u10ov
|
||||
Reference in New Issue
Block a user