element.size, element.position, mouse pos in cb
This commit is contained in:
@@ -55,6 +55,39 @@ for i = 1, #children do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### element.size
|
||||||
|
|
||||||
|
Gets the size of an element in pixels.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local box = gurt.select('#my-box')
|
||||||
|
local size = box.size
|
||||||
|
|
||||||
|
trace.log('Width: ' .. size.width .. 'px')
|
||||||
|
trace.log('Height: ' .. size.height .. 'px')
|
||||||
|
|
||||||
|
if size.width == size.height then
|
||||||
|
trace.log('Element is square')
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### element.position
|
||||||
|
|
||||||
|
Gets the position of an element relative to its parent.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local element = gurt.select('#positioned-element')
|
||||||
|
local pos = element.position
|
||||||
|
|
||||||
|
trace.log('X position: ' .. pos.x .. 'px')
|
||||||
|
trace.log('Y position: ' .. pos.y .. 'px')
|
||||||
|
|
||||||
|
-- Check if element is at origin
|
||||||
|
if pos.x == 0 and pos.y == 0 then
|
||||||
|
trace.log('Element is at origin')
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
## DOM Traversal
|
## DOM Traversal
|
||||||
|
|
||||||
### element.parent
|
### element.parent
|
||||||
@@ -96,11 +129,19 @@ Adds an event listener. Returns a subscription object.
|
|||||||
local button = gurt.select('#my-button')
|
local button = gurt.select('#my-button')
|
||||||
|
|
||||||
-- Click event
|
-- Click event
|
||||||
local subscription = button:on('click', function()
|
local subscription = button:on('click', function(event)
|
||||||
trace.log('Button clicked!')
|
trace.log('Button clicked at: ' .. event.x .. ', ' .. event.y)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
|
button:on('mousedown', function(event)
|
||||||
|
trace.log('Mouse down at: ' .. event.x .. ', ' .. event.y)
|
||||||
|
end)
|
||||||
|
|
||||||
|
button:on('mouseup', function(event)
|
||||||
|
trace.log('Mouse up at: ' .. event.x .. ', ' .. event.y)
|
||||||
|
end)
|
||||||
|
|
||||||
button:on('mouseenter', function()
|
button:on('mouseenter', function()
|
||||||
button.classList:add('hover-effect')
|
button.classList:add('hover-effect')
|
||||||
end)
|
end)
|
||||||
@@ -128,6 +169,30 @@ end)
|
|||||||
subscription:unsubscribe()
|
subscription:unsubscribe()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Mouse Event Positioning
|
||||||
|
|
||||||
|
Mouse events (`click`, `mousedown`, `mouseup`) provide position information relative to the element:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local element = gurt.select('#interactive-element')
|
||||||
|
|
||||||
|
element:on('click', function(event)
|
||||||
|
-- event.x and event.y are relative to the element's top-left corner
|
||||||
|
local elementX = event.x
|
||||||
|
local elementY = event.y
|
||||||
|
|
||||||
|
trace.log('Clicked at (' .. elementX .. ', ' .. elementY .. ') within element')
|
||||||
|
|
||||||
|
local size = element.size
|
||||||
|
local pos = element.position
|
||||||
|
|
||||||
|
local xPercent = (elementX / size.width) * 100
|
||||||
|
local yPercent = (elementY / size.height) * 100
|
||||||
|
|
||||||
|
trace.log('Clicked at ' .. xPercent .. '% horizontally, ' .. yPercent .. '% vertically')
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
### element:append(childElement)
|
### element:append(childElement)
|
||||||
|
|
||||||
Adds a child element.
|
Adds a child element.
|
||||||
|
|||||||
@@ -359,7 +359,8 @@ func _on_gui_input_click(event: InputEvent, subscription: EventSubscription) ->
|
|||||||
if event is InputEventMouseButton:
|
if event is InputEventMouseButton:
|
||||||
var mouse_event = event as InputEventMouseButton
|
var mouse_event = event as InputEventMouseButton
|
||||||
if mouse_event.button_index == MOUSE_BUTTON_LEFT and mouse_event.pressed:
|
if mouse_event.button_index == MOUSE_BUTTON_LEFT and mouse_event.pressed:
|
||||||
_execute_lua_callback(subscription)
|
var mouse_info = _get_element_relative_mouse_position(mouse_event, subscription.element_id)
|
||||||
|
_execute_lua_callback(subscription, [mouse_info])
|
||||||
|
|
||||||
func _on_gui_input_mouse_universal(event: InputEvent, signal_node: Node) -> void:
|
func _on_gui_input_mouse_universal(event: InputEvent, signal_node: Node) -> void:
|
||||||
if event is InputEventMouseButton:
|
if event is InputEventMouseButton:
|
||||||
@@ -376,7 +377,8 @@ func _on_gui_input_mouse_universal(event: InputEvent, signal_node: Node) -> void
|
|||||||
should_trigger = true
|
should_trigger = true
|
||||||
|
|
||||||
if should_trigger:
|
if should_trigger:
|
||||||
_execute_lua_callback(subscription)
|
var mouse_info = _get_element_relative_mouse_position(mouse_event, subscription.element_id)
|
||||||
|
_execute_lua_callback(subscription, [mouse_info])
|
||||||
|
|
||||||
# Event callback handlers
|
# Event callback handlers
|
||||||
func _on_gui_input_mousemove(event: InputEvent, subscription: EventSubscription) -> void:
|
func _on_gui_input_mousemove(event: InputEvent, subscription: EventSubscription) -> void:
|
||||||
@@ -449,6 +451,30 @@ func _input(event: InputEvent) -> void:
|
|||||||
if subscription.event_name == "mousemove":
|
if subscription.event_name == "mousemove":
|
||||||
_handle_mousemove_event(mouse_event, subscription)
|
_handle_mousemove_event(mouse_event, subscription)
|
||||||
|
|
||||||
|
func _get_element_relative_mouse_position(mouse_event: InputEvent, element_id: String) -> Dictionary:
|
||||||
|
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
|
if not dom_node or not dom_node is Control:
|
||||||
|
return {"x": 0, "y": 0}
|
||||||
|
|
||||||
|
var control = dom_node as Control
|
||||||
|
var global_pos: Vector2
|
||||||
|
|
||||||
|
if mouse_event is InputEventMouseButton:
|
||||||
|
global_pos = (mouse_event as InputEventMouseButton).global_position
|
||||||
|
elif mouse_event is InputEventMouseMotion:
|
||||||
|
global_pos = (mouse_event as InputEventMouseMotion).global_position
|
||||||
|
else:
|
||||||
|
return {"x": 0, "y": 0}
|
||||||
|
|
||||||
|
var element_rect = control.get_global_rect()
|
||||||
|
var local_x = global_pos.x - element_rect.position.x
|
||||||
|
var local_y = global_pos.y - element_rect.position.y
|
||||||
|
|
||||||
|
return {
|
||||||
|
"x": local_x,
|
||||||
|
"y": local_y
|
||||||
|
}
|
||||||
|
|
||||||
func _handle_mousemove_event(mouse_event: InputEventMouseMotion, subscription: EventSubscription) -> void:
|
func _handle_mousemove_event(mouse_event: InputEventMouseMotion, subscription: EventSubscription) -> void:
|
||||||
# TODO: pass reference instead of hardcoded path
|
# TODO: pass reference instead of hardcoded path
|
||||||
var body_container = Engine.get_main_loop().current_scene.website_container
|
var body_container = Engine.get_main_loop().current_scene.website_container
|
||||||
@@ -1003,3 +1029,31 @@ func _handle_download_request(operation: Dictionary):
|
|||||||
|
|
||||||
var main_node = Engine.get_main_loop().current_scene
|
var main_node = Engine.get_main_loop().current_scene
|
||||||
main_node.download_manager.handle_download_request(download_data)
|
main_node.download_manager.handle_download_request(download_data)
|
||||||
|
|
||||||
|
func _get_element_size_sync(result: Array, element_id: String):
|
||||||
|
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
|
if dom_node and dom_node is Control:
|
||||||
|
var control = dom_node as Control
|
||||||
|
result[0] = control.size.x
|
||||||
|
result[1] = control.size.y
|
||||||
|
result[2] = true # completion flag
|
||||||
|
return
|
||||||
|
|
||||||
|
# Fallback
|
||||||
|
result[0] = 0.0
|
||||||
|
result[1] = 0.0
|
||||||
|
result[2] = true # completion flag
|
||||||
|
|
||||||
|
func _get_element_position_sync(result: Array, element_id: String):
|
||||||
|
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
|
if dom_node and dom_node is Control:
|
||||||
|
var control = dom_node as Control
|
||||||
|
result[0] = control.position.x
|
||||||
|
result[1] = control.position.y
|
||||||
|
result[2] = true # completion flag
|
||||||
|
return
|
||||||
|
|
||||||
|
# Fallback
|
||||||
|
result[0] = 0.0
|
||||||
|
result[1] = 0.0
|
||||||
|
result[2] = true # completion flag
|
||||||
|
|||||||
@@ -1054,6 +1054,60 @@ static func _element_index_wrapper(vm: LuauVM) -> int:
|
|||||||
# Fallback to true (visible by default)
|
# Fallback to true (visible by default)
|
||||||
vm.lua_pushboolean(true)
|
vm.lua_pushboolean(true)
|
||||||
return 1
|
return 1
|
||||||
|
"size":
|
||||||
|
if lua_api:
|
||||||
|
vm.lua_getfield(1, "_element_id")
|
||||||
|
var element_id: String = vm.lua_tostring(-1)
|
||||||
|
vm.lua_pop(1)
|
||||||
|
|
||||||
|
var dom_node = lua_api.dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
|
if dom_node and dom_node is Control:
|
||||||
|
var result = [0.0, 0.0, false]
|
||||||
|
lua_api.call_deferred("_get_element_size_sync", result, element_id)
|
||||||
|
while not result[2]: # wait for completion flag
|
||||||
|
OS.delay_msec(1)
|
||||||
|
|
||||||
|
vm.lua_newtable()
|
||||||
|
vm.lua_pushnumber(result[0])
|
||||||
|
vm.lua_setfield(-2, "width")
|
||||||
|
vm.lua_pushnumber(result[1])
|
||||||
|
vm.lua_setfield(-2, "height")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Fallback to zero size
|
||||||
|
vm.lua_newtable()
|
||||||
|
vm.lua_pushnumber(0)
|
||||||
|
vm.lua_setfield(-2, "width")
|
||||||
|
vm.lua_pushnumber(0)
|
||||||
|
vm.lua_setfield(-2, "height")
|
||||||
|
return 1
|
||||||
|
"position":
|
||||||
|
if lua_api:
|
||||||
|
vm.lua_getfield(1, "_element_id")
|
||||||
|
var element_id: String = vm.lua_tostring(-1)
|
||||||
|
vm.lua_pop(1)
|
||||||
|
|
||||||
|
var dom_node = lua_api.dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
|
if dom_node and dom_node is Control:
|
||||||
|
var result = [0.0, 0.0, false]
|
||||||
|
lua_api.call_deferred("_get_element_position_sync", result, element_id)
|
||||||
|
while not result[2]: # wait for completion flag
|
||||||
|
OS.delay_msec(1)
|
||||||
|
|
||||||
|
vm.lua_newtable()
|
||||||
|
vm.lua_pushnumber(result[0])
|
||||||
|
vm.lua_setfield(-2, "x")
|
||||||
|
vm.lua_pushnumber(result[1])
|
||||||
|
vm.lua_setfield(-2, "y")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Fallback to zero position
|
||||||
|
vm.lua_newtable()
|
||||||
|
vm.lua_pushnumber(0)
|
||||||
|
vm.lua_setfield(-2, "x")
|
||||||
|
vm.lua_pushnumber(0)
|
||||||
|
vm.lua_setfield(-2, "y")
|
||||||
|
return 1
|
||||||
_:
|
_:
|
||||||
# Check for DOM traversal properties first
|
# Check for DOM traversal properties first
|
||||||
if lua_api:
|
if lua_api:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ static func connect_element_event(signal_node: Node, event_name: String, subscri
|
|||||||
var wrapper = func():
|
var wrapper = func():
|
||||||
LuaAudioUtils.mark_user_event()
|
LuaAudioUtils.mark_user_event()
|
||||||
LuaDownloadUtils.mark_user_event()
|
LuaDownloadUtils.mark_user_event()
|
||||||
subscription.lua_api._on_event_triggered(subscription)
|
subscription.lua_api._execute_lua_callback(subscription, [{}])
|
||||||
signal_node.pressed.connect(wrapper)
|
signal_node.pressed.connect(wrapper)
|
||||||
subscription.connected_signal = "pressed"
|
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
|
subscription.connected_node = signal_node if signal_node != subscription.lua_api.get_dom_node(signal_node.get_parent(), "signal") else null
|
||||||
|
|||||||
Reference in New Issue
Block a user