extends Control signal content_updated(bbcode:String) var console:PankuConsole var _module:PankuModule const MAX_LOGS = 128 @export var tag_prefab:PackedScene @export var search_box:LineEdit @export var search_btn:Button @export var pin_btn:Button @export var cls_btn:Button @export var tags_container2:ScrollContainer @export var tags_container:HBoxContainer @export var rlabel:RichTextLabel var current_filter:String = "" var logs:Array = [] const CFG_LOGGER_TAGS = "logger_tags" const CFG_LOGGER_OUTPUT_FONT_SIZE = "logger_output_font_size" #level: #1.info 2.warning 3.error func add_log(message:String, level:int): #add prefix if level == 2: message = "[bgcolor=yellow][color=black][warning][/color][/bgcolor] " + message elif level == 3: message = "[bgcolor=red][color=white][error][/color][/bgcolor] " + message #update tags for tag in tags_container.get_children(): tag.check(message) if logs.size() > 0: var last_log = logs.back() if (last_log["message"] == message) and (Time.get_unix_time_from_system() - last_log["timestamp"] < 1.0): last_log["count"] += 1 last_log["timestamp"] = Time.get_unix_time_from_system() update_view() return logs.push_back({ "message": message, "level": level, "timestamp": Time.get_unix_time_from_system(), "count": 1 }) #TODO: support more logs if logs.size() >= MAX_LOGS: logs = logs.slice(int(MAX_LOGS / 2)) update_view() func search(filter_string:String): current_filter = filter_string search_box.text = current_filter update_view() func clear_all(): logs.clear() update_view() func add_tag(filter_string:String): if filter_string.trim_prefix(" ").trim_suffix(" ").is_empty(): return var tag = tag_prefab.instantiate() tag.tag_btn.text = filter_string tag.tag_text = filter_string tag.tag_btn.pressed.connect( func(): search(filter_string) ) tag.rm_btn.pressed.connect( func(): if tags_container.get_child_count() == 1: tags_container2.hide() tag.queue_free() ) #special treatment if filter_string == "[warning]": tag.self_modulate = Color("#f5c518") tag.tag_btn.self_modulate = Color("#0a1014") tag.rm_btn.self_modulate = Color("#0a1014") elif filter_string == "[error]": tag.self_modulate = Color("#d91f11") tags_container.add_child(tag) tags_container2.show() func update_view(): #TODO: optimization var result:PackedStringArray = PackedStringArray() for log in logs: if !current_filter.is_empty() and !log["message"].contains(current_filter): continue var s = "" if log["level"] == 1: s = log["message"] elif log["level"] == 2: s = "[color=#e1ed96]%s[/color]" % log["message"] elif log["level"] == 3: s = "[color=#dd7085]%s[/color]" % log["message"] if log["count"] > 1: s = "[b](%d)[/b] %s" % [log["count"], s] # add timestamp prefix if _module.show_timestamp: var time_str := Time.get_time_string_from_unix_time(log["timestamp"] + Time.get_time_zone_from_system()['bias'] * 60) s = "[color=#a0a0a0][%s][/color] %s" % [time_str, s] result.append(s) var content:String = "\n".join(result) #sync content rlabel.text = content content_updated.emit(content) func load_data(data:Array): for item in data: var text:String = item add_tag(text) func get_data() -> Array: var tags := PackedStringArray() for tag in tags_container.get_children(): tags.push_back(tag.tag_text) return tags func _ready(): #ui callbacks search_btn.pressed.connect( func(): search(search_box.text) ) search_box.text_submitted.connect( func(text:String): search(search_box.text) ) pin_btn.pressed.connect( func(): add_tag(search_box.text) search_box.clear() ) cls_btn.pressed.connect(clear_all) clear_all()