import tkinter as tk from tkinter import ttk, messagebox, simpledialog, scrolledtext import re # Funciones para cargar y guardar archivos def load_file(file_path): with open(file_path, 'r') as file: return file.read() def save_file(file_path, content): with open(file_path, 'w') as file: file.write(content) # Funciones para actualizar el archivo Lua def update_file(content, start, end, updated_dict, var_name): updated_entries = [] for key, value in updated_dict.items(): entries = ', '.join([f"{dir} = {{x = {coords['x']}, y = {coords['y']}}}" for dir, coords in value.items()]) updated_entries.append(f"[{key}] = {{{entries}}}") updated_str = f"{var_name} = {{{', '.join(updated_entries)}}}" return content[:start] + updated_str + content[end:] # Clase principal para la aplicación class WingsEditorApp(tk.Tk): def __init__(self): super().__init__() self.title("Wings Editor") self.geometry("1000x800") self.file_path = 'game_wings.lua' self.content = load_file(self.file_path) # Pestañas principales self.tab_control = ttk.Notebook(self) # Pestañas para cada área self.tabs = { "typesWingedOffSet": ttk.Frame(self.tab_control), "typesWingedMountedOffSet": ttk.Frame(self.tab_control), "WingsOffsets": ttk.Frame(self.tab_control), "WingsMountedOffsets": ttk.Frame(self.tab_control) } for name, frame in self.tabs.items(): self.tab_control.add(frame, text=name) self.tab_control.pack(expand=1, fill="both") # Crear widgets y cargar contenido self.tables = {} self.start_end_positions = {} for name in ["typesWingedOffSet", "typesWingedMountedOffSet"]: self.tables[name], start, end = self.parse_lua_table(self.content, name) self.start_end_positions[name] = (start, end) self.create_table(self.tabs[name], self.tables[name], name) for name in ["WingsOffsets", "WingsMountedOffsets"]: self.tables[name], start, end = self.parse_lua_table(self.content, name) self.start_end_positions[name] = (start, end) self.create_table(self.tabs[name], self.tables[name], name) # Botones de acción self.save_button = tk.Button(self, text="Guardar cambios", command=self.save_changes) self.save_button.pack(pady=10) # Terminal interna self.terminal = scrolledtext.ScrolledText(self, height=10, state='disabled', bg='black', fg='white', insertbackground='white') self.terminal.pack(fill=tk.BOTH, padx=10, pady=10, expand=True) # Función para analizar las tablas Lua def parse_lua_table(self, content, var_name): pattern = re.compile(rf'{var_name}\s*=\s*\{{(.*?)\}}', re.DOTALL) match = pattern.search(content) if match: table_str = match.group(1) start_index = match.start(1) end_index = match.end(1) table_dict = {} entry_pattern = re.compile(r'\[(\d+)\]\s*:\s*\{(.*?)\}', re.DOTALL) for entry in entry_pattern.finditer(table_str): key = int(entry.group(1)) value_str = entry.group(2).strip() directions = re.findall(r'(\w+)\s*=\s*\{\s*x\s*=\s*(-?\d+),\s*y\s*=\s*(-?\d+)\s*\}', value_str) table_dict[key] = {dir[0]: {'x': int(dir[1]), 'y': int(dir[2])} for dir in directions} return table_dict, start_index, end_index return {}, None, None # Función para crear la tabla def create_table(self, parent, data, table_name): tree = ttk.Treeview(parent, columns=("x", "y"), show='headings') tree.heading("x", text="X") tree.heading("y", text="Y") tree.pack(expand=True, fill=tk.BOTH) for key, value in data.items(): for direction, coords in value.items(): tree.insert("", "end", values=(direction, coords['x'], coords['y'])) # Botones de agregar, eliminar y cargar add_button = tk.Button(parent, text="Agregar", command=lambda: self.add_entry(table_name)) add_button.pack(pady=5, side=tk.LEFT, padx=5) delete_button = tk.Button(parent, text="Eliminar", command=lambda: self.delete_entry(table_name)) delete_button.pack(pady=5, side=tk.LEFT, padx=5) load_button = tk.Button(parent, text="Cargar", command=lambda: self.load_table(table_name)) load_button.pack(pady=5, side=tk.LEFT, padx=5) # Función para agregar una entrada def add_entry(self, table_name): key = simpledialog.askinteger("Agregar entrada", "Ingrese el ID de la nueva entrada:") if key is not None and key not in self.tables[table_name]: self.tables[table_name][key] = {direction: {'x': 0, 'y': 0} for direction in ["North", "East", "South", "West"]} self.refresh_table(table_name) self.log(f"Entrada {key} agregada en {table_name}.") # Función para eliminar una entrada def delete_entry(self, table_name): key = simpledialog.askinteger("Eliminar entrada", "Ingrese el ID de la entrada a eliminar:") if key is not None and key in self.tables[table_name]: del self.tables[table_name][key] self.refresh_table(table_name) self.log(f"Entrada {key} eliminada en {table_name}.") # Función para cargar una tabla def load_table(self, table_name): self.tables[table_name], start, end = self.parse_lua_table(self.content, table_name) self.start_end_positions[table_name] = (start, end) # Actualizar posiciones de inicio y fin self.refresh_table(table_name) self.log(f"Tabla {table_name} cargada.") # Función para actualizar la tabla def refresh_table(self, table_name): for widget in self.tabs[table_name].winfo_children(): widget.destroy() self.create_table(self.tabs[table_name], self.tables[table_name], table_name) # Función para guardar los cambios en el archivo def save_changes(self): for name in ["typesWingedOffSet", "typesWingedMountedOffSet"]: updated_dict = self.tables[name] start, end = self.start_end_positions[name] self.content = update_file(self.content, start, end, updated_dict, name) for name in ["WingsOffsets", "WingsMountedOffsets"]: updated_dict = self.tables[name] start, end = self.start_end_positions[name] self.content = update_file(self.content, start, end, updated_dict, name) save_file(self.file_path, self.content) self.log("Cambios guardados correctamente.") # Función para mostrar mensajes en la terminal interna def log(self, message): self.terminal.configure(state='normal') self.terminal.insert(tk.END, message + '\n') self.terminal.configure(state='disabled') self.terminal.yview(tk.END) if __name__ == "__main__": app = WingsEditorApp() app.mainloop()