extends Node ## A logger to log data to relevant locations ## ## A logger that logs various forms of data at different log levels to both ## built in locations in Godot as well as other components that listen to the ## provided log created signal. signal log_created(message: String, level: LogLevel) enum LogLevel { DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3 } ## The log level that should be outputted as a minimum. @export var log_level: LogLevel ## Log a message at log level debug (meant for troubleshooting). func debug(message: String, arguments: Dictionary = {}) -> void: if log_level > LogLevel.DEBUG: return _log(message, LogLevel.DEBUG, arguments) ## Log a message at log level info (log to indicate something happened). func info(message: String, arguments: Dictionary = {}) -> void: if log_level > LogLevel.INFO: return _log(message, LogLevel.INFO, arguments) ## Log a warning at log level warning (something unexpected happened but it can ## continue). func warn(message: String, arguments: Dictionary = {}) -> void: _log(message, LogLevel.WARN, arguments) ## Log an error at log level error (an issue that prevents something from ## functioning). func error(message: String, arguments: Dictionary = {}) -> void: _log(message, LogLevel.ERROR, arguments) func _log(message: String, level: LogLevel, arguments: Dictionary = {}) -> void: var category = arguments.category if arguments.has("category") and arguments.category else "???" var color = arguments.color if arguments.has("color") else "olive" var image = arguments.image if arguments.has("image") and arguments.image else "res://components/Logger/scroll-text.svg" var adjusted_message = _clean_message(message) var constructed_message = "[color=%s][%s][/color] [img= width=12 height=12 valign=center]%s[/img] %s" % [color, category, image, adjusted_message] print_rich(constructed_message) log_created.emit(constructed_message, level) func _clean_message(message: String) -> String: var cleans = [ { "type": "button", "regex": "μ(.*)μ", "color": Color.html("#a4bf37") }, { "type": "key", "regex": "<(.*)>", "color": Color.html("#42ad24") }, { "type": "tool", "regex": "λ(.*)λ", "color": Color.html("#bf9d37") }, { "type": "object", "regex": "→(.*)←", "color": Color.html("#854322") }, { "type": "path", "regex": "♢(.*)♢", "color": Color.html("#22852e") }, { "type": "function", "regex": "∨(.*)∨", "color": Color.html("#ad2452") }, { "type": "trigger", "regex": "∧(.*)∧", "color": Color.html("#ad2d24") }, { "type": "category", "regex": "\\{(.*)\\}", "color": Color.html("#ad9b24") }, { "type": "value", "regex": "\\|(.*)\\|", "color": Color.TEAL } ] var adjusted_message = message for clean in cleans: adjusted_message = _replace_regex_color(adjusted_message, clean.regex, clean.color) return adjusted_message func _replace_regex_color(message: String, regex_string: String, color: Color) -> String: return _replace_regex(message, regex_string, "[color=" + color.to_html() + "]%s[/color]") func _replace_regex(message: String, regex_string: String, new_content: String) -> String: var adjusted_message = message var stripped_message = message var regex = RegEx.new() regex.compile(regex_string) var result = regex.search(adjusted_message) while result: var before_content = adjusted_message.substr(0, result.get_start()) var after_content = adjusted_message.substr(result.get_end(), adjusted_message.length()) var template_string = "%s" + new_content + "%s" adjusted_message = template_string % [before_content, result.get_string(1), after_content] result = regex.search(adjusted_message) return adjusted_message