add create, append, remove, set_timeout, clear_timeout, get_children, refactor ul/ol and dynamic recounting
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bli1234568aa"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ps8duq0aw3tu" path="res://Scripts/Tags/li.gd" id="1_li"]
|
||||
|
||||
[node name="li" type="VBoxContainer"]
|
||||
anchors_preset = 10
|
||||
anchor_right = 1.0
|
||||
grow_horizontal = 2
|
||||
script = ExtResource("1_li")
|
||||
@@ -1,6 +1,5 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bopt1234568aa"]
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bopt1234568aa"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ps8duq0aw3tu" path="res://Scripts/Tags/li.gd" id="1_option"]
|
||||
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="2_theme"]
|
||||
|
||||
[node name="option" type="Control"]
|
||||
@@ -8,7 +7,6 @@ layout_mode = 3
|
||||
anchors_preset = 10
|
||||
anchor_right = 1.0
|
||||
grow_horizontal = 2
|
||||
script = ExtResource("1_option")
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
@@ -18,8 +18,8 @@ class HTMLElement:
|
||||
func has_attribute(name_: String) -> bool:
|
||||
return attributes.has(name_)
|
||||
|
||||
func get_class_name() -> String:
|
||||
return get_attribute("class")
|
||||
func set_attribute(name_: String, value: String) -> void:
|
||||
attributes.set(name_, value)
|
||||
|
||||
func get_id() -> String:
|
||||
return get_attribute("id")
|
||||
|
||||
@@ -16,6 +16,30 @@ var event_subscriptions: Dictionary = {}
|
||||
var next_subscription_id: int = 1
|
||||
var next_callback_ref: int = 1
|
||||
|
||||
var timeout_manager: LuaTimeoutManager
|
||||
var element_id_counter: int = 1
|
||||
var element_id_registry: Dictionary = {}
|
||||
|
||||
func _init():
|
||||
timeout_manager = LuaTimeoutManager.new()
|
||||
|
||||
func get_or_assign_element_id(element: HTMLParser.HTMLElement) -> String:
|
||||
var existing_id = element.get_attribute("id")
|
||||
if not existing_id.is_empty():
|
||||
element_id_registry[element] = existing_id
|
||||
return existing_id
|
||||
|
||||
if element_id_registry.has(element):
|
||||
return element_id_registry[element]
|
||||
|
||||
var new_id = "auto_" + str(element_id_counter)
|
||||
element_id_counter += 1
|
||||
|
||||
element.set_attribute("id", new_id)
|
||||
element_id_registry[element] = new_id
|
||||
|
||||
return new_id
|
||||
|
||||
func _gurt_select_handler(vm: LuauVM) -> int:
|
||||
var selector: String = vm.luaL_checkstring(1)
|
||||
|
||||
@@ -38,6 +62,87 @@ func _gurt_select_handler(vm: LuauVM) -> int:
|
||||
add_element_methods(vm)
|
||||
return 1
|
||||
|
||||
# selectAll() function to find multiple elements
|
||||
func _gurt_select_all_handler(vm: LuauVM) -> int:
|
||||
var selector: String = vm.luaL_checkstring(1)
|
||||
|
||||
var elements: Array[HTMLParser.HTMLElement] = []
|
||||
|
||||
# Handle different selector types
|
||||
if selector.begins_with("#"):
|
||||
# ID selector - find single element
|
||||
var element_id = selector.substr(1)
|
||||
var element = dom_parser.find_by_id(element_id)
|
||||
if element:
|
||||
elements.append(element)
|
||||
LuaPrintUtils.lua_print_direct("WARNING: Using ID selector in select_all is not recommended, use select instead.")
|
||||
elif selector.begins_with("."):
|
||||
# Class selector - find all elements with class
|
||||
var cls = selector.substr(1)
|
||||
for element in dom_parser.parse_result.all_elements:
|
||||
var element_classes = CSSParser.smart_split_utility_classes(element.get_attribute("style"))
|
||||
if cls in element_classes:
|
||||
elements.append(element)
|
||||
else:
|
||||
# Tag selector - find all elements with tag name
|
||||
elements = dom_parser.find_all(selector)
|
||||
|
||||
vm.lua_newtable()
|
||||
var index = 1
|
||||
|
||||
for element in elements:
|
||||
var element_id = get_or_assign_element_id(element)
|
||||
|
||||
# Create element wrapper
|
||||
vm.lua_newtable()
|
||||
vm.lua_pushstring(element_id)
|
||||
vm.lua_setfield(-2, "_element_id")
|
||||
vm.lua_pushstring(element.tag_name)
|
||||
vm.lua_setfield(-2, "_tag_name")
|
||||
|
||||
add_element_methods(vm)
|
||||
|
||||
# Add to array at index
|
||||
vm.lua_rawseti(-2, index)
|
||||
index += 1
|
||||
|
||||
return 1
|
||||
|
||||
# create() function to create HTML element
|
||||
func _gurt_create_handler(vm: LuauVM) -> int:
|
||||
var tag_name: String = vm.luaL_checkstring(1)
|
||||
var options: Dictionary = {}
|
||||
|
||||
if vm.lua_gettop() >= 2 and vm.lua_istable(2):
|
||||
options = vm.lua_todictionary(2)
|
||||
|
||||
var element = HTMLParser.HTMLElement.new(tag_name)
|
||||
|
||||
# Apply options as attributes and content
|
||||
for key in options:
|
||||
if key == "text":
|
||||
element.text_content = str(options[key])
|
||||
else:
|
||||
element.attributes[str(key)] = str(options[key])
|
||||
|
||||
# Add to parser's element collection first
|
||||
dom_parser.parse_result.all_elements.append(element)
|
||||
|
||||
# Get or assign stable ID
|
||||
var unique_id = get_or_assign_element_id(element)
|
||||
|
||||
# Create Lua element wrapper with methods
|
||||
vm.lua_newtable()
|
||||
vm.lua_pushstring(unique_id)
|
||||
vm.lua_setfield(-2, "_element_id")
|
||||
vm.lua_pushstring(tag_name)
|
||||
vm.lua_setfield(-2, "_tag_name")
|
||||
vm.lua_pushboolean(true)
|
||||
vm.lua_setfield(-2, "_is_dynamic")
|
||||
|
||||
add_element_methods(vm)
|
||||
return 1
|
||||
|
||||
func add_element_methods(vm: LuauVM) -> void:
|
||||
vm.lua_pushcallable(_element_set_text_handler, "element.set_text")
|
||||
vm.lua_setfield(-2, "set_text")
|
||||
@@ -47,6 +152,45 @@ func add_element_methods(vm: LuauVM) -> void:
|
||||
|
||||
vm.lua_pushcallable(_element_on_event_handler, "element.on")
|
||||
vm.lua_setfield(-2, "on")
|
||||
|
||||
vm.lua_pushcallable(_element_append_handler, "element.append")
|
||||
vm.lua_setfield(-2, "append")
|
||||
|
||||
vm.lua_pushcallable(_element_remove_handler, "element.remove")
|
||||
vm.lua_setfield(-2, "remove")
|
||||
|
||||
vm.lua_pushcallable(_element_get_children_handler, "element.get_children")
|
||||
vm.lua_setfield(-2, "get_children")
|
||||
|
||||
func _element_get_children_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find the element
|
||||
var element: HTMLParser.HTMLElement = null
|
||||
if element_id == "body":
|
||||
element = dom_parser.find_first("body")
|
||||
else:
|
||||
element = dom_parser.find_by_id(element_id)
|
||||
|
||||
vm.lua_newtable()
|
||||
var index = 1
|
||||
|
||||
if element:
|
||||
for child in element.children:
|
||||
vm.lua_newtable()
|
||||
vm.lua_pushstring(child.tag_name)
|
||||
vm.lua_setfield(-2, "tag_name")
|
||||
vm.lua_pushstring(child.get_text_content())
|
||||
vm.lua_setfield(-2, "text")
|
||||
|
||||
vm.lua_rawseti(-2, index)
|
||||
index += 1
|
||||
|
||||
return 1
|
||||
|
||||
# Element manipulation handlers
|
||||
func _element_set_text_handler(vm: LuauVM) -> int:
|
||||
@@ -83,6 +227,129 @@ func _element_get_text_handler(vm: LuauVM) -> int:
|
||||
vm.lua_pushstring(text)
|
||||
return 1
|
||||
|
||||
# append() function to add a child element
|
||||
func _element_append_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
vm.luaL_checktype(2, vm.LUA_TTABLE)
|
||||
|
||||
# Get parent element info
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var parent_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get child element info
|
||||
vm.lua_getfield(2, "_element_id")
|
||||
var child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
vm.lua_getfield(2, "_is_dynamic")
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find parent element
|
||||
var parent_element: HTMLParser.HTMLElement = null
|
||||
if parent_element_id == "body":
|
||||
parent_element = dom_parser.find_first("body")
|
||||
else:
|
||||
parent_element = dom_parser.find_by_id(parent_element_id)
|
||||
|
||||
if not parent_element:
|
||||
return 0
|
||||
|
||||
# Find child element
|
||||
var child_element = dom_parser.find_by_id(child_element_id)
|
||||
if not child_element:
|
||||
return 0
|
||||
|
||||
# Add child to parent in DOM tree
|
||||
child_element.parent = parent_element
|
||||
parent_element.children.append(child_element)
|
||||
|
||||
# If the parent is already rendered, we need to create and add the visual node
|
||||
var parent_dom_node: Node = null
|
||||
if parent_element_id == "body":
|
||||
var main_scene = get_node("/root/Main")
|
||||
if main_scene:
|
||||
parent_dom_node = main_scene.website_container
|
||||
else:
|
||||
parent_dom_node = dom_parser.parse_result.dom_nodes.get(parent_element_id, null)
|
||||
|
||||
if parent_dom_node:
|
||||
_render_new_element.call_deferred(child_element, parent_dom_node)
|
||||
|
||||
return 0
|
||||
|
||||
# remove() function to remove an element
|
||||
func _element_remove_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find the element in DOM
|
||||
var element = dom_parser.find_by_id(element_id)
|
||||
if not element:
|
||||
return 0
|
||||
|
||||
# Remove from parent's children array
|
||||
if element.parent:
|
||||
var parent_children = element.parent.children
|
||||
var idx = parent_children.find(element)
|
||||
if idx >= 0:
|
||||
parent_children.remove_at(idx)
|
||||
|
||||
# Remove the visual node
|
||||
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||
if dom_node:
|
||||
dom_node.queue_free()
|
||||
dom_parser.parse_result.dom_nodes.erase(element_id)
|
||||
|
||||
# Remove from all_elements array
|
||||
var all_elements = dom_parser.parse_result.all_elements
|
||||
var index = all_elements.find(element)
|
||||
if index >= 0:
|
||||
all_elements.remove_at(index)
|
||||
|
||||
# Remove from element_id_registry to avoid memory leaks
|
||||
if element_id_registry.has(element):
|
||||
element_id_registry.erase(element)
|
||||
|
||||
return 0
|
||||
|
||||
func _render_new_element(element: HTMLParser.HTMLElement, parent_node: Node) -> void:
|
||||
# Get reference to main scene for rendering
|
||||
var main_scene = get_node("/root/Main")
|
||||
if not main_scene:
|
||||
return
|
||||
|
||||
# Create the visual node for the element
|
||||
var element_node = await main_scene.create_element_node(element, dom_parser)
|
||||
if not element_node:
|
||||
LuaPrintUtils.lua_print_direct("Failed to create visual node for element: " + str(element))
|
||||
return
|
||||
|
||||
# Set metadata so ul/ol can detect dynamically added li elements
|
||||
element_node.set_meta("html_element", element)
|
||||
|
||||
# Register the DOM node
|
||||
dom_parser.register_dom_node(element, element_node)
|
||||
|
||||
# Add to parent - handle body special case
|
||||
var container_node = parent_node
|
||||
if parent_node is MarginContainer and parent_node.get_child_count() > 0:
|
||||
container_node = parent_node.get_child(0)
|
||||
elif parent_node == main_scene.website_container:
|
||||
container_node = parent_node
|
||||
|
||||
main_scene.safe_add_child(container_node, element_node)
|
||||
|
||||
# Timeout management handlers
|
||||
func _gurt_set_timeout_handler(vm: LuauVM) -> int:
|
||||
return timeout_manager.set_timeout_handler(vm, self)
|
||||
|
||||
func _gurt_clear_timeout_handler(vm: LuauVM) -> int:
|
||||
return timeout_manager.clear_timeout_handler(vm)
|
||||
|
||||
# Event system handlers
|
||||
func _element_on_event_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
@@ -590,7 +590,8 @@ var HTML_CONTENT3 = """<head>
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
|
||||
var HTML_CONTENT = """<head>
|
||||
var HTML_CONTENT = """
|
||||
<head>
|
||||
<title>Lua API Demo</title>
|
||||
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
||||
<meta name="theme-color" content="#000080">
|
||||
@@ -663,6 +664,38 @@ var HTML_CONTENT = """<head>
|
||||
else
|
||||
gurt.log('Could not find button or event log element')
|
||||
end
|
||||
|
||||
-- DOM Manipulation Demo
|
||||
gurt.log('Testing DOM manipulation...')
|
||||
|
||||
-- Create a new div with styling
|
||||
local new_div = gurt.create('div', { style = 'bg-red-500 p-4 rounded-lg mb-4' })
|
||||
|
||||
-- Create a paragraph with text
|
||||
local new_p = gurt.create('p', {
|
||||
style = 'text-white font-bold text-lg',
|
||||
text = 'This element was created dynamically with Lua!'
|
||||
})
|
||||
|
||||
-- Append paragraph to div
|
||||
new_div:append(new_p)
|
||||
|
||||
-- Append div to body
|
||||
gurt.body:append(new_div)
|
||||
|
||||
-- Create another element to test removal
|
||||
local temp_element = gurt.create('div', {
|
||||
style = 'bg-yellow-400 p-2 rounded text-black',
|
||||
text = 'This will be removed in 3 seconds...'
|
||||
})
|
||||
gurt.body:append(temp_element)
|
||||
|
||||
local test = gurt.set_timeout(function()
|
||||
print('removed')
|
||||
temp_element:remove()
|
||||
end, 3000)
|
||||
|
||||
-- gurt.clear_timeout(test)
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -681,5 +714,61 @@ var HTML_CONTENT = """<head>
|
||||
<p id="btnmouse" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Move mouse over Button</p>
|
||||
|
||||
<p id="type" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Type something</p>
|
||||
</body>""".to_utf8_buffer()
|
||||
|
||||
var HTML_CONTENT_ADD_REMOVE = """<head>
|
||||
<title>Lua List Manipulation Demo</title>
|
||||
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
||||
<meta name="theme-color" content="#000080">
|
||||
<meta name="description" content="Adding and popping list items with GURT Lua API">
|
||||
|
||||
<style>
|
||||
body { bg-[#f8f9fa] p-6 }
|
||||
h1 { text-[#2563eb] text-4xl font-bold }
|
||||
.container { flex flex-row bg-[#ffffff] p-4 rounded-lg shadow-lg }
|
||||
.demo-button { bg-[#3b82f6] text-white px-4 py-2 rounded hover:bg-[#2563eb] cursor-pointer }
|
||||
ul { list-disc pl-6 }
|
||||
li { text-[#111827] py-1 }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
local add_button = gurt.select('#add-button')
|
||||
local pop_button = gurt.select('#pop-button')
|
||||
local list = gurt.select('#item-list')
|
||||
local counter = 1
|
||||
|
||||
gurt.log('List manipulation script started.')
|
||||
|
||||
add_button:on('click', function()
|
||||
local new_item = gurt.create('li', {
|
||||
text = 'Item #' .. counter
|
||||
})
|
||||
list:append(new_item)
|
||||
counter = counter + 1
|
||||
end)
|
||||
|
||||
pop_button:on('click', function()
|
||||
local items = list:get_children()
|
||||
local last = items[#items]
|
||||
if last then
|
||||
last:remove()
|
||||
counter = math.max(1, counter - 1)
|
||||
end
|
||||
end)
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="main-heading">List Manipulation with Lua</h1>
|
||||
|
||||
<div style="container">
|
||||
<p>Use the buttons below to add or remove items from the list:</p>
|
||||
<button id="add-button" style="demo-button inline-block mr-2">Add Item</button>
|
||||
<button id="pop-button" style="demo-button inline-block">Pop Item</button>
|
||||
</div>
|
||||
|
||||
<ul id="item-list" style="mt-4 bg-[#f3f4f6] p-4 rounded min-h-24">
|
||||
<!-- List items will appear here -->
|
||||
</ul>
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
|
||||
@@ -204,7 +204,16 @@ static func apply_margin_wrapper(node: Control, styles: Dictionary) -> Control:
|
||||
node.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
node.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
|
||||
margin_container.add_child(node)
|
||||
# Handle reparenting properly
|
||||
var original_parent = node.get_parent()
|
||||
if original_parent:
|
||||
var node_index = node.get_index()
|
||||
original_parent.remove_child(node)
|
||||
margin_container.add_child(node)
|
||||
original_parent.add_child(margin_container)
|
||||
original_parent.move_child(margin_container, node_index)
|
||||
else:
|
||||
margin_container.add_child(node)
|
||||
|
||||
return margin_container
|
||||
|
||||
|
||||
282
flumi/Scripts/Tags/BaseListContainer.gd
Normal file
282
flumi/Scripts/Tags/BaseListContainer.gd
Normal file
@@ -0,0 +1,282 @@
|
||||
class_name BaseListContainer
|
||||
extends VBoxContainer
|
||||
|
||||
const BROWSER_TEXT = preload("res://Scenes/Styles/BrowserText.tres")
|
||||
|
||||
var list_type: String
|
||||
var marker_width: float
|
||||
var parser_ref: HTMLParser = null
|
||||
var is_ordered: bool = false
|
||||
|
||||
func _ready():
|
||||
child_entered_tree.connect(_on_child_added)
|
||||
child_exiting_tree.connect(_on_child_removed)
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||
list_type = element.get_attribute("type").to_lower()
|
||||
if list_type == "":
|
||||
list_type = "disc" if not is_ordered else "decimal"
|
||||
parser_ref = parser
|
||||
|
||||
marker_width = await calculate_marker_width(element)
|
||||
|
||||
var index = 1
|
||||
for child_element in element.children:
|
||||
if child_element.tag_name == "li":
|
||||
var li_node = create_li_node(child_element, index, parser)
|
||||
if li_node:
|
||||
add_child(li_node)
|
||||
index += 1
|
||||
|
||||
func calculate_marker_width(element: HTMLParser.HTMLElement) -> float:
|
||||
var temp_label = RichTextLabel.new()
|
||||
temp_label.bbcode_enabled = true
|
||||
temp_label.fit_content = true
|
||||
temp_label.scroll_active = false
|
||||
temp_label.theme = BROWSER_TEXT
|
||||
add_child(temp_label)
|
||||
|
||||
var sample_text = ""
|
||||
if is_ordered:
|
||||
var item_count = 0
|
||||
for child_element in element.children:
|
||||
if child_element.tag_name == "li":
|
||||
item_count += 1
|
||||
sample_text = str(item_count) + "."
|
||||
else:
|
||||
match list_type:
|
||||
"circle":
|
||||
sample_text = "◦"
|
||||
"disc":
|
||||
sample_text = "•"
|
||||
"square":
|
||||
sample_text = "■"
|
||||
"none":
|
||||
sample_text = " "
|
||||
_:
|
||||
sample_text = "•"
|
||||
|
||||
StyleManager.apply_styles_to_label(temp_label, {}, null, null, sample_text)
|
||||
|
||||
await get_tree().process_frame
|
||||
|
||||
var width = temp_label.get_content_width() + 5
|
||||
|
||||
remove_child(temp_label)
|
||||
temp_label.queue_free()
|
||||
|
||||
return max(width, 20.0 if not is_ordered else 30.0)
|
||||
|
||||
func create_li_node(element: HTMLParser.HTMLElement, index: int, parser: HTMLParser = null) -> Control:
|
||||
var li_container = HBoxContainer.new()
|
||||
|
||||
# Create marker
|
||||
var marker_label = RichTextLabel.new()
|
||||
marker_label.custom_minimum_size = Vector2(marker_width, 0)
|
||||
marker_label.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
marker_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
marker_label.bbcode_enabled = true
|
||||
marker_label.fit_content = true
|
||||
marker_label.scroll_active = false
|
||||
marker_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
marker_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
marker_label.theme = BROWSER_TEXT
|
||||
|
||||
var marker_text = get_marker_text(index)
|
||||
var marker_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(marker_label, marker_styles, element, parser, marker_text)
|
||||
|
||||
# Create content
|
||||
var content_label = RichTextLabel.new()
|
||||
content_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
content_label.bbcode_enabled = true
|
||||
content_label.fit_content = true
|
||||
content_label.scroll_active = false
|
||||
content_label.theme = BROWSER_TEXT
|
||||
|
||||
var content_text = element.get_bbcode_formatted_text(parser)
|
||||
var content_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(content_label, content_styles, element, parser, content_text)
|
||||
|
||||
li_container.add_theme_constant_override("separation", 0)
|
||||
li_container.add_child(marker_label)
|
||||
li_container.add_child(content_label)
|
||||
|
||||
# Store element metadata on the container for renumbering
|
||||
li_container.set_meta("html_element", element)
|
||||
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
if BackgroundUtils.needs_background_wrapper(styles):
|
||||
var panel_container = BackgroundUtils.create_panel_container_with_background(styles)
|
||||
panel_container.name = "Li"
|
||||
# Store element metadata on the panel container too
|
||||
panel_container.set_meta("html_element", element)
|
||||
# Get the VBoxContainer inside PanelContainer and replace it with our HBoxContainer
|
||||
var vbox = panel_container.get_child(0)
|
||||
panel_container.remove_child(vbox)
|
||||
vbox.queue_free()
|
||||
panel_container.add_child(li_container)
|
||||
return panel_container
|
||||
else:
|
||||
return li_container
|
||||
|
||||
func _on_child_added(child: Node):
|
||||
if child.has_meta("html_element"):
|
||||
var element = child.get_meta("html_element")
|
||||
if element is HTMLParser.HTMLElement and element.tag_name == "li":
|
||||
|
||||
call_deferred("_process_dynamic_li", child, element)
|
||||
|
||||
func _process_dynamic_li(child: Node, element: HTMLParser.HTMLElement):
|
||||
child_entered_tree.disconnect(_on_child_added)
|
||||
|
||||
# Get the correct index for this new item
|
||||
var current_li_count = 0
|
||||
for existing_child in get_children():
|
||||
if existing_child != child:
|
||||
current_li_count += 1
|
||||
|
||||
# Remove the basic li node and replace with properly formatted one
|
||||
if child.get_parent() == self:
|
||||
remove_child(child)
|
||||
var li_node = create_li_node(element, current_li_count + 1, parser_ref)
|
||||
if li_node:
|
||||
var element_id = element.get_attribute("id")
|
||||
if parser_ref and element_id:
|
||||
parser_ref.parse_result.dom_nodes[element_id] = li_node
|
||||
add_child(li_node)
|
||||
child.queue_free()
|
||||
|
||||
# Reconnect signal
|
||||
child_entered_tree.connect(_on_child_added)
|
||||
|
||||
func _on_child_removed(_child: Node):
|
||||
if is_ordered: # Only OL needs renumbering
|
||||
call_deferred("_renumber_list")
|
||||
|
||||
func _renumber_list():
|
||||
# Temporarily disconnect signals to avoid recursion
|
||||
child_entered_tree.disconnect(_on_child_added)
|
||||
child_exiting_tree.disconnect(_on_child_removed)
|
||||
|
||||
# Get all current li children
|
||||
var li_children = []
|
||||
for child in get_children():
|
||||
var is_li = false
|
||||
if child is HBoxContainer:
|
||||
is_li = true
|
||||
elif child is PanelContainer and child.get_child_count() > 0:
|
||||
var inner_child = child.get_child(0)
|
||||
if inner_child is HBoxContainer:
|
||||
is_li = true
|
||||
|
||||
if is_li:
|
||||
li_children.append(child)
|
||||
|
||||
# Renumber all existing items
|
||||
for i in range(li_children.size()):
|
||||
var child = li_children[i]
|
||||
var marker_label = null
|
||||
|
||||
# Find the marker label within the child structure
|
||||
if child is HBoxContainer and child.get_child_count() > 0:
|
||||
marker_label = child.get_child(0)
|
||||
elif child is PanelContainer and child.get_child_count() > 0:
|
||||
var hbox = child.get_child(0)
|
||||
if hbox is HBoxContainer and hbox.get_child_count() > 0:
|
||||
marker_label = hbox.get_child(0)
|
||||
|
||||
# Update the marker text - recreate it completely to avoid BBCode corruption
|
||||
if marker_label and marker_label is RichTextLabel:
|
||||
var index = i + 1
|
||||
var new_marker_text = get_marker_text(index)
|
||||
# Get the HTMLElement from the li container to reapply styles properly
|
||||
var element = null
|
||||
if child.has_meta("html_element"):
|
||||
element = child.get_meta("html_element")
|
||||
elif child is PanelContainer and child.get_child_count() > 0:
|
||||
var hbox = child.get_child(0)
|
||||
if hbox.has_meta("html_element"):
|
||||
element = hbox.get_meta("html_element")
|
||||
|
||||
if element and parser_ref:
|
||||
var marker_styles = parser_ref.get_element_styles_with_inheritance(element, "", [])
|
||||
StyleManager.apply_styles_to_label(marker_label, marker_styles, element, parser_ref, new_marker_text)
|
||||
else:
|
||||
# Fallback - just set the text
|
||||
marker_label.text = new_marker_text
|
||||
|
||||
# Reconnect signals
|
||||
child_entered_tree.connect(_on_child_added)
|
||||
child_exiting_tree.connect(_on_child_removed)
|
||||
|
||||
func refresh_list():
|
||||
# Force refresh of all li children for dynamically added content
|
||||
var children_to_process = []
|
||||
for child in get_children():
|
||||
if child.has_meta("html_element"):
|
||||
var element = child.get_meta("html_element")
|
||||
if element is HTMLParser.HTMLElement and element.tag_name == "li":
|
||||
children_to_process.append([child, element])
|
||||
|
||||
# Clear all children first
|
||||
for child_data in children_to_process:
|
||||
var child = child_data[0]
|
||||
remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
# Recalculate marker width if needed
|
||||
var new_count = children_to_process.size()
|
||||
if new_count > 0 and is_ordered:
|
||||
marker_width = await calculate_marker_width(children_to_process[0][1])
|
||||
|
||||
# Re-add with correct indices
|
||||
for i in range(children_to_process.size()):
|
||||
var element = children_to_process[i][1]
|
||||
var li_node = create_li_node(element, i + 1, parser_ref)
|
||||
if li_node:
|
||||
add_child(li_node)
|
||||
|
||||
func int_to_roman(num: int) -> String:
|
||||
var values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
|
||||
var symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
|
||||
var result = ""
|
||||
|
||||
for i in range(values.size()):
|
||||
while num >= values[i]:
|
||||
result += symbols[i]
|
||||
num -= values[i]
|
||||
|
||||
return result
|
||||
|
||||
func get_marker_text(index: int) -> String:
|
||||
if is_ordered:
|
||||
match list_type:
|
||||
"decimal":
|
||||
return str(index) + "."
|
||||
"zero-lead":
|
||||
return "%02d." % index
|
||||
"lower-alpha":
|
||||
return char(96 + index) + "."
|
||||
"lower-roman":
|
||||
return int_to_roman(index).to_lower() + "."
|
||||
"upper-alpha":
|
||||
return char(64 + index) + "."
|
||||
"upper-roman":
|
||||
return int_to_roman(index) + "."
|
||||
"none":
|
||||
return ""
|
||||
_:
|
||||
return str(index) + "."
|
||||
else:
|
||||
match list_type:
|
||||
"circle":
|
||||
return "◦"
|
||||
"disc":
|
||||
return "•"
|
||||
"square":
|
||||
return "■"
|
||||
"none":
|
||||
return " "
|
||||
_:
|
||||
return "•"
|
||||
1
flumi/Scripts/Tags/BaseListContainer.gd.uid
Normal file
1
flumi/Scripts/Tags/BaseListContainer.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cbdk823naa108
|
||||
@@ -1,8 +0,0 @@
|
||||
extends Control
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||
# This is mainly for cases where <li> appears outside of <ul>/<ol>
|
||||
var label: RichTextLabel = $RichTextLabel
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
|
||||
StyleManager.apply_styles_to_label(label, styles, element, parser)
|
||||
@@ -1 +0,0 @@
|
||||
uid://ps8duq0aw3tu
|
||||
@@ -1,117 +1,5 @@
|
||||
extends VBoxContainer
|
||||
extends BaseListContainer
|
||||
|
||||
const BROWSER_TEXT = preload("res://Scenes/Styles/BrowserText.tres")
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||
var list_type = element.get_attribute("type").to_lower()
|
||||
if list_type == "": list_type = "decimal" # Default
|
||||
|
||||
var item_count = 0
|
||||
for child_element in element.children:
|
||||
if child_element.tag_name == "li":
|
||||
item_count += 1
|
||||
|
||||
var marker_min_width = await calculate_marker_width(list_type, item_count)
|
||||
|
||||
var index = 1
|
||||
for child_element in element.children:
|
||||
if child_element.tag_name == "li":
|
||||
var li_node = create_li_node(child_element, list_type, index, marker_min_width, parser)
|
||||
if li_node:
|
||||
add_child(li_node)
|
||||
index += 1
|
||||
|
||||
func calculate_marker_width(list_type: String, max_index: int) -> float:
|
||||
var temp_label = RichTextLabel.new()
|
||||
temp_label.bbcode_enabled = true
|
||||
temp_label.fit_content = true
|
||||
temp_label.scroll_active = false
|
||||
temp_label.theme = BROWSER_TEXT
|
||||
add_child(temp_label)
|
||||
|
||||
var marker_text = get_marker_for_type(list_type, max_index)
|
||||
StyleManager.apply_styles_to_label(temp_label, {}, null, null, marker_text)
|
||||
|
||||
await get_tree().process_frame
|
||||
|
||||
var width = temp_label.get_content_width() + 5
|
||||
|
||||
remove_child(temp_label)
|
||||
temp_label.queue_free()
|
||||
|
||||
return max(width, 30) # Minimum pixels
|
||||
|
||||
func create_li_node(element: HTMLParser.HTMLElement, list_type: String, index: int, marker_width: float = 30, parser: HTMLParser = null) -> Control:
|
||||
var li_container = HBoxContainer.new()
|
||||
|
||||
# Create number/letter marker
|
||||
var marker_label = RichTextLabel.new()
|
||||
marker_label.custom_minimum_size = Vector2(marker_width, 0)
|
||||
marker_label.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
marker_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
marker_label.bbcode_enabled = true
|
||||
marker_label.fit_content = true
|
||||
marker_label.scroll_active = false
|
||||
marker_label.theme = BROWSER_TEXT
|
||||
|
||||
var marker_text = get_marker_for_type(list_type, index)
|
||||
|
||||
var marker_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(marker_label, marker_styles, element, parser, marker_text)
|
||||
|
||||
# Create content
|
||||
var content_label = RichTextLabel.new()
|
||||
content_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
content_label.bbcode_enabled = true
|
||||
content_label.fit_content = true
|
||||
content_label.scroll_active = false
|
||||
content_label.theme = BROWSER_TEXT
|
||||
|
||||
var content_text = element.get_bbcode_formatted_text(parser)
|
||||
|
||||
var content_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(content_label, content_styles, element, parser, content_text)
|
||||
|
||||
li_container.add_theme_constant_override("separation", 0)
|
||||
li_container.add_child(marker_label)
|
||||
li_container.add_child(content_label)
|
||||
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
if BackgroundUtils.needs_background_wrapper(styles):
|
||||
var panel_container = BackgroundUtils.create_panel_container_with_background(styles)
|
||||
panel_container.name = "Li"
|
||||
# Get the VBoxContainer inside PanelContainer and replace it with our HBoxContainer
|
||||
var vbox = panel_container.get_child(0)
|
||||
panel_container.remove_child(vbox)
|
||||
vbox.queue_free()
|
||||
panel_container.add_child(li_container)
|
||||
return panel_container
|
||||
else:
|
||||
return li_container
|
||||
|
||||
func get_marker_for_type(list_type: String, index: int) -> String:
|
||||
match list_type:
|
||||
"decimal":
|
||||
return str(index) + "."
|
||||
"zero-lead":
|
||||
return "%02d." % index
|
||||
"lower-alpha", "lower-roman":
|
||||
return char(96 + index) + "." if list_type == "lower-alpha" else int_to_roman(index).to_lower() + "."
|
||||
"upper-alpha", "upper-roman":
|
||||
return char(64 + index) + "." if list_type == "upper-alpha" else int_to_roman(index) + "."
|
||||
"none":
|
||||
return ""
|
||||
_:
|
||||
return str(index) + "." # Default to decimal
|
||||
|
||||
func int_to_roman(num: int) -> String:
|
||||
var values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
|
||||
var symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
|
||||
var result = ""
|
||||
|
||||
for i in range(values.size()):
|
||||
while num >= values[i]:
|
||||
result += symbols[i]
|
||||
num -= values[i]
|
||||
|
||||
return result
|
||||
func _ready():
|
||||
is_ordered = true
|
||||
super._ready()
|
||||
|
||||
@@ -1,97 +1,5 @@
|
||||
extends VBoxContainer
|
||||
extends BaseListContainer
|
||||
|
||||
const BROWSER_TEXT = preload("res://Scenes/Styles/BrowserText.tres")
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||
var list_type = element.get_attribute("type").to_lower()
|
||||
if list_type == "": list_type = "disc" # Default
|
||||
|
||||
var marker_min_width = await calculate_marker_width(list_type)
|
||||
|
||||
for child_element in element.children:
|
||||
if child_element.tag_name == "li":
|
||||
var li_node = create_li_node(child_element, list_type, marker_min_width, parser)
|
||||
if li_node:
|
||||
add_child(li_node)
|
||||
|
||||
func calculate_marker_width(list_type: String) -> float:
|
||||
var temp_label = RichTextLabel.new()
|
||||
temp_label.bbcode_enabled = true
|
||||
temp_label.fit_content = true
|
||||
temp_label.scroll_active = false
|
||||
temp_label.theme = BROWSER_TEXT
|
||||
add_child(temp_label)
|
||||
|
||||
var bullet_text = get_bullet_for_type(list_type)
|
||||
StyleManager.apply_styles_to_label(temp_label, {}, null, null, bullet_text)
|
||||
|
||||
await get_tree().process_frame
|
||||
|
||||
var width = temp_label.get_content_width() + 5 # padding
|
||||
|
||||
remove_child(temp_label)
|
||||
temp_label.queue_free()
|
||||
|
||||
return max(width, 20) # Minimum pixels
|
||||
|
||||
func create_li_node(element: HTMLParser.HTMLElement, list_type: String, marker_width: float = 20, parser: HTMLParser = null) -> Control:
|
||||
var li_container = HBoxContainer.new()
|
||||
|
||||
# Create bullet point
|
||||
var bullet_label = RichTextLabel.new()
|
||||
bullet_label.custom_minimum_size = Vector2(marker_width, 0)
|
||||
bullet_label.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
bullet_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
bullet_label.bbcode_enabled = true
|
||||
bullet_label.fit_content = true
|
||||
bullet_label.scroll_active = false
|
||||
bullet_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
bullet_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
bullet_label.theme = BROWSER_TEXT
|
||||
|
||||
var bullet_text = get_bullet_for_type(list_type)
|
||||
|
||||
var bullet_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(bullet_label, bullet_styles, element, parser, bullet_text)
|
||||
|
||||
# Create content
|
||||
var content_label = RichTextLabel.new()
|
||||
content_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
content_label.bbcode_enabled = true
|
||||
content_label.fit_content = true
|
||||
content_label.theme = BROWSER_TEXT
|
||||
content_label.scroll_active = false
|
||||
var content_text = element.get_bbcode_formatted_text(parser)
|
||||
|
||||
var content_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||
StyleManager.apply_styles_to_label(content_label, content_styles, element, parser, content_text)
|
||||
|
||||
li_container.add_theme_constant_override("separation", 0)
|
||||
li_container.add_child(bullet_label)
|
||||
li_container.add_child(content_label)
|
||||
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
if BackgroundUtils.needs_background_wrapper(styles):
|
||||
var panel_container = BackgroundUtils.create_panel_container_with_background(styles)
|
||||
panel_container.name = "Li"
|
||||
# Get the VBoxContainer inside PanelContainer and replace it with our HBoxContainer
|
||||
var vbox = panel_container.get_child(0)
|
||||
panel_container.remove_child(vbox)
|
||||
vbox.queue_free()
|
||||
panel_container.add_child(li_container)
|
||||
return panel_container
|
||||
else:
|
||||
return li_container
|
||||
|
||||
func get_bullet_for_type(list_type: String) -> String:
|
||||
match list_type:
|
||||
"circle":
|
||||
return "◦"
|
||||
"disc":
|
||||
return "•"
|
||||
"square":
|
||||
return "■"
|
||||
"none":
|
||||
return " "
|
||||
_:
|
||||
return "•" # Default to disc
|
||||
func _ready():
|
||||
is_ordered = false
|
||||
super._ready()
|
||||
|
||||
@@ -35,6 +35,18 @@ static func setup_gurt_api(vm: LuauVM, lua_api, dom_parser: HTMLParser) -> void:
|
||||
vm.lua_pushcallable(lua_api._gurt_select_handler, "gurt.select")
|
||||
vm.lua_setfield(-2, "select")
|
||||
|
||||
vm.lua_pushcallable(lua_api._gurt_select_all_handler, "gurt.select_all")
|
||||
vm.lua_setfield(-2, "select_all")
|
||||
|
||||
vm.lua_pushcallable(lua_api._gurt_create_handler, "gurt.create")
|
||||
vm.lua_setfield(-2, "create")
|
||||
|
||||
vm.lua_pushcallable(lua_api._gurt_set_timeout_handler, "gurt.set_timeout")
|
||||
vm.lua_setfield(-2, "set_timeout")
|
||||
|
||||
vm.lua_pushcallable(lua_api._gurt_clear_timeout_handler, "gurt.clear_timeout")
|
||||
vm.lua_setfield(-2, "clear_timeout")
|
||||
|
||||
# Add body element access
|
||||
var body_element = dom_parser.find_first("body")
|
||||
if body_element:
|
||||
@@ -52,6 +64,9 @@ static func setup_gurt_api(vm: LuauVM, lua_api, dom_parser: HTMLParser) -> void:
|
||||
vm.lua_pushcallable(lua_api._body_on_event_handler, "body.on")
|
||||
vm.lua_setfield(-2, "on")
|
||||
|
||||
vm.lua_pushcallable(lua_api._element_append_handler, "body.append")
|
||||
vm.lua_setfield(-2, "append")
|
||||
|
||||
vm.lua_setfield(-2, "body")
|
||||
|
||||
vm.lua_setglobal("gurt")
|
||||
|
||||
@@ -10,9 +10,12 @@ static func lua_print(vm: LuauVM) -> int:
|
||||
message_parts.append(value_str)
|
||||
|
||||
var final_message = "\t".join(message_parts)
|
||||
print("GURT LOG: ", final_message)
|
||||
lua_print_direct(final_message)
|
||||
return 0
|
||||
|
||||
static func lua_print_direct(msg) -> void:
|
||||
print("GURT LOG: ", msg)
|
||||
|
||||
static func lua_value_to_string(vm: LuauVM, index: int) -> String:
|
||||
var lua_type = vm.lua_type(index)
|
||||
|
||||
@@ -84,4 +87,4 @@ static func table_to_string(vm: LuauVM, index: int, max_depth: int = 3, current_
|
||||
result += ", ..."
|
||||
|
||||
result += "}"
|
||||
return result
|
||||
return result
|
||||
|
||||
102
flumi/Scripts/Utils/Lua/Timeout.gd
Normal file
102
flumi/Scripts/Utils/Lua/Timeout.gd
Normal file
@@ -0,0 +1,102 @@
|
||||
class_name LuaTimeoutManager
|
||||
extends RefCounted
|
||||
|
||||
var active_timeouts: Dictionary = {}
|
||||
var next_timeout_id: int = 1
|
||||
var next_callback_ref: int = 1
|
||||
|
||||
class TimeoutInfo:
|
||||
var id: int
|
||||
var callback_ref: int
|
||||
var vm: LuauVM
|
||||
var timer: Timer
|
||||
var timeout_manager: LuaTimeoutManager
|
||||
|
||||
func _init(timeout_id: int, cb_ref: int, lua_vm: LuauVM, manager: LuaTimeoutManager):
|
||||
id = timeout_id
|
||||
callback_ref = cb_ref
|
||||
vm = lua_vm
|
||||
timeout_manager = manager
|
||||
|
||||
func set_timeout_handler(vm: LuauVM, parent_node: Node) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TFUNCTION)
|
||||
var delay_ms: int = vm.luaL_checkint(2)
|
||||
|
||||
var timeout_id = next_timeout_id
|
||||
next_timeout_id += 1
|
||||
|
||||
# Store the callback function in the registry
|
||||
vm.lua_pushvalue(1)
|
||||
var callback_ref = vm.luaL_ref(vm.LUA_REGISTRYINDEX)
|
||||
|
||||
# Create timeout info
|
||||
var timeout_info = TimeoutInfo.new(timeout_id, callback_ref, vm, self)
|
||||
|
||||
# Create and configure timer
|
||||
var timer = Timer.new()
|
||||
timer.wait_time = delay_ms / 1000.0
|
||||
timer.one_shot = true
|
||||
timer.timeout.connect(_on_timeout_triggered.bind(timeout_info))
|
||||
|
||||
timeout_info.timer = timer
|
||||
active_timeouts[timeout_id] = timeout_info
|
||||
|
||||
# Add timer to scene tree
|
||||
parent_node.add_child(timer)
|
||||
timer.start()
|
||||
|
||||
# Return timeout ID
|
||||
vm.lua_pushinteger(timeout_id)
|
||||
return 1
|
||||
|
||||
func clear_timeout_handler(vm: LuauVM) -> int:
|
||||
var timeout_id: int = vm.luaL_checkint(1)
|
||||
|
||||
var timeout_info = active_timeouts.get(timeout_id, null)
|
||||
if timeout_info:
|
||||
# Stop and remove timer
|
||||
if timeout_info.timer:
|
||||
timeout_info.timer.stop()
|
||||
timeout_info.timer.queue_free()
|
||||
|
||||
# Clean up callback reference
|
||||
vm.lua_pushnil()
|
||||
vm.lua_rawseti(vm.LUA_REGISTRYINDEX, timeout_info.callback_ref)
|
||||
|
||||
# Remove from active timeouts
|
||||
active_timeouts.erase(timeout_id)
|
||||
|
||||
return 0
|
||||
|
||||
func _on_timeout_triggered(timeout_info: TimeoutInfo) -> void:
|
||||
if not active_timeouts.has(timeout_info.id):
|
||||
return
|
||||
|
||||
# Execute the callback
|
||||
timeout_info.vm.lua_rawgeti(timeout_info.vm.LUA_REGISTRYINDEX, timeout_info.callback_ref)
|
||||
if timeout_info.vm.lua_isfunction(-1):
|
||||
if timeout_info.vm.lua_pcall(0, 0, 0) != timeout_info.vm.LUA_OK:
|
||||
print("GURT ERROR in timeout callback: ", timeout_info.vm.lua_tostring(-1))
|
||||
timeout_info.vm.lua_pop(1)
|
||||
else:
|
||||
timeout_info.vm.lua_pop(1)
|
||||
|
||||
# Clean up timeout
|
||||
timeout_info.timer.queue_free()
|
||||
timeout_info.vm.lua_pushnil()
|
||||
timeout_info.vm.lua_rawseti(timeout_info.vm.LUA_REGISTRYINDEX, timeout_info.callback_ref)
|
||||
active_timeouts.erase(timeout_info.id)
|
||||
|
||||
func cleanup_all_timeouts():
|
||||
# Clean up all active timeouts
|
||||
for timeout_id in active_timeouts:
|
||||
var timeout_info = active_timeouts[timeout_id]
|
||||
if timeout_info.timer:
|
||||
timeout_info.timer.stop()
|
||||
timeout_info.timer.queue_free()
|
||||
|
||||
# Release Lua callback reference
|
||||
if timeout_info.vm and timeout_info.callback_ref:
|
||||
timeout_info.vm.lua_pushnil()
|
||||
timeout_info.vm.lua_rawseti(timeout_info.vm.LUA_REGISTRYINDEX, timeout_info.callback_ref)
|
||||
active_timeouts.clear()
|
||||
1
flumi/Scripts/Utils/Lua/Timeout.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/Timeout.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dlhj6h7qyo5hp
|
||||
@@ -24,7 +24,6 @@ const INPUT = preload("res://Scenes/Tags/input.tscn")
|
||||
const BUTTON = preload("res://Scenes/Tags/button.tscn")
|
||||
const UL = preload("res://Scenes/Tags/ul.tscn")
|
||||
const OL = preload("res://Scenes/Tags/ol.tscn")
|
||||
const LI = preload("res://Scenes/Tags/li.tscn")
|
||||
const SELECT = preload("res://Scenes/Tags/select.tscn")
|
||||
const OPTION = preload("res://Scenes/Tags/option.tscn")
|
||||
const TEXTAREA = preload("res://Scenes/Tags/textarea.tscn")
|
||||
@@ -347,8 +346,8 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
||||
await node.init(element, parser)
|
||||
return node
|
||||
"li":
|
||||
node = LI.instantiate()
|
||||
node.init(element, parser)
|
||||
node = P.instantiate()
|
||||
node.init(element)
|
||||
"select":
|
||||
node = SELECT.instantiate()
|
||||
node.init(element)
|
||||
|
||||
Reference in New Issue
Block a user