From f91d8d55606e5d7c348bb3201779d2309e0dd728 Mon Sep 17 00:00:00 2001 From: JayTheBusinessGoose Date: Sat, 23 Dec 2023 18:38:15 -0700 Subject: [PATCH] Split tilecodes from dependencies into separate palettes so that they aren't automatically added to the level file when saving, but are still available in the palette to select. --- .../custom_levels/custom_level_editor.py | 2 + .../ui/levels/shared/palette_panel.py | 53 ++++++++- src/modlunky2/ui/levels/shared/tile.py | 10 ++ .../multi_room/multi_room_editor_tab.py | 5 +- .../vanilla_levels/vanilla_level_editor.py | 110 ++++++++++++------ 5 files changed, 140 insertions(+), 40 deletions(-) create mode 100644 src/modlunky2/ui/levels/shared/tile.py diff --git a/src/modlunky2/ui/levels/custom_levels/custom_level_editor.py b/src/modlunky2/ui/levels/custom_levels/custom_level_editor.py index 039b6e05..25515550 100644 --- a/src/modlunky2/ui/levels/custom_levels/custom_level_editor.py +++ b/src/modlunky2/ui/levels/custom_levels/custom_level_editor.py @@ -173,6 +173,7 @@ def toggle_panel_hidden(): self.delete_tilecode, self.add_tilecode, None, + None, self.texture_fetcher, self.texture_fetcher.sprite_fetcher, ) @@ -454,6 +455,7 @@ def populate_tilecode_palette(self): self.palette_panel.update_with_palette( self.tile_palette_ref_in_use, self.tile_palette_suggestions, + None, self.lvl_biome, self.lvl, ) diff --git a/src/modlunky2/ui/levels/shared/palette_panel.py b/src/modlunky2/ui/levels/shared/palette_panel.py index 29e74f97..c3d24b82 100644 --- a/src/modlunky2/ui/levels/shared/palette_panel.py +++ b/src/modlunky2/ui/levels/shared/palette_panel.py @@ -162,6 +162,7 @@ def __init__( on_delete_tilecode, on_add_tilecode, on_select_tile, + on_use_dependency_tile, texture_fetcher, sprite_fetcher, *args, @@ -173,6 +174,7 @@ def __init__( self.on_delete_tilecode = on_delete_tilecode self.on_add_tilecode = on_add_tilecode self.on_select_tile = on_select_tile + self.on_use_dependency_tile = on_use_dependency_tile # The tile palettes are loaded into here as buttons with their image # as a tile and text as their value to grab when needed. @@ -203,7 +205,7 @@ def delete_tilecode(self, tile_name, tile_code): if self.secondary_tile_view.tile_code() == tile_code: self.secondary_tile_view.reset(disable=False) - def update_with_palette(self, new_palette, suggestions, biome, lvl): + def update_with_palette(self, new_palette, suggestions, dependency_tiles, biome, lvl): for widget in self.palette.scrollable_frame.winfo_children(): widget.destroy() @@ -306,6 +308,49 @@ def update_with_palette(self, new_palette, suggestions, biome, lvl): event, ts, ti ), ) + + if dependency_tiles and len(dependency_tiles): + for dependency in dependency_tiles: + if len(dependency.tiles) == 0: + continue + count_col = -1 + self.palette.scrollable_frame.rowconfigure(count_row + 1, minsize=15) + count_row += 2 + dependency_label = ttk.Label(self.palette.scrollable_frame, text=str(dependency.name) + ":") + dependency_label.grid(row=count_row, column=0, columnspan=5, sticky="nw") + count_row += 1 + + for tile in dependency.tiles: + count_col += 1 + if count_col == TILES_PER_ROW: + count_col = 0 + count_row += 1 + + tile_image = tile[2] + self.tile_images.append(tile_image) + + new_tile = tk.Button( + self.palette.scrollable_frame, + text=tile[0], + width=40, + height=40, + image=tile_image, + ) + new_tile.grid(row=count_row, column=count_col) + new_tile.bind( + "", + lambda event, t=tile, d=dependency: self.dependency_tile_pick( + event, t, d + ), + ) + new_tile.bind( + "", + lambda event, t=tile, d=dependency: self.dependency_tile_pick( + event, t, d + ), + ) + + self.primary_tile_view.enable() self.secondary_tile_view.enable() self.new_tile_panel.reset() @@ -325,6 +370,12 @@ def suggested_tile_pick(self, event, suggested_tile, tile_image): return self.select_tile(tile[0], tile_image, event.num == 1, True) + def dependency_tile_pick(self, event, tile, dependency): + if self.on_use_dependency_tile: + self.on_use_dependency_tile(tile, dependency) + + self.select_tile(tile[0], tile[2], event.num == 1, True) + def select_tile(self, tile_name, tile_image, is_primary, tell_delegate=False): tile_view = self.primary_tile_view if not is_primary: diff --git a/src/modlunky2/ui/levels/shared/tile.py b/src/modlunky2/ui/levels/shared/tile.py new file mode 100644 index 00000000..1ab53560 --- /dev/null +++ b/src/modlunky2/ui/levels/shared/tile.py @@ -0,0 +1,10 @@ +from dataclasses import dataclass +from typing import List, Optional + +from modlunky2.levels.level_templates import TemplateSetting +from modlunky2.ui.levels.shared.setrooms import MatchedSetroom + +@dataclass +class DependencyPalette: + name: str + tiles: List \ No newline at end of file diff --git a/src/modlunky2/ui/levels/vanilla_levels/multi_room/multi_room_editor_tab.py b/src/modlunky2/ui/levels/vanilla_levels/multi_room/multi_room_editor_tab.py index 7af0ebda..10de1096 100644 --- a/src/modlunky2/ui/levels/vanilla_levels/multi_room/multi_room_editor_tab.py +++ b/src/modlunky2/ui/levels/vanilla_levels/multi_room/multi_room_editor_tab.py @@ -42,6 +42,7 @@ def __init__( on_add_tilecode, on_delete_tilecode, on_select_palette_tile, + on_use_dependency_tile, on_modify_room, on_change_filetree, on_add_room, @@ -139,6 +140,7 @@ def toggle_panel_hidden(): self.delete_tilecode, self.add_tilecode, self.palette_selected_tile, + on_use_dependency_tile, self.texture_fetcher, self.texture_fetcher.sprite_fetcher, ) @@ -720,10 +722,11 @@ def room_setting_change_at(self, setting, value, map_index, row, col): if setting == TemplateSetting.DUAL or setting == TemplateSetting.ONLYFLIP: self.redraw() - def populate_tilecode_palette(self, tile_palette, suggestions): + def populate_tilecode_palette(self, tile_palette, suggestions, dependency_tiles): self.palette_panel.update_with_palette( tile_palette, suggestions, + dependency_tiles, self.lvl_biome, self.lvl, ) diff --git a/src/modlunky2/ui/levels/vanilla_levels/vanilla_level_editor.py b/src/modlunky2/ui/levels/vanilla_levels/vanilla_level_editor.py index 20b5cacb..c835ac80 100644 --- a/src/modlunky2/ui/levels/vanilla_levels/vanilla_level_editor.py +++ b/src/modlunky2/ui/levels/vanilla_levels/vanilla_level_editor.py @@ -29,6 +29,7 @@ ) from modlunky2.ui.levels.shared.palette_panel import PalettePanel from modlunky2.ui.levels.shared.setrooms import Setroom, MatchedSetroom +from modlunky2.ui.levels.shared.tile import DependencyPalette from modlunky2.ui.levels.vanilla_levels.dual_util import make_dual, remove_dual from modlunky2.ui.levels.vanilla_levels.level_list_panel import LevelListPanel from modlunky2.ui.levels.vanilla_levels.level_settings_bar import LevelSettingsBar @@ -112,6 +113,7 @@ def __init__( self.current_selected_room = None self.usable_codes = ShortCode.usable_codes() self.tile_palette_ref_in_use = [] + self.dependency_tile_palette_ref_in_use = [] self.tile_palette_map = {} self.tile_codes = [] self.template_list = [] @@ -168,6 +170,7 @@ def tab_selected(event): ), self.delete_tilecode, self.multiroom_editor_selected_tile, + self.use_dependency_tile, self.multiroom_editor_modified_room, self.multiroom_editor_changed_filetree, self.on_insert_room, @@ -283,6 +286,7 @@ def tab_selected(event): tile, percent, alt_tile, self.palette_panel, self.mag ), self.palette_selected_tile, + self.use_dependency_tile, self.texture_fetcher, self.texture_fetcher.sprite_fetcher, ) @@ -327,7 +331,20 @@ def zoom_changed(_): self.mag, ) ) - self.room_select() + + if self.dependency_tile_palette_ref_in_use: + for palette in self.dependency_tile_palette_ref_in_use: + for tile in palette.tiles: + tile_name = tile[0].split(" ", 2)[0] + tile[1] = ImageTk.PhotoImage( + self.texture_fetcher.get_texture( + tile_name, + self.lvl_biome, + self.lvl, + self.mag, + ) + ) + self.room_select() self.slider_zoom = tk.Scale( side_panel_container, @@ -359,6 +376,7 @@ def read_lvl_file(self, lvl): self.button_replace["state"] = tk.NORMAL self.tile_palette_ref_in_use = [] + self.dependency_tile_palette_ref_in_use = [] self.tile_palette_map = {} self.lvl = lvl @@ -377,23 +395,11 @@ def read_lvl_file(self, lvl): else: lvl_path = self.extracts_path / lvl - # Levels to load dependency tilecodes from. - level_dependencies = LevelDependencies.dependencies_for_level(lvl) - levels = [] - for dependency in level_dependencies: - levels.append( - LevelDependencies.loaded_level_file_for_path( - dependency, self.lvls_path, self.extracts_path - ) - ) - levels.append(LevelFile.from_path(Path(lvl_path))) - - level = None - for level in levels: + def get_level_tilecodes(level): logger.debug("%s loaded.", level.comment) level_tilecodes = level.tile_codes.all() - for tilecode in level_tilecodes: + def tilecode_item(tilecode): tilecode_item = [] tilecode_item.append(str(tilecode.name) + " " + str(tilecode.value)) @@ -407,18 +413,44 @@ def read_lvl_file(self, lvl): tilecode_item.append(ImageTk.PhotoImage(img)) tilecode_item.append(ImageTk.PhotoImage(selection_img)) - self.select_palette_tile(tilecode_item, True) - self.select_palette_tile(tilecode_item, False) + return tilecode_item + + return [tilecode_item(tc) for tc in level_tilecodes] + def clear_tile_from_dependencies(tile): + for palette in self.dependency_tile_palette_ref_in_use: + for i in palette.tiles: + if str(i[0]).split(" ", 1)[1] == str(tile[0]).split(" ", 1)[1]: + palette.tiles.remove(i) - for i in self.tile_palette_ref_in_use: - if str(i[0]).split(" ", 1)[1] == str(tilecode.value): - self.tile_palette_ref_in_use.remove(i) + def register_tile_code(tile): + self.select_palette_tile(tile, True) + self.select_palette_tile(tile, False) + code = tile[0].split(" ", 1)[1] + if code in self.usable_codes: + self.usable_codes.remove(code) - if tilecode.value in self.usable_codes: - self.usable_codes.remove(tilecode.value) + self.tile_palette_map[code] = tile - self.tile_palette_ref_in_use.append(tilecode_item) - self.tile_palette_map[tilecode.value] = tilecode_item + level_dependencies = LevelDependencies.dependencies_for_level(lvl) + + for dependency in level_dependencies: + level = LevelDependencies.loaded_level_file_for_path( + dependency, self.lvls_path, self.extracts_path + ) + logger.debug("%s loaded.", level.comment) + tiles = get_level_tilecodes(level) + for tile in tiles: + clear_tile_from_dependencies(tile) + register_tile_code(tile) + + self.dependency_tile_palette_ref_in_use.insert(0, DependencyPalette("From " + dependency, tiles)) + + level = LevelFile.from_path(Path(lvl_path)) + tiles = get_level_tilecodes(level) + self.tile_palette_ref_in_use = tiles + for tile in tiles: + clear_tile_from_dependencies(tile) + register_tile_code(tile) # Populate the default tile code for left clicks. if "1" in self.tile_palette_map: @@ -508,11 +540,12 @@ def populate_tilecode_palette(self): self.palette_panel.update_with_palette( self.tile_palette_ref_in_use, None, + self.dependency_tile_palette_ref_in_use, self.lvl_biome, self.lvl, ) self.multi_room_editor_tab.populate_tilecode_palette( - self.tile_palette_ref_in_use, None + self.tile_palette_ref_in_use, None, self.dependency_tile_palette_ref_in_use ) def palette_selected_tile(self, tile_name, image, is_primary): @@ -880,18 +913,9 @@ def room_select(self): # Loads room when click if not parent node. for canvas_index, layer_tile_codes in enumerate(self.tile_codes): for row_index, row in enumerate(layer_tile_codes): for column_index, tile_code in enumerate(row): - tile_name = "" - tiles = [ - c - for c in self.tile_palette_ref_in_use - if str(" " + tile_code) in str(c[0]) - ] - if tiles: - tile_image = tiles[-1][1] - tile_name = str(tiles[-1][0]).split(" ", 1)[0] - else: - # There's a missing tile id somehow - logger.debug("%s Not Found", tile_code) + tile = self.tile_palette_map[tile_code] + tile_name = str(tile[0]).split(" ", 1)[0] + tile_image = tile[1] x_coord, y_coord = self.texture_fetcher.adjust_texture_xy( tile_image.width(), tile_image.height(), @@ -948,6 +972,14 @@ def log_codes_left(self): codes += str(code) logger.debug("%s codes left (%s)", len(self.usable_codes), codes) + def use_dependency_tile(self, tile, dependency): + self.tile_palette_ref_in_use.append(tile) + dependency.tiles.remove(tile) + + self.populate_tilecode_palette() + self.changes_made() + + def add_tilecode( self, tile, @@ -996,8 +1028,9 @@ def add_tilecode( ) # Compares tile id to tile ids in palette list. - for palette_tile in self.tile_palette_ref_in_use: + for _, palette_tile in self.tile_palette_map.items(): palette_tile = palette_tile[0].split()[0].strip() + print(palette_tile) if new_tile_code == palette_tile: tkMessageBox.showinfo("Uh Oh!", "You already have that!") return @@ -1172,6 +1205,7 @@ def reset(self): self.canvas.clear() self.tile_palette_map = {} self.tile_palette_ref_in_use = None + self.dependency_tile_palette_ref_in_use = None self.lvl = None self.lvl_biome = None self.reset_save_button()