tilemap-editor 3.2.2__tar.gz → 3.2.4__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.
Files changed (193) hide show
  1. {tilemap_editor-3.2.2/src/tilemap_editor.egg-info → tilemap_editor-3.2.4}/PKG-INFO +1 -1
  2. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/pyproject.toml +1 -1
  3. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/editor.py +121 -3
  4. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/editor.py +46 -2
  5. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/models.py +3 -0
  6. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/timeline.py +4 -0
  7. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/editor.py +46 -1
  8. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/standalone.py +18 -0
  9. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
  10. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor.egg-info/SOURCES.txt +8 -1
  11. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/tile_grid.py +699 -65
  12. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/tile_selector.py +38 -0
  13. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/toolbar.py +23 -0
  14. tilemap_editor-3.2.4/tests/test_animation_library_grid_offset.py +150 -0
  15. tilemap_editor-3.2.4/tests/test_editor_pan_mode.py +324 -0
  16. tilemap_editor-3.2.4/tests/test_sprite_animation_editor_grid.py +145 -0
  17. tilemap_editor-3.2.4/tests/test_tile_grid_selection.py +573 -0
  18. tilemap_editor-3.2.4/tests/test_tile_selector_pick.py +193 -0
  19. tilemap_editor-3.2.4/tests/test_timeline_invalidate_cache.py +154 -0
  20. tilemap_editor-3.2.4/tests/test_toolbar_tools.py +208 -0
  21. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/LICENSE +0 -0
  22. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/MANIFEST.in +0 -0
  23. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/README.md +0 -0
  24. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  25. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  26. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  27. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  28. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  29. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  30. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  31. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  32. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/arrow-down.svg +0 -0
  33. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/check.svg +0 -0
  34. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/checked.svg +0 -0
  35. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/close.svg +0 -0
  36. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/duplicate.svg +0 -0
  37. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/error.svg +0 -0
  38. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/file.svg +0 -0
  39. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/filedead.svg +0 -0
  40. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/fit.svg +0 -0
  41. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/folder.svg +0 -0
  42. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/grid.svg +0 -0
  43. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/image.svg +0 -0
  44. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/info.svg +0 -0
  45. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/load.svg +0 -0
  46. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/loop.svg +0 -0
  47. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/pan.svg +0 -0
  48. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/pause.svg +0 -0
  49. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/pencil.svg +0 -0
  50. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/play.svg +0 -0
  51. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/plus.svg +0 -0
  52. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/radio.svg +0 -0
  53. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/reset.svg +0 -0
  54. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/save.svg +0 -0
  55. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/stop.svg +0 -0
  56. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/tilemap.svg +0 -0
  57. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/tileset.svg +0 -0
  58. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/unchecked.svg +0 -0
  59. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/warning.svg +0 -0
  60. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/zoomin.svg +0 -0
  61. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/assets/icons/zoomout.svg +0 -0
  62. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/setup.cfg +0 -0
  63. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/configs/themes.py +0 -0
  64. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/constants.py +0 -0
  65. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/event_map.py +0 -0
  66. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/layers.py +0 -0
  67. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/main.py +0 -0
  68. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/__init__.py +0 -0
  69. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/__init__.py +0 -0
  70. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/editor.py +0 -0
  71. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/models.py +0 -0
  72. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/protocols.py +0 -0
  73. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/shape_editor.py +0 -0
  74. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/character_collision/standalone.py +0 -0
  75. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/object_tileset_collision/__init__.py +0 -0
  76. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/object_tileset_collision/editor.py +0 -0
  77. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/object_tileset_collision/models.py +0 -0
  78. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/object_tileset_collision/protocols.py +0 -0
  79. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/object_tileset_collision/standalone.py +0 -0
  80. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/__init__.py +0 -0
  81. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/__main__.py +0 -0
  82. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  83. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/frame_picker.py +0 -0
  84. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/preview.py +0 -0
  85. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/protocols.py +0 -0
  86. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/runtime_load.py +0 -0
  87. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/standalone.py +0 -0
  88. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_animation/validation.py +0 -0
  89. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_editor/__init__.py +0 -0
  90. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_editor/editor.py +0 -0
  91. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/sprite_editor/standalone.py +0 -0
  92. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/__init__.py +0 -0
  93. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/collision_painter.py +0 -0
  94. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/models.py +0 -0
  95. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/plugins/tileset_collision/protocols.py +0 -0
  96. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/standalone_automap.py +0 -0
  97. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/standalone_error_console.py +0 -0
  98. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/standalone_filemanager.py +0 -0
  99. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/standalone_image_viewer.py +0 -0
  100. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap.py +0 -0
  101. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/__init__.py +0 -0
  102. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/__main__.py +0 -0
  103. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/__init__.py +0 -0
  104. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  105. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  106. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  107. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  108. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  109. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  110. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  111. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  112. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  113. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  114. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/check.svg +0 -0
  115. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  116. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/close.svg +0 -0
  117. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  118. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/error.svg +0 -0
  119. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/file.svg +0 -0
  120. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  121. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  122. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  123. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  124. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/image.svg +0 -0
  125. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/info.svg +0 -0
  126. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/load.svg +0 -0
  127. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  128. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  129. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  130. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  131. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/play.svg +0 -0
  132. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  133. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  134. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  135. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/save.svg +0 -0
  136. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  137. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  138. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  139. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  140. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  141. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  142. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  143. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/cli.py +0 -0
  144. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/main.py +0 -0
  145. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor/settings.py +0 -0
  146. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  147. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  148. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor.egg-info/requires.txt +0 -0
  149. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  150. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/ttypes/__init__.py +0 -0
  151. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/ttypes/tilemap.py +0 -0
  152. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/__init__.py +0 -0
  153. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/editor_preference.py +0 -0
  154. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/error_handler.py +0 -0
  155. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/font_manager.py +0 -0
  156. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/history.py +0 -0
  157. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/icon_manager.py +0 -0
  158. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/icons_cache.py +0 -0
  159. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/log_capture.py +0 -0
  160. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/project_paths.py +0 -0
  161. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/serialization.py +0 -0
  162. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/standalone.py +0 -0
  163. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/utils/validation.py +0 -0
  164. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/__init__.py +0 -0
  165. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/automap_models.py +0 -0
  166. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/autotile_template.py +0 -0
  167. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/autotiler.py +0 -0
  168. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/filemanager.py +0 -0
  169. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/input.py +0 -0
  170. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/layer_selector.py +0 -0
  171. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/map_properties.py +0 -0
  172. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/mapsetup.py +0 -0
  173. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/regex_automap_designer.py +0 -0
  174. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/spritesheet_grid.py +0 -0
  175. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/collision_layer_mask.py +0 -0
  176. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  177. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/draw_utils.py +0 -0
  178. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/fileinput.py +0 -0
  179. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/layer_type_dialog.py +0 -0
  180. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/menubar.py +0 -0
  181. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/mode_indicator.py +0 -0
  182. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/notification.py +0 -0
  183. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/property_editor.py +0 -0
  184. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/region_selector.py +0 -0
  185. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/status_bar.py +0 -0
  186. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/theme.py +0 -0
  187. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/tileset_type_dialog.py +0 -0
  188. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/src/widgets/ui/tooltip.py +0 -0
  189. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/tests/test_collision_layer_mask.py +0 -0
  190. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/tests/test_collision_layer_sidebar.py +0 -0
  191. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/tests/test_project_paths.py +0 -0
  192. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/tests/test_render_scale.py +0 -0
  193. {tilemap_editor-3.2.2 → tilemap_editor-3.2.4}/tests/test_tilemap_save.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 3.2.2
3
+ Version: 3.2.4
4
4
  Summary: Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-editor"
7
- version = "3.2.2"
7
+ version = "3.2.4"
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"
@@ -150,6 +150,9 @@ class Editor:
150
150
  self.running = False
151
151
  self.pan_mode = False
152
152
  self.autotile_mode = False
153
+ self.eraser_mode = False
154
+ self.select_mode = False
155
+ self._prev_tool = None
153
156
 
154
157
  if isinstance(size, tuple) and len(size) == 2:
155
158
  self.screen = pygame.display.set_mode(size, pygame.RESIZABLE)
@@ -684,13 +687,17 @@ class Editor:
684
687
  self.open_file_manager(
685
688
  on_select=self._launch_animation_editor_with_image,
686
689
  initial_dir=self.data_root,
687
- allowed_exts=[".png", ".jpg", ".jpeg"],
690
+ allowed_exts=[".png", ".jpg", ".jpeg", ".json"],
688
691
  mode="open",
689
692
  )
690
693
 
691
694
  def _launch_animation_editor_with_image(self, path: Path):
692
- """Launch animation editor subprocess with selected image."""
695
+ """Launch animation editor subprocess with selected image or JSON."""
693
696
  try:
697
+ if path.suffix.lower() == ".json":
698
+ self._launch_animation_editor_with_json(path)
699
+ return
700
+
694
701
  tile_size = "32x32"
695
702
  if hasattr(self.tilemap, "tile_size") and self.tilemap.tile_size:
696
703
  tw, th = self.tilemap.tile_size
@@ -711,6 +718,47 @@ class Editor:
711
718
  except Exception as e:
712
719
  error_handler.capture(e, context="launch_animation_editor")
713
720
 
721
+ def _launch_animation_editor_with_json(self, path: Path) -> None:
722
+ """Launch animation editor from a saved .anim.json file."""
723
+ try:
724
+ from plugins.sprite_animation.models import AnimationLibrary
725
+ from utils.project_paths import resolve_project_path
726
+
727
+ lib = AnimationLibrary.load(path)
728
+ spritesheet_path = lib.spritesheet_path
729
+ tile_size = lib.tile_size
730
+
731
+ if spritesheet_path:
732
+ resolved = resolve_project_path(
733
+ spritesheet_path,
734
+ path.parent,
735
+ fallback_roots=[self.base_path] if self.base_path else None,
736
+ must_exist=True,
737
+ )
738
+ else:
739
+ resolved = None
740
+
741
+ if not resolved or not resolved.exists():
742
+ print(f"Could not locate spritesheet for animation file: {path.name}")
743
+ return
744
+
745
+ args = [
746
+ str(resolved),
747
+ "--tile-size", f"{tile_size[0]}x{tile_size[1]}",
748
+ "--load", str(path),
749
+ "--data-root", str(self.data_root),
750
+ ]
751
+ process = launch_standalone(
752
+ "plugins.sprite_animation.standalone",
753
+ args,
754
+ cwd=self.base_path,
755
+ text=True,
756
+ )
757
+ self.child_processes.append(process)
758
+ print(f"Launched animation editor with: {path.name} (spritesheet: {resolved.name})")
759
+ except Exception as e:
760
+ error_handler.capture(e, context="launch_animation_editor")
761
+
714
762
  def launch_sprite_editor(self):
715
763
  """Launch the sprite editor in a new window."""
716
764
  self.open_file_manager(
@@ -775,6 +823,11 @@ class Editor:
775
823
 
776
824
  args = [str(path), "--tile-size", tile_size, "--data-root", str(self.data_root)]
777
825
 
826
+ # Collect auto-tile variant groups for this tileset and pass as --propagation-groups
827
+ propagation_groups_path = self._write_propagation_groups(path)
828
+ if propagation_groups_path:
829
+ args.extend(["--propagation-groups", str(propagation_groups_path)])
830
+
778
831
  collision_dir = self.data_root / self.config.get("collision_paths", {}).get("tileset", "collision")
779
832
  collision_path = collision_dir / f"{path.stem}.collision.json"
780
833
  if collision_path.exists():
@@ -793,6 +846,54 @@ class Editor:
793
846
  if logger:
794
847
  logger.info(msg)
795
848
 
849
+ def _write_propagation_groups(self, tileset_path: Path) -> Optional[Path]:
850
+ """Collect auto-tile variant groups for a tileset and write to temp JSON.
851
+
852
+ Returns the path to the temp file, or None if no autotiler data is available.
853
+ """
854
+ if not hasattr(self, "autotiler") or not self.autotiler:
855
+ return None
856
+
857
+ tw = getattr(self, "tileset_widget", None)
858
+ if not tw or not tw.tilesets:
859
+ return None
860
+
861
+ # Find the tileset index matching the given path
862
+ resolved_path = Path(tileset_path).resolve()
863
+ tileset_index = None
864
+ for idx, ts in enumerate(tw.tilesets):
865
+ try:
866
+ if Path(ts.path).resolve() == resolved_path:
867
+ tileset_index = idx
868
+ break
869
+ except (OSError, ValueError):
870
+ continue
871
+
872
+ if tileset_index is None:
873
+ return None
874
+
875
+ # Collect variant_ids grouped by group_id from autotile rules matching this tileset
876
+ groups: Dict[str, List[int]] = {}
877
+ for group in self.autotiler.groups:
878
+ for rule in group.rules:
879
+ if rule.tileset_index == tileset_index and rule.variant_ids:
880
+ gid = rule.group_id or group.name
881
+ if gid not in groups:
882
+ groups[gid] = []
883
+ groups[gid].extend(rule.variant_ids)
884
+
885
+ if not groups:
886
+ return None
887
+
888
+ import json
889
+ import tempfile
890
+ fd, tmp_path = tempfile.mkstemp(suffix=".json", prefix="propagation_groups_")
891
+ with os.fdopen(fd, "w") as f:
892
+ json.dump(groups, f)
893
+
894
+ print(f"[COLLISION] Wrote {len(groups)} propagation groups to {tmp_path}")
895
+ return Path(tmp_path)
896
+
796
897
  def _launch_object_tileset_collision_editor_with_image(self, path: Path):
797
898
  """Launch object tileset collision editor (region-based)."""
798
899
  logger = self.logger if hasattr(self, 'logger') else None
@@ -1018,7 +1119,24 @@ class Editor:
1018
1119
  self.perform_load()
1019
1120
  continue
1020
1121
  elif event.key == pygame.K_SPACE:
1021
- self.pan_mode = not self.pan_mode
1122
+ if self.pan_mode:
1123
+ # Restoring: turn off pan, re-enable previous tool
1124
+ self.pan_mode = False
1125
+ if getattr(self, "_prev_tool", None) == "select":
1126
+ self.select_mode = True
1127
+ elif getattr(self, "_prev_tool", None) == "eraser":
1128
+ self.eraser_mode = True
1129
+ else:
1130
+ # Entering pan: save current tool, turn off others
1131
+ if self.select_mode:
1132
+ self._prev_tool = "select"
1133
+ elif self.eraser_mode:
1134
+ self._prev_tool = "eraser"
1135
+ else:
1136
+ self._prev_tool = None
1137
+ self.pan_mode = True
1138
+ self.select_mode = False
1139
+ self.eraser_mode = False
1022
1140
  continue
1023
1141
  elif event.mod & pygame.KMOD_CTRL and event.key == pygame.K_g:
1024
1142
  self.toggle_grid()
@@ -1367,7 +1367,7 @@ class SpriteAnimationEditor:
1367
1367
  self.preview.set_surface(self._surface, self._tile_size)
1368
1368
  self.timeline.surface = self._surface
1369
1369
  self.timeline.tile_size = self._tile_size
1370
- self.timeline._thumb_cache.clear()
1370
+ self.timeline.invalidate_cache()
1371
1371
 
1372
1372
  # Update input fields to show clamped values
1373
1373
  self._frame_width_input = str(width)
@@ -1404,7 +1404,7 @@ class SpriteAnimationEditor:
1404
1404
  if hasattr(self.timeline, "grid_offset_x"):
1405
1405
  self.timeline.grid_offset_x = offset_x
1406
1406
  self.timeline.grid_offset_y = offset_y
1407
- self.timeline._thumb_cache.clear()
1407
+ self.timeline.invalidate_cache()
1408
1408
 
1409
1409
  # Update preview with offset (if it has the attribute)
1410
1410
  if hasattr(self.preview, "grid_offset_x"):
@@ -1420,6 +1420,43 @@ class SpriteAnimationEditor:
1420
1420
  self._offset_x_input = str(self._grid_offset_x)
1421
1421
  self._offset_y_input = str(self._grid_offset_y)
1422
1422
 
1423
+ def _apply_library_grid_settings(self) -> None:
1424
+ """Sync tile_size and grid_offset from the loaded library to all widgets."""
1425
+ tw, th = self.library.tile_size
1426
+ self._tile_size = (tw, th)
1427
+ self.library.tile_size = (tw, th)
1428
+
1429
+ # Update frame picker
1430
+ self.frame_picker.set_surface(self._surface, self._tile_size)
1431
+
1432
+ # Update preview and timeline
1433
+ self.preview.set_surface(self._surface, self._tile_size)
1434
+ self.timeline.surface = self._surface
1435
+ self.timeline.tile_size = self._tile_size
1436
+ self.timeline.invalidate_cache()
1437
+
1438
+ # Update frame size input fields
1439
+ self._frame_width_input = str(tw)
1440
+ self._frame_height_input = str(th)
1441
+
1442
+ # Sync grid offset from library
1443
+ gx, gy = self.library.grid_offset
1444
+ self._grid_offset_x = gx
1445
+ self._grid_offset_y = gy
1446
+ self._offset_x_input = str(gx)
1447
+ self._offset_y_input = str(gy)
1448
+
1449
+ # Propagate offset to all widgets
1450
+ if hasattr(self.frame_picker, "set_grid_offset"):
1451
+ self.frame_picker.set_grid_offset(gx, gy)
1452
+ if hasattr(self.timeline, "grid_offset_x"):
1453
+ self.timeline.grid_offset_x = gx
1454
+ self.timeline.grid_offset_y = gy
1455
+ self.timeline.invalidate_cache()
1456
+ if hasattr(self.preview, "grid_offset_x"):
1457
+ self.preview.grid_offset_x = gx
1458
+ self.preview.grid_offset_y = gy
1459
+
1423
1460
  def _sync_active_animation(self) -> None:
1424
1461
  """Push current animation data to sub-widgets."""
1425
1462
  anim = self._get_active()
@@ -1843,6 +1880,7 @@ class SpriteAnimationEditor:
1843
1880
  print(f"Warning: Could not import FileManager: {e}")
1844
1881
  path = self._default_save_path()
1845
1882
  try:
1883
+ self.library.grid_offset = (self._grid_offset_x, self._grid_offset_y)
1846
1884
  self.library.save(path, base_path=path.parent)
1847
1885
  self._last_saved_path = path
1848
1886
  print(f"Animations saved to {path}")
@@ -1888,6 +1926,7 @@ class SpriteAnimationEditor:
1888
1926
  if self._last_saved_path:
1889
1927
  # Save to existing path
1890
1928
  try:
1929
+ self.library.grid_offset = (self._grid_offset_x, self._grid_offset_y)
1891
1930
  self.library.save(
1892
1931
  self._last_saved_path,
1893
1932
  base_path=self._last_saved_path.parent,
@@ -1913,6 +1952,7 @@ class SpriteAnimationEditor:
1913
1952
  try:
1914
1953
  self.library = AnimationLibrary.load(path)
1915
1954
  self._resolve_library_paths(path)
1955
+ self._apply_library_grid_settings()
1916
1956
  names = self.library.animation_names()
1917
1957
  self._active_anim_name = names[0] if names else None
1918
1958
  if not names:
@@ -1948,6 +1988,8 @@ class SpriteAnimationEditor:
1948
1988
  def _on_save_file_selected(self, path: Path) -> None:
1949
1989
  """Callback when user selects a file to save to."""
1950
1990
  try:
1991
+ # Sync current grid offset into library before saving
1992
+ self.library.grid_offset = (self._grid_offset_x, self._grid_offset_y)
1951
1993
  self.library.save(path, base_path=path.parent)
1952
1994
  self._last_saved_path = path # Track for quick save
1953
1995
  print(f"Animations saved to {path}")
@@ -1968,6 +2010,7 @@ class SpriteAnimationEditor:
1968
2010
  self.library = AnimationLibrary.load(path)
1969
2011
  self._resolve_library_paths(path)
1970
2012
  self._last_saved_path = path # Track loaded file as save location
2013
+ self._apply_library_grid_settings()
1971
2014
  names = self.library.animation_names()
1972
2015
  self._active_anim_name = names[0] if names else None
1973
2016
  if not names:
@@ -2110,6 +2153,7 @@ class SpriteAnimationEditor:
2110
2153
  def load_animation_data(self, data: dict) -> None:
2111
2154
  """Load animation library from a dict (e.g. from project JSON)."""
2112
2155
  self.library = AnimationLibrary.from_dict(data)
2156
+ self._apply_library_grid_settings()
2113
2157
  names = self.library.animation_names()
2114
2158
  self._active_anim_name = names[0] if names else None
2115
2159
  if not names:
@@ -167,6 +167,7 @@ class AnimationLibrary:
167
167
  animations: Dict[str, Animation] = field(default_factory=dict)
168
168
  spritesheet_path: Optional[str] = None
169
169
  tile_size: Tuple[int, int] = (32, 32)
170
+ grid_offset: Tuple[int, int] = (0, 0)
170
171
 
171
172
  def add_animation(self, anim: Animation) -> None:
172
173
  self.animations[anim.name] = anim
@@ -199,6 +200,7 @@ class AnimationLibrary:
199
200
  return {
200
201
  "spritesheet_path": spritesheet_path,
201
202
  "tile_size": list(self.tile_size),
203
+ "grid_offset": list(self.grid_offset),
202
204
  "animations": {
203
205
  name: anim.to_dict() for name, anim in self.animations.items()
204
206
  },
@@ -209,6 +211,7 @@ class AnimationLibrary:
209
211
  lib = AnimationLibrary(
210
212
  spritesheet_path=data.get("spritesheet_path"),
211
213
  tile_size=tuple(data.get("tile_size", [32, 32])),
214
+ grid_offset=tuple(data.get("grid_offset", [0, 0])),
212
215
  )
213
216
  for name, anim_data in data.get("animations", {}).items():
214
217
  lib.animations[name] = Animation.from_dict(anim_data)
@@ -140,6 +140,10 @@ class Timeline:
140
140
  self.tile_size = tile_size
141
141
  self._thumb_cache.clear()
142
142
 
143
+ def invalidate_cache(self) -> None:
144
+ """Clear the thumbnail cache. Call after external changes to surface, tile_size, or grid offset."""
145
+ self._thumb_cache.clear()
146
+
143
147
  def resize(self, rect: Rect) -> None:
144
148
  self.rect = rect
145
149
 
@@ -72,6 +72,9 @@ class TilesetCollisionEditor:
72
72
  self._toast_timer: float = 0.0
73
73
  self._toast_start: int = 0
74
74
 
75
+ # Auto-tile propagation: group_id -> [variant_ids]
76
+ self._propagation_groups: Dict[str, List[int]] = {}
77
+
75
78
  # Collision library
76
79
  self.library = TilesetCollisionLibrary(
77
80
  tileset_name=self._tileset_name,
@@ -436,13 +439,53 @@ class TilesetCollisionEditor:
436
439
  error_handler.capture(e, context="load_collision_data")
437
440
 
438
441
  def save_to_file(self, path: Path) -> None:
439
- """Save collision data to file"""
442
+ """Save collision data to file, auto-propagating within auto-tile groups."""
440
443
  try:
441
444
  self._save_tile_collision_for_selection()
445
+ self._propagate_collision_to_groups()
442
446
  self.library.save(path)
443
447
  except Exception as e:
444
448
  error_handler.capture(e, context="save_collision_file")
445
449
 
450
+ def _propagate_collision_to_groups(self) -> None:
451
+ """Propagate collision shapes within each auto-tile group.
452
+
453
+ If any tile in a propagation group has collision shapes, those shapes
454
+ are copied to all other tiles in the same group that don't already
455
+ have their own collision data.
456
+ """
457
+ if not self._propagation_groups:
458
+ return
459
+
460
+ propagated_count = 0
461
+ for group_id, variant_ids in self._propagation_groups.items():
462
+ # Find the first tile in this group that has collision shapes
463
+ source_shapes = None
464
+ for vid in variant_ids:
465
+ tile_data = self.library.tiles.get(vid)
466
+ if tile_data and tile_data.shapes:
467
+ source_shapes = tile_data.shapes
468
+ break
469
+
470
+ if source_shapes is None:
471
+ continue
472
+
473
+ # Propagate to all variants in the group that lack collision
474
+ for vid in variant_ids:
475
+ existing = self.library.tiles.get(vid)
476
+ if existing is None:
477
+ self.library.tiles[vid] = TileCollisionData(
478
+ tile_id=vid,
479
+ shapes=[CollisionPolygon(
480
+ vertices=list(s.vertices),
481
+ one_way=s.one_way,
482
+ ) for s in source_shapes],
483
+ )
484
+ propagated_count += 1
485
+
486
+ if propagated_count:
487
+ self._show_toast(f"Propagated collision to {propagated_count} auto-tile variants")
488
+
446
489
  def load_from_file(self, path: Path) -> None:
447
490
  """Load collision data from file"""
448
491
  try:
@@ -829,6 +872,7 @@ class TilesetCollisionEditor:
829
872
  tile_size: Tuple[int, int] = (32, 32),
830
873
  window_size: Tuple[int, int] = (1200, 800),
831
874
  data_root: Path = None,
875
+ propagation_groups: Optional[Dict[str, List[int]]] = None,
832
876
  ) -> "TilesetCollisionEditor":
833
877
  """Create editor from tileset image path (for standalone use)"""
834
878
  surface = pygame.image.load(tileset_path).convert_alpha()
@@ -838,6 +882,7 @@ class TilesetCollisionEditor:
838
882
  editor._tileset_path_stem = tileset_path.stem
839
883
  editor._tileset_name = tileset_path.stem # Use actual filename, not "Tileset"
840
884
  editor.library.tileset_name = tileset_path.stem
885
+ editor._propagation_groups = propagation_groups or {}
841
886
  return editor
842
887
 
843
888
  def run(self) -> None:
@@ -86,6 +86,12 @@ def main(argv: list[str] | None = None) -> None:
86
86
  required=True,
87
87
  help="Path to project data root directory (REQUIRED)",
88
88
  )
89
+ parser.add_argument(
90
+ "--propagation-groups",
91
+ type=Path,
92
+ default=None,
93
+ help="Path to JSON file mapping auto-tile group IDs to variant ID lists",
94
+ )
89
95
 
90
96
  args = parser.parse_args(argv)
91
97
 
@@ -107,11 +113,23 @@ def main(argv: list[str] | None = None) -> None:
107
113
  screen = pygame.display.set_mode(window_size, pygame.RESIZABLE)
108
114
  pygame.display.set_caption(f"Tileset Collision Editor — {args.image.name}")
109
115
 
116
+ propagation_groups = None
117
+ if args.propagation_groups and args.propagation_groups.exists():
118
+ import json
119
+ with open(args.propagation_groups) as f:
120
+ propagation_groups = json.load(f)
121
+ print(f"Loaded {len(propagation_groups)} auto-tile propagation groups")
122
+ try:
123
+ args.propagation_groups.unlink()
124
+ except OSError:
125
+ pass
126
+
110
127
  editor = TilesetCollisionEditor.from_path(
111
128
  args.image,
112
129
  tile_size=tile_size,
113
130
  window_size=window_size,
114
131
  data_root=data_root,
132
+ propagation_groups=propagation_groups,
115
133
  )
116
134
 
117
135
  if args.load and args.load.exists():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 3.2.2
3
+ Version: 3.2.4
4
4
  Summary: Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -177,8 +177,15 @@ src/widgets/ui/theme.py
177
177
  src/widgets/ui/tileset_type_dialog.py
178
178
  src/widgets/ui/toolbar.py
179
179
  src/widgets/ui/tooltip.py
180
+ tests/test_animation_library_grid_offset.py
180
181
  tests/test_collision_layer_mask.py
181
182
  tests/test_collision_layer_sidebar.py
183
+ tests/test_editor_pan_mode.py
182
184
  tests/test_project_paths.py
183
185
  tests/test_render_scale.py
184
- tests/test_tilemap_save.py
186
+ tests/test_sprite_animation_editor_grid.py
187
+ tests/test_tile_grid_selection.py
188
+ tests/test_tile_selector_pick.py
189
+ tests/test_tilemap_save.py
190
+ tests/test_timeline_invalidate_cache.py
191
+ tests/test_toolbar_tools.py