tilemap-editor 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tilemap_editor-2.0.2/src/tilemap_editor.egg-info → tilemap_editor-2.0.3}/PKG-INFO +1 -1
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/pyproject.toml +1 -1
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/editor.py +30 -9
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/autotile_template.py +24 -23
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/autotiler.py +64 -39
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/CHANGELOG.md +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/LICENSE +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/MANIFEST.in +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/README.md +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/check.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/checked.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/close.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/error.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/file.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/filedead.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/fit.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/folder.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/grid.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/image.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/info.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/load.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/loop.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/pan.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/pause.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/pencil.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/play.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/plus.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/radio.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/reset.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/save.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/stop.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/tileset.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/warning.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/setup.cfg +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/configs/themes.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/constants.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/event_map.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/layers.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/main.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/editor.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/models.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/protocols.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/shape_editor.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/standalone.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/__main__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/clipboard_util.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/editor.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/frame_picker.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/models.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/preview.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/protocols.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/runtime_load.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/standalone.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/timeline.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/validation.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/collision_painter.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/editor.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/models.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/protocols.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/standalone.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/standalone_automap.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/standalone_error_console.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/standalone_filemanager.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/standalone_image_viewer.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor/__main__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor/cli.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/SOURCES.txt +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/requires.txt +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/top_level.txt +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/ttypes/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/ttypes/tilemap.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/error_handler.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/font_manager.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/history.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/icon_manager.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/icons_cache.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/log_capture.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/serialization.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/settings.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/standalone.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/utils/validation.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/__init__.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/automap_models.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/filemanager.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/layer_selector.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/mapsetup.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/regex_automap_designer.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/tile_grid.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/tile_selector.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/draw_utils.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/fileinput.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/layer_type_dialog.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/menubar.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/notification.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/property_editor.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/theme.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/tileset_type_dialog.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/toolbar.py +0 -0
- {tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/widgets/ui/tooltip.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tilemap-editor"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.3"
|
|
8
8
|
description = "Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -762,6 +762,7 @@ class Editor:
|
|
|
762
762
|
if event.type == pygame.VIDEORESIZE:
|
|
763
763
|
self.handle_resize(event.w, event.h)
|
|
764
764
|
|
|
765
|
+
# Priority 1: Modal dialogs and inputs (highest priority)
|
|
765
766
|
if self.save_input.active:
|
|
766
767
|
self.save_input.handle_event(event)
|
|
767
768
|
continue
|
|
@@ -782,9 +783,20 @@ class Editor:
|
|
|
782
783
|
if self.property_editor.handle_event(event):
|
|
783
784
|
continue
|
|
784
785
|
|
|
786
|
+
# Priority 2: Autotiler and Regex Designer (block all events when visible)
|
|
787
|
+
if self.autotiler.visible:
|
|
788
|
+
if self.autotiler.handle_event(event):
|
|
789
|
+
continue
|
|
790
|
+
|
|
791
|
+
if self.regex_automap_designer.visible:
|
|
792
|
+
if self.regex_automap_designer.handle_event(event):
|
|
793
|
+
continue
|
|
794
|
+
|
|
795
|
+
# Priority 3: Menu bar
|
|
785
796
|
if self.menubar.handle_event(event):
|
|
786
797
|
continue
|
|
787
798
|
|
|
799
|
+
# Priority 4: Keyboard shortcuts
|
|
788
800
|
if event.type == pygame.KEYDOWN:
|
|
789
801
|
mods = pygame.key.get_mods()
|
|
790
802
|
ctrl_held = mods & (pygame.KMOD_LCTRL | pygame.KMOD_RCTRL)
|
|
@@ -836,23 +848,17 @@ class Editor:
|
|
|
836
848
|
self.tilemap.layer_manager.set_active_layer(idx)
|
|
837
849
|
continue
|
|
838
850
|
|
|
851
|
+
# Priority 5: Toolbar
|
|
839
852
|
if self.toolbar and self.toolbar.handle_event(event):
|
|
840
853
|
continue
|
|
841
854
|
|
|
842
|
-
|
|
843
|
-
if self.autotiler.handle_event(event):
|
|
844
|
-
continue
|
|
845
|
-
|
|
846
|
-
if self.regex_automap_designer.visible:
|
|
847
|
-
if self.regex_automap_designer.handle_event(event):
|
|
848
|
-
continue
|
|
849
|
-
|
|
850
|
-
# Route events to the dockable animation panel
|
|
855
|
+
# Priority 6: Dockable animation panel
|
|
851
856
|
if self.left_panel_visible and self.animation_panel:
|
|
852
857
|
if hasattr(self.animation_panel, "handle_event"):
|
|
853
858
|
if self.animation_panel.handle_event(event):
|
|
854
859
|
continue
|
|
855
860
|
|
|
861
|
+
# Priority 7: Side panels (tileset and layer widgets)
|
|
856
862
|
consumed = False
|
|
857
863
|
if self.tileset_widget and self.tileset_widget.handle_event(event):
|
|
858
864
|
consumed = True
|
|
@@ -862,6 +868,8 @@ class Editor:
|
|
|
862
868
|
and self.layer_widget.handle_event(event)
|
|
863
869
|
):
|
|
864
870
|
consumed = True
|
|
871
|
+
|
|
872
|
+
# Priority 8: Main tile grid (lowest priority)
|
|
865
873
|
if not consumed and self.tile_grid_widget:
|
|
866
874
|
self.tile_grid_widget.handle_event(event)
|
|
867
875
|
|
|
@@ -894,9 +902,22 @@ class Editor:
|
|
|
894
902
|
self.tileset_widget.draw(self.screen)
|
|
895
903
|
if self.layer_widget:
|
|
896
904
|
self.layer_widget.draw(self.screen)
|
|
905
|
+
|
|
906
|
+
# Draw autotiler and regex designer with modal overlay
|
|
897
907
|
if self.autotiler:
|
|
908
|
+
if self.autotiler.visible:
|
|
909
|
+
# Dim background when autotiler is open
|
|
910
|
+
overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
|
|
911
|
+
overlay.fill((0, 0, 0, 100))
|
|
912
|
+
self.screen.blit(overlay, (0, 0))
|
|
898
913
|
self.autotiler.draw(self.screen)
|
|
914
|
+
|
|
899
915
|
if self.regex_automap_designer:
|
|
916
|
+
if self.regex_automap_designer.visible:
|
|
917
|
+
# Dim background when regex designer is open
|
|
918
|
+
overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
|
|
919
|
+
overlay.fill((0, 0, 0, 100))
|
|
920
|
+
self.screen.blit(overlay, (0, 0))
|
|
900
921
|
self.regex_automap_designer.draw(self.screen)
|
|
901
922
|
|
|
902
923
|
# Draw the dockable animation panel
|
|
@@ -166,6 +166,14 @@ class AutotileTemplateApplier:
|
|
|
166
166
|
if not ts:
|
|
167
167
|
return
|
|
168
168
|
|
|
169
|
+
# Check if a group is selected
|
|
170
|
+
if self.designer.selected_group_idx == -1:
|
|
171
|
+
print("Template Error: No group selected. Please select a group first.")
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
# Use the currently selected group
|
|
175
|
+
target_group = self.designer.groups[self.designer.selected_group_idx]
|
|
176
|
+
|
|
169
177
|
rx, ry, rw, rh = tile_selector.selected_tile
|
|
170
178
|
tile_w, tile_h = self.designer.editor.tilemap.tile_size
|
|
171
179
|
sheet_cols = ts.surface.get_width() // tile_w
|
|
@@ -173,24 +181,6 @@ class AutotileTemplateApplier:
|
|
|
173
181
|
start_col = rx // tile_w
|
|
174
182
|
start_row = ry // tile_h
|
|
175
183
|
|
|
176
|
-
# Define a unique group ID for THIS specific 3x3 selection area
|
|
177
|
-
# (e.g. "GrassSet_12_4")
|
|
178
|
-
set_id = f"{ts.name}_{start_col}_{start_row}"
|
|
179
|
-
|
|
180
|
-
from .autotiler import AutotileGroup
|
|
181
|
-
|
|
182
|
-
# Create a real group object in the designer
|
|
183
|
-
target_group = None
|
|
184
|
-
for g in self.designer.groups:
|
|
185
|
-
if g.name == set_id:
|
|
186
|
-
target_group = g
|
|
187
|
-
break
|
|
188
|
-
|
|
189
|
-
if not target_group:
|
|
190
|
-
target_group = AutotileGroup(set_id)
|
|
191
|
-
self.designer.groups.append(target_group)
|
|
192
|
-
self.designer.selected_group_idx = len(self.designer.groups) - 1
|
|
193
|
-
|
|
194
184
|
added_count = 0
|
|
195
185
|
updated_count = 0
|
|
196
186
|
|
|
@@ -204,32 +194,43 @@ class AutotileTemplateApplier:
|
|
|
204
194
|
|
|
205
195
|
ts_index = tile_selector.active_idx
|
|
206
196
|
|
|
207
|
-
# Check for existing rule in THIS group
|
|
197
|
+
# Check for existing rule in THIS group with EXACT same neighbors and tileset
|
|
208
198
|
matched_rule = None
|
|
209
199
|
for r in target_group.rules:
|
|
200
|
+
# Must match both neighbors AND tileset to be considered the same rule
|
|
210
201
|
if r.neighbors == neighbors and r.tileset_index == ts_index:
|
|
211
202
|
matched_rule = r
|
|
212
203
|
break
|
|
213
204
|
|
|
214
205
|
if matched_rule:
|
|
206
|
+
# Only add variant if it's not already there
|
|
215
207
|
if vid not in matched_rule.variant_ids:
|
|
216
208
|
matched_rule.variant_ids.append(vid)
|
|
217
209
|
updated_count += 1
|
|
218
210
|
else:
|
|
219
|
-
|
|
211
|
+
# Create a new rule with a unique name
|
|
212
|
+
rule_num = len(target_group.rules) + 1
|
|
213
|
+
rule_name = f"Rule {rule_num}"
|
|
214
|
+
|
|
215
|
+
# Ensure unique name
|
|
216
|
+
existing_names = {r.name for r in target_group.rules}
|
|
217
|
+
while rule_name in existing_names:
|
|
218
|
+
rule_num += 1
|
|
219
|
+
rule_name = f"Rule {rule_num}"
|
|
220
|
+
|
|
220
221
|
new_rule = AutotileRule(
|
|
221
222
|
name=rule_name,
|
|
222
|
-
neighbors=neighbors,
|
|
223
|
+
neighbors=set(neighbors), # Create a new set to avoid reference issues
|
|
223
224
|
tileset_path=str(ts.path),
|
|
224
225
|
variant_ids=[vid],
|
|
225
226
|
tileset_index=ts_index,
|
|
226
|
-
group_id=
|
|
227
|
+
group_id=target_group.name,
|
|
227
228
|
)
|
|
228
229
|
target_group.rules.append(new_rule)
|
|
229
230
|
added_count += 1
|
|
230
231
|
|
|
231
232
|
print(
|
|
232
|
-
f"Template Applied: {template.name}
|
|
233
|
+
f"Template Applied: {template.name} to Group '{target_group.name}'. {added_count} rules added, {updated_count} rules updated."
|
|
233
234
|
)
|
|
234
235
|
|
|
235
236
|
def draw(self, screen: Surface):
|
|
@@ -87,7 +87,7 @@ class AutotileGroup:
|
|
|
87
87
|
class AutotileRuleDesigner:
|
|
88
88
|
def __init__(self, editor: "Editor", x: int, y: int):
|
|
89
89
|
self.editor = editor
|
|
90
|
-
self.rect = Rect(x, y, 600,
|
|
90
|
+
self.rect = Rect(x, y, 600, 500) # Increased height to accommodate buttons outside list areas
|
|
91
91
|
self.header_height = 30
|
|
92
92
|
|
|
93
93
|
self.visible = False
|
|
@@ -102,7 +102,7 @@ class AutotileRuleDesigner:
|
|
|
102
102
|
self.rename_text: str = ""
|
|
103
103
|
|
|
104
104
|
self.scroll_offset: int = 0
|
|
105
|
-
self.max_visible_rules: int =
|
|
105
|
+
self.max_visible_rules: int = 6 # Reduced to make scrolling more visible
|
|
106
106
|
self.scroll_bar_rect: Optional[Rect] = None
|
|
107
107
|
self.is_scrollbar_dragging: bool = False
|
|
108
108
|
|
|
@@ -139,9 +139,16 @@ class AutotileRuleDesigner:
|
|
|
139
139
|
body_h = self.rect.height - self.header_height
|
|
140
140
|
sidebar_w = 200
|
|
141
141
|
self.list_area = Rect(self.rect.x, body_y, sidebar_w, body_h)
|
|
142
|
-
|
|
142
|
+
|
|
143
|
+
# Reserve space for buttons at the bottom of each list area
|
|
144
|
+
button_h = 30
|
|
145
|
+
group_content_h = (body_h // 2) - button_h
|
|
146
|
+
rule_content_h = (body_h // 2) - button_h
|
|
147
|
+
|
|
148
|
+
# Group list area excludes the button
|
|
149
|
+
self.group_list_area = Rect(self.rect.x, body_y, sidebar_w, group_content_h)
|
|
143
150
|
self.rule_list_area = Rect(
|
|
144
|
-
self.rect.x, body_y + body_h // 2, sidebar_w,
|
|
151
|
+
self.rect.x, body_y + body_h // 2, sidebar_w, rule_content_h
|
|
145
152
|
)
|
|
146
153
|
|
|
147
154
|
self.edit_area = Rect(
|
|
@@ -154,15 +161,16 @@ class AutotileRuleDesigner:
|
|
|
154
161
|
self.save_btn_rect = Rect(cx - btn_w - 5, btn_y, btn_w, 30)
|
|
155
162
|
self.delete_btn_rect = Rect(cx + 5, btn_y, btn_w, 30)
|
|
156
163
|
|
|
164
|
+
# Position buttons OUTSIDE their respective list areas to prevent click conflicts
|
|
157
165
|
self.new_group_btn_rect = Rect(
|
|
158
166
|
self.group_list_area.x + 10,
|
|
159
|
-
self.group_list_area.bottom
|
|
167
|
+
self.group_list_area.bottom + 5, # Below the group list area
|
|
160
168
|
self.group_list_area.width - 20,
|
|
161
169
|
25,
|
|
162
170
|
)
|
|
163
171
|
self.new_rule_btn_rect = Rect(
|
|
164
172
|
self.rule_list_area.x + 10,
|
|
165
|
-
self.rule_list_area.bottom
|
|
173
|
+
self.rule_list_area.bottom + 5, # Below the rule list area
|
|
166
174
|
self.rule_list_area.width - 20,
|
|
167
175
|
25,
|
|
168
176
|
)
|
|
@@ -277,10 +285,16 @@ class AutotileRuleDesigner:
|
|
|
277
285
|
)
|
|
278
286
|
return True
|
|
279
287
|
|
|
288
|
+
# Check buttons FIRST before checking list areas (since buttons are outside)
|
|
280
289
|
if self.new_group_btn_rect.collidepoint(mouse_pos):
|
|
281
290
|
self._create_new_group_with_focus()
|
|
282
291
|
return True
|
|
292
|
+
|
|
293
|
+
if self.new_rule_btn_rect.collidepoint(mouse_pos):
|
|
294
|
+
self._reset_selection()
|
|
295
|
+
return True
|
|
283
296
|
|
|
297
|
+
# Then check list areas
|
|
284
298
|
if self.group_list_area.collidepoint(mouse_pos):
|
|
285
299
|
self._handle_group_list_click(mouse_pos)
|
|
286
300
|
return True
|
|
@@ -289,28 +303,18 @@ class AutotileRuleDesigner:
|
|
|
289
303
|
self._handle_rule_list_click(mouse_pos)
|
|
290
304
|
return True
|
|
291
305
|
|
|
292
|
-
|
|
293
|
-
self._save_current_rule()
|
|
294
|
-
return True
|
|
295
|
-
if self.save_btn_rect.inflate(0, 40).collidepoint(mouse_pos):
|
|
296
|
-
pass
|
|
297
|
-
|
|
298
|
-
if self.new_rule_btn_rect.collidepoint(mouse_pos):
|
|
299
|
-
self._reset_selection()
|
|
300
|
-
return True
|
|
301
|
-
|
|
306
|
+
# Edit area interactions
|
|
302
307
|
if self.edit_area.collidepoint(mouse_pos):
|
|
303
|
-
if self.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
self.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
self.template_manager.show_at(mouse_pos)
|
|
308
|
+
if self.save_btn_rect.collidepoint(mouse_pos):
|
|
309
|
+
self._save_current_rule()
|
|
310
|
+
elif self.delete_btn_rect.collidepoint(mouse_pos):
|
|
311
|
+
self._delete_current_rule()
|
|
312
|
+
elif self.external_btn_rect.collidepoint(mouse_pos):
|
|
313
|
+
self._launch_external_viewer()
|
|
314
|
+
elif self.template_btn_rect.collidepoint(mouse_pos):
|
|
315
|
+
self.template_manager.show_at(mouse_pos)
|
|
316
|
+
else:
|
|
317
|
+
self._handle_grid_click(mouse_pos)
|
|
314
318
|
return True
|
|
315
319
|
|
|
316
320
|
elif event.type == pygame.MOUSEBUTTONUP:
|
|
@@ -323,10 +327,8 @@ class AutotileRuleDesigner:
|
|
|
323
327
|
self._update_layout()
|
|
324
328
|
return True
|
|
325
329
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return True
|
|
330
|
+
# Always consume events when visible to prevent clicks bleeding through
|
|
331
|
+
return self.rect.collidepoint(mouse_pos) or self.is_dragging
|
|
330
332
|
|
|
331
333
|
def _sync_last_editor_state(self):
|
|
332
334
|
tile_selector = getattr(self.editor, "tileset_widget", None)
|
|
@@ -430,10 +432,6 @@ class AutotileRuleDesigner:
|
|
|
430
432
|
return
|
|
431
433
|
|
|
432
434
|
def _handle_rule_list_click(self, mouse_pos):
|
|
433
|
-
if self.new_rule_btn_rect.collidepoint(mouse_pos):
|
|
434
|
-
self._reset_selection()
|
|
435
|
-
return
|
|
436
|
-
|
|
437
435
|
if self.selected_group_idx == -1:
|
|
438
436
|
return
|
|
439
437
|
|
|
@@ -441,6 +439,17 @@ class AutotileRuleDesigner:
|
|
|
441
439
|
start_y = self.rule_list_area.y + 25
|
|
442
440
|
item_h = 25
|
|
443
441
|
|
|
442
|
+
# Only process clicks within the visible list area
|
|
443
|
+
list_content_area = Rect(
|
|
444
|
+
self.rule_list_area.x,
|
|
445
|
+
self.rule_list_area.y + 25,
|
|
446
|
+
self.rule_list_area.width,
|
|
447
|
+
self.rule_list_area.height - 25 # Adjusted since button is outside
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
if not list_content_area.collidepoint(mouse_pos):
|
|
451
|
+
return
|
|
452
|
+
|
|
444
453
|
visible_start = self.scroll_offset
|
|
445
454
|
visible_end = min(visible_start + self.max_visible_rules, len(group.rules))
|
|
446
455
|
|
|
@@ -684,6 +693,7 @@ class AutotileRuleDesigner:
|
|
|
684
693
|
d_name = name if len(name) < 22 else name[:19] + ".."
|
|
685
694
|
screen.blit(self.font.render(d_name, True, TEXT_COLOR), (r.x + 5, r.y + 5))
|
|
686
695
|
|
|
696
|
+
# Draw button OUTSIDE the group list area
|
|
687
697
|
pygame.draw.rect(
|
|
688
698
|
screen, (80, 120, 80), self.new_group_btn_rect, border_radius=4
|
|
689
699
|
)
|
|
@@ -700,6 +710,7 @@ class AutotileRuleDesigner:
|
|
|
700
710
|
|
|
701
711
|
self._draw_scrollable_rule_list(screen)
|
|
702
712
|
|
|
713
|
+
# Draw button OUTSIDE the rule list area
|
|
703
714
|
pygame.draw.rect(
|
|
704
715
|
screen, (70, 130, 180), self.new_rule_btn_rect, border_radius=4
|
|
705
716
|
)
|
|
@@ -709,7 +720,7 @@ class AutotileRuleDesigner:
|
|
|
709
720
|
)
|
|
710
721
|
|
|
711
722
|
def _draw_scrollable_rule_list(self, screen: Surface) -> None:
|
|
712
|
-
"""Draw rules with scroll indicators and scrollbar"""
|
|
723
|
+
"""Draw rules with scroll indicators and scrollbar - with clipping to prevent overflow"""
|
|
713
724
|
if self.selected_group_idx == -1:
|
|
714
725
|
return
|
|
715
726
|
|
|
@@ -720,6 +731,17 @@ class AutotileRuleDesigner:
|
|
|
720
731
|
|
|
721
732
|
self.scroll_offset = max(0, min(self.scroll_offset, max_scroll))
|
|
722
733
|
|
|
734
|
+
# Set clip rect to prevent rules from rendering outside the list area
|
|
735
|
+
# Since button is now outside, we can use more of the area
|
|
736
|
+
list_clip = Rect(
|
|
737
|
+
self.rule_list_area.x,
|
|
738
|
+
self.rule_list_area.y + 25,
|
|
739
|
+
self.rule_list_area.width,
|
|
740
|
+
self.rule_list_area.height - 25 # Just leave space for header
|
|
741
|
+
)
|
|
742
|
+
old_clip = screen.get_clip()
|
|
743
|
+
screen.set_clip(list_clip)
|
|
744
|
+
|
|
723
745
|
visible_start = self.scroll_offset
|
|
724
746
|
visible_end = min(visible_start + self.max_visible_rules, total_rules)
|
|
725
747
|
|
|
@@ -741,6 +763,9 @@ class AutotileRuleDesigner:
|
|
|
741
763
|
d_name = rule.name if len(rule.name) < 20 else rule.name[:17] + ".."
|
|
742
764
|
screen.blit(self.font.render(d_name, True, TEXT_COLOR), (r.x + 5, r.y + 5))
|
|
743
765
|
|
|
766
|
+
# Restore clip
|
|
767
|
+
screen.set_clip(old_clip)
|
|
768
|
+
|
|
744
769
|
if total_rules > self.max_visible_rules:
|
|
745
770
|
if self.scroll_offset > 0:
|
|
746
771
|
arrow_up = "▲"
|
|
@@ -755,11 +780,11 @@ class AutotileRuleDesigner:
|
|
|
755
780
|
arrow_surf = self.font.render(arrow_down, True, (150, 200, 255))
|
|
756
781
|
screen.blit(
|
|
757
782
|
arrow_surf,
|
|
758
|
-
(self.rule_list_area.right - 20, self.rule_list_area.bottom -
|
|
783
|
+
(self.rule_list_area.right - 20, self.rule_list_area.bottom - 20),
|
|
759
784
|
)
|
|
760
785
|
|
|
761
786
|
scrollbar_height = 60
|
|
762
|
-
track_height = self.rule_list_area.height -
|
|
787
|
+
track_height = self.rule_list_area.height - 50
|
|
763
788
|
scroll_ratio = self.scroll_offset / max_scroll if max_scroll > 0 else 0
|
|
764
789
|
|
|
765
790
|
scrollbar_y = (
|
|
@@ -812,7 +837,7 @@ class AutotileRuleDesigner:
|
|
|
812
837
|
elif event.type == pygame.MOUSEMOTION:
|
|
813
838
|
if self.is_scrollbar_dragging:
|
|
814
839
|
relative_y = event.pos[1] - self.rule_list_area.y - 25
|
|
815
|
-
track_height = self.rule_list_area.height -
|
|
840
|
+
track_height = self.rule_list_area.height - 50 # Updated to match drawing
|
|
816
841
|
|
|
817
842
|
if track_height > 0:
|
|
818
843
|
scroll_ratio = max(0, min(1, relative_y / track_height))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf
RENAMED
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf
RENAMED
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/character_collision/shape_editor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/sprite_animation/clipboard_util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/plugins/tileset_collision/collision_painter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_editor-2.0.2 → tilemap_editor-2.0.3}/src/tilemap_editor.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|