class_name LogsRich extends RichTextLabel var _log_text: String = "": set(value): _log_text = value text = _log_text scroll_to_line(get_line_count()) get: return _log_text enum LogLevel { INFO, WARNING, ERROR, DEBUG } var _level_colors: Dictionary = { LogLevel.INFO: Color.WHITE, LogLevel.WARNING: Color.YELLOW, LogLevel.ERROR: Color.RED, LogLevel.DEBUG: Color.CYAN } var _level_prefixes: Dictionary = { LogLevel.INFO: "[INFO]", LogLevel.WARNING: "[WARNING]", LogLevel.ERROR: "[ERROR]", LogLevel.DEBUG: "[DEBUG]" } var max_lines: int = 1000 func _ready(): scroll_active = true scroll_following = true bbcode_enabled = true # Добавляем моноширинный шрифт для лучшего отображения логов var font = get_theme_font("normal_font") if font: add_theme_font_override("normal_font", font.duplicate()) clear_logs() func add_log(message: String, level: LogLevel = LogLevel.INFO) -> void: var timestamp = Time.get_time_string_from_system() var prefix = _level_prefixes.get(level, "[INFO]") var color = _level_colors.get(level, Color.WHITE) var formatted_message = "[%s] %s %s" % [timestamp, prefix, message] # Используем BBcode для цветного текста # Важно: to_html() возвращает цвет без #, нужно добавить var color_hex = color.to_html() append_text("[color=#%s]%s[/color]\n" % [color_hex, formatted_message]) # Обновляем приватную переменную _log_text = text # Ограничиваем количество строк limit_line_count() # Прокручиваем к последней строке scroll_to_line(get_line_count()) func info(message: String) -> void: add_log(message, LogLevel.INFO) func warning(message: String) -> void: add_log(message, LogLevel.WARNING) func error(message: String) -> void: add_log(message, LogLevel.ERROR) func debug(message: String) -> void: add_log(message, LogLevel.DEBUG) func clear_logs() -> void: clear() text = "" _log_text = "" func limit_line_count() -> void: var lines = get_parsed_text().split("\n") if lines.size() > max_lines: # Удаляем старые строки var _new_lines = lines.slice(lines.size() - max_lines) # Очищаем и перестраиваем текст с сохранением форматирования clear() text = "" # Нужно переформатировать все строки снова # Это сложно сделать правильно без хранения дополнительной информации о цветах # Поэтому лучше использовать альтернативный подход: # Просто обрезаем raw текст var current_text = get_parsed_text() var all_lines = current_text.split("\n") if all_lines.size() > max_lines: var trimmed_lines = all_lines.slice(all_lines.size() - max_lines) clear() text = "\n".join(trimmed_lines) _log_text = text # Альтернативная, более простая реализация limit_line_count func limit_line_count_simple() -> void: # Получаем сырой текст без BBcode тегов var raw_text = get_parsed_text() var lines = raw_text.split("\n") if lines.size() > max_lines: # Удаляем первые строки сверх лимита clear() text = "" # Начинаем с индекса, где превышен лимит var start_index = lines.size() - max_lines for i in range(start_index, lines.size()): # Здесь нужно определить уровень логирования для каждой строки # Это сложно без хранения дополнительной информации # Поэтому просто добавляем как INFO var line = lines[i].strip_edges() if line.length() > 0: append_text("[color=#ffffff]%s[/color]\n" % line) _log_text = text # Лучший подход: хранить логи в массиве и перерисовывать при необходимости var _log_entries: Array = [] # Каждая запись: {message: String, level: LogLevel, timestamp: String} func add_log_advanced(message: String, level: LogLevel = LogLevel.INFO) -> void: var timestamp = Time.get_time_string_from_system() var entry = { "message": message, "level": level, "timestamp": timestamp } _log_entries.append(entry) # Ограничиваем количество записей if _log_entries.size() > max_lines: _log_entries.pop_front() # Перерисовываем все логи redraw_logs() func redraw_logs() -> void: clear() text = "" for entry in _log_entries: var prefix = _level_prefixes.get(entry.level, "[INFO]") var color = _level_colors.get(entry.level, Color.WHITE) var formatted_message = "[%s] %s %s" % [entry.timestamp, prefix, entry.message] var color_hex = color.to_html() append_text("[color=#%s]%s[/color]\n" % [color_hex, formatted_message]) _log_text = text scroll_to_line(get_line_count()) # Метод для сохранения логов в файл func save_logs_to_file(path: String = "user://logs.txt") -> void: var file = FileAccess.open(path, FileAccess.WRITE) if file: file.store_string(get_parsed_text()) file.close() info("Logs saved to: %s" % path) else: error("Failed to save logs to: %s" % path) # Метод для фильтрации логов по уровню func filter_logs_by_level(min_level: LogLevel) -> void: if _log_entries.is_empty(): return clear() text = "" for entry in _log_entries: if entry.level >= min_level: var prefix = _level_prefixes.get(entry.level, "[INFO]") var color = _level_colors.get(entry.level, Color.WHITE) var formatted_message = "[%s] %s %s" % [entry.timestamp, prefix, entry.message] var color_hex = color.to_html() append_text("[color=#%s]%s[/color]\n" % [color_hex, formatted_message]) _log_text = text