tilemap-editor 3.2.3__tar.gz → 3.2.5__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.3/src/tilemap_editor.egg-info → tilemap_editor-3.2.5}/PKG-INFO +1 -1
  2. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/pyproject.toml +1 -1
  3. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/editor.py +53 -0
  4. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/editor.py +46 -1
  5. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/standalone.py +18 -0
  6. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
  7. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor.egg-info/SOURCES.txt +8 -1
  8. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/layer_selector.py +9 -9
  9. tilemap_editor-3.2.5/tests/test_animation_library_grid_offset.py +150 -0
  10. tilemap_editor-3.2.5/tests/test_editor_pan_mode.py +324 -0
  11. tilemap_editor-3.2.5/tests/test_sprite_animation_editor_grid.py +145 -0
  12. tilemap_editor-3.2.5/tests/test_tile_grid_selection.py +573 -0
  13. tilemap_editor-3.2.5/tests/test_tile_selector_pick.py +193 -0
  14. tilemap_editor-3.2.5/tests/test_timeline_invalidate_cache.py +154 -0
  15. tilemap_editor-3.2.5/tests/test_toolbar_tools.py +208 -0
  16. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/LICENSE +0 -0
  17. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/MANIFEST.in +0 -0
  18. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/README.md +0 -0
  19. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  20. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  21. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  22. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  23. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  24. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  25. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  26. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  27. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/arrow-down.svg +0 -0
  28. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/check.svg +0 -0
  29. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/checked.svg +0 -0
  30. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/close.svg +0 -0
  31. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/duplicate.svg +0 -0
  32. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/error.svg +0 -0
  33. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/file.svg +0 -0
  34. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/filedead.svg +0 -0
  35. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/fit.svg +0 -0
  36. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/folder.svg +0 -0
  37. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/grid.svg +0 -0
  38. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/image.svg +0 -0
  39. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/info.svg +0 -0
  40. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/load.svg +0 -0
  41. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/loop.svg +0 -0
  42. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/pan.svg +0 -0
  43. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/pause.svg +0 -0
  44. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/pencil.svg +0 -0
  45. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/play.svg +0 -0
  46. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/plus.svg +0 -0
  47. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/radio.svg +0 -0
  48. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/reset.svg +0 -0
  49. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/save.svg +0 -0
  50. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/stop.svg +0 -0
  51. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/tilemap.svg +0 -0
  52. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/tileset.svg +0 -0
  53. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/unchecked.svg +0 -0
  54. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/warning.svg +0 -0
  55. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/zoomin.svg +0 -0
  56. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/assets/icons/zoomout.svg +0 -0
  57. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/setup.cfg +0 -0
  58. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/configs/themes.py +0 -0
  59. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/constants.py +0 -0
  60. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/event_map.py +0 -0
  61. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/layers.py +0 -0
  62. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/main.py +0 -0
  63. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/__init__.py +0 -0
  64. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/__init__.py +0 -0
  65. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/editor.py +0 -0
  66. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/models.py +0 -0
  67. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/protocols.py +0 -0
  68. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/shape_editor.py +0 -0
  69. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/character_collision/standalone.py +0 -0
  70. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/object_tileset_collision/__init__.py +0 -0
  71. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/object_tileset_collision/editor.py +0 -0
  72. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/object_tileset_collision/models.py +0 -0
  73. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/object_tileset_collision/protocols.py +0 -0
  74. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/object_tileset_collision/standalone.py +0 -0
  75. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/__init__.py +0 -0
  76. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/__main__.py +0 -0
  77. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  78. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/editor.py +0 -0
  79. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/frame_picker.py +0 -0
  80. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/models.py +0 -0
  81. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/preview.py +0 -0
  82. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/protocols.py +0 -0
  83. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/runtime_load.py +0 -0
  84. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/standalone.py +0 -0
  85. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/timeline.py +0 -0
  86. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_animation/validation.py +0 -0
  87. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_editor/__init__.py +0 -0
  88. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_editor/editor.py +0 -0
  89. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/sprite_editor/standalone.py +0 -0
  90. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/__init__.py +0 -0
  91. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/collision_painter.py +0 -0
  92. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/models.py +0 -0
  93. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/plugins/tileset_collision/protocols.py +0 -0
  94. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/standalone_automap.py +0 -0
  95. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/standalone_error_console.py +0 -0
  96. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/standalone_filemanager.py +0 -0
  97. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/standalone_image_viewer.py +0 -0
  98. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap.py +0 -0
  99. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/__init__.py +0 -0
  100. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/__main__.py +0 -0
  101. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/__init__.py +0 -0
  102. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  103. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  104. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  105. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  106. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  107. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  108. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  109. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  110. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  111. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  112. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/check.svg +0 -0
  113. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  114. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/close.svg +0 -0
  115. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  116. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/error.svg +0 -0
  117. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/file.svg +0 -0
  118. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  119. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  120. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  121. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  122. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/image.svg +0 -0
  123. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/info.svg +0 -0
  124. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/load.svg +0 -0
  125. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  126. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  127. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  128. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  129. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/play.svg +0 -0
  130. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  131. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  132. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  133. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/save.svg +0 -0
  134. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  135. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  136. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  137. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  138. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  139. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  140. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  141. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/cli.py +0 -0
  142. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/main.py +0 -0
  143. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor/settings.py +0 -0
  144. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  145. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  146. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor.egg-info/requires.txt +0 -0
  147. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  148. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/ttypes/__init__.py +0 -0
  149. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/ttypes/tilemap.py +0 -0
  150. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/__init__.py +0 -0
  151. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/editor_preference.py +0 -0
  152. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/error_handler.py +0 -0
  153. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/font_manager.py +0 -0
  154. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/history.py +0 -0
  155. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/icon_manager.py +0 -0
  156. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/icons_cache.py +0 -0
  157. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/log_capture.py +0 -0
  158. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/project_paths.py +0 -0
  159. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/serialization.py +0 -0
  160. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/standalone.py +0 -0
  161. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/utils/validation.py +0 -0
  162. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/__init__.py +0 -0
  163. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/automap_models.py +0 -0
  164. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/autotile_template.py +0 -0
  165. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/autotiler.py +0 -0
  166. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/filemanager.py +0 -0
  167. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/input.py +0 -0
  168. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/map_properties.py +0 -0
  169. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/mapsetup.py +0 -0
  170. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/regex_automap_designer.py +0 -0
  171. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/spritesheet_grid.py +0 -0
  172. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/tile_grid.py +0 -0
  173. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/tile_selector.py +0 -0
  174. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/collision_layer_mask.py +0 -0
  175. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  176. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/draw_utils.py +0 -0
  177. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/fileinput.py +0 -0
  178. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/layer_type_dialog.py +0 -0
  179. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/menubar.py +0 -0
  180. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/mode_indicator.py +0 -0
  181. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/notification.py +0 -0
  182. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/property_editor.py +0 -0
  183. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/region_selector.py +0 -0
  184. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/status_bar.py +0 -0
  185. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/theme.py +0 -0
  186. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/tileset_type_dialog.py +0 -0
  187. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/toolbar.py +0 -0
  188. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/src/widgets/ui/tooltip.py +0 -0
  189. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/tests/test_collision_layer_mask.py +0 -0
  190. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/tests/test_collision_layer_sidebar.py +0 -0
  191. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/tests/test_project_paths.py +0 -0
  192. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/tests/test_render_scale.py +0 -0
  193. {tilemap_editor-3.2.3 → tilemap_editor-3.2.5}/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.3
3
+ Version: 3.2.5
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.3"
7
+ version = "3.2.5"
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"
@@ -823,6 +823,11 @@ class Editor:
823
823
 
824
824
  args = [str(path), "--tile-size", tile_size, "--data-root", str(self.data_root)]
825
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
+
826
831
  collision_dir = self.data_root / self.config.get("collision_paths", {}).get("tileset", "collision")
827
832
  collision_path = collision_dir / f"{path.stem}.collision.json"
828
833
  if collision_path.exists():
@@ -841,6 +846,54 @@ class Editor:
841
846
  if logger:
842
847
  logger.info(msg)
843
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
+
844
897
  def _launch_object_tileset_collision_editor_with_image(self, path: Path):
845
898
  """Launch object tileset collision editor (region-based)."""
846
899
  logger = self.logger if hasattr(self, 'logger') else None
@@ -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.3
3
+ Version: 3.2.5
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
@@ -382,13 +382,6 @@ class LayerSelector:
382
382
  pygame.draw.rect(screen, color, item_rect)
383
383
  pygame.draw.rect(screen, COLORS.border_soft, item_rect, 1)
384
384
 
385
- if i == self.renaming_layer_idx:
386
- pygame.draw.rect(
387
- screen,
388
- COLORS.selected,
389
- Rect(item_rect.x + 4, item_rect.y + 4, 120, 20),
390
- border_radius=SHAPE.radius_sm,
391
- )
392
385
  mx, my = pygame.mouse.get_pos()
393
386
  eye_rect = self._get_eye_icon_rect(i, (mx, my))
394
387
  lock_rect = self._get_lock_icon_rect(i, (mx, my))
@@ -396,13 +389,20 @@ class LayerSelector:
396
389
  self.editor.tooltip.show("Toggle Visibility", (mx + 10, my + 10))
397
390
  elif lock_rect and lock_rect.collidepoint(mx, my):
398
391
  self.editor.tooltip.show("Toggle Lock", (mx + 10, my + 10))
392
+
393
+ if i == self.renaming_layer_idx:
394
+ pygame.draw.rect(
395
+ screen,
396
+ COLORS.selected,
397
+ Rect(item_rect.x + 4, item_rect.y + 4, 120, 20),
398
+ border_radius=SHAPE.radius_sm,
399
+ )
399
400
  name_txt = self.font_layer.render(
400
401
  self.rename_text + "|", True, self.text_color
401
402
  )
402
- screen.blit(name_txt, (item_rect.x + 5, item_rect.y + 5))
403
403
  else:
404
404
  name_txt = self.font_layer.render(layer.name, True, self.text_color)
405
- screen.blit(name_txt, (item_rect.x + 5, item_rect.y + 5))
405
+ screen.blit(name_txt, (item_rect.x + 5, item_rect.y + 5))
406
406
 
407
407
  eye_x = item_rect.right - 25
408
408
  eye_y = item_rect.y + 7
@@ -0,0 +1,150 @@
1
+ """
2
+ Tests for AnimationLibrary.grid_offset field added in PR.
3
+
4
+ Covers:
5
+ - Default value
6
+ - to_dict serializes grid_offset
7
+ - from_dict deserializes grid_offset
8
+ - from_dict falls back to (0, 0) when key is missing (backward compat)
9
+ - save/load round-trip preserves grid_offset
10
+ - grid_offset is a tuple (not list) after deserialization
11
+ """
12
+
13
+ import json
14
+ import tempfile
15
+ from pathlib import Path
16
+
17
+ import pytest
18
+
19
+ import sys
20
+ sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
21
+
22
+
23
+ class TestAnimationLibraryGridOffset:
24
+ """Tests for the grid_offset field on AnimationLibrary."""
25
+
26
+ def test_default_grid_offset_is_zero(self):
27
+ from plugins.sprite_animation.models import AnimationLibrary
28
+
29
+ lib = AnimationLibrary()
30
+ assert lib.grid_offset == (0, 0)
31
+
32
+ def test_to_dict_includes_grid_offset(self):
33
+ from plugins.sprite_animation.models import AnimationLibrary
34
+
35
+ lib = AnimationLibrary(grid_offset=(4, 8))
36
+ d = lib.to_dict()
37
+ assert "grid_offset" in d
38
+ assert d["grid_offset"] == [4, 8]
39
+
40
+ def test_to_dict_zero_grid_offset(self):
41
+ from plugins.sprite_animation.models import AnimationLibrary
42
+
43
+ lib = AnimationLibrary(grid_offset=(0, 0))
44
+ d = lib.to_dict()
45
+ assert d["grid_offset"] == [0, 0]
46
+
47
+ def test_from_dict_reads_grid_offset(self):
48
+ from plugins.sprite_animation.models import AnimationLibrary
49
+
50
+ data = {
51
+ "spritesheet_path": None,
52
+ "tile_size": [32, 32],
53
+ "grid_offset": [10, 20],
54
+ "animations": {},
55
+ }
56
+ lib = AnimationLibrary.from_dict(data)
57
+ assert lib.grid_offset == (10, 20)
58
+
59
+ def test_from_dict_missing_grid_offset_defaults_to_zero(self):
60
+ """Backward-compat: old JSON files without grid_offset key should load fine."""
61
+ from plugins.sprite_animation.models import AnimationLibrary
62
+
63
+ data = {
64
+ "spritesheet_path": None,
65
+ "tile_size": [32, 32],
66
+ "animations": {},
67
+ }
68
+ lib = AnimationLibrary.from_dict(data)
69
+ assert lib.grid_offset == (0, 0)
70
+
71
+ def test_from_dict_grid_offset_is_tuple(self):
72
+ """grid_offset should be a tuple after deserialization, not a list."""
73
+ from plugins.sprite_animation.models import AnimationLibrary
74
+
75
+ data = {
76
+ "spritesheet_path": None,
77
+ "tile_size": [32, 32],
78
+ "grid_offset": [5, 3],
79
+ "animations": {},
80
+ }
81
+ lib = AnimationLibrary.from_dict(data)
82
+ assert isinstance(lib.grid_offset, tuple)
83
+
84
+ def test_save_load_round_trip_preserves_grid_offset(self):
85
+ """save() then load() must preserve a non-zero grid_offset."""
86
+ from plugins.sprite_animation.models import AnimationLibrary
87
+
88
+ lib = AnimationLibrary(grid_offset=(7, 13), tile_size=(16, 16))
89
+ with tempfile.TemporaryDirectory() as tmp:
90
+ path = Path(tmp) / "anim.json"
91
+ lib.save(path)
92
+ loaded = AnimationLibrary.load(path)
93
+
94
+ assert loaded.grid_offset == (7, 13)
95
+
96
+ def test_save_load_round_trip_zero_grid_offset(self):
97
+ """save() then load() preserves (0, 0) grid_offset."""
98
+ from plugins.sprite_animation.models import AnimationLibrary
99
+
100
+ lib = AnimationLibrary(grid_offset=(0, 0))
101
+ with tempfile.TemporaryDirectory() as tmp:
102
+ path = Path(tmp) / "anim.json"
103
+ lib.save(path)
104
+ loaded = AnimationLibrary.load(path)
105
+
106
+ assert loaded.grid_offset == (0, 0)
107
+
108
+ def test_to_dict_grid_offset_is_list(self):
109
+ """grid_offset is serialized as a JSON list (not tuple) for JSON compat."""
110
+ from plugins.sprite_animation.models import AnimationLibrary
111
+
112
+ lib = AnimationLibrary(grid_offset=(2, 6))
113
+ d = lib.to_dict()
114
+ assert isinstance(d["grid_offset"], list)
115
+
116
+ def test_grid_offset_stored_alongside_tile_size(self):
117
+ """Both tile_size and grid_offset appear in the serialized dict."""
118
+ from plugins.sprite_animation.models import AnimationLibrary
119
+
120
+ lib = AnimationLibrary(tile_size=(16, 16), grid_offset=(4, 4))
121
+ d = lib.to_dict()
122
+ assert d["tile_size"] == [16, 16]
123
+ assert d["grid_offset"] == [4, 4]
124
+
125
+ def test_from_dict_large_grid_offset(self):
126
+ """Arbitrary large values are preserved."""
127
+ from plugins.sprite_animation.models import AnimationLibrary
128
+
129
+ data = {
130
+ "spritesheet_path": None,
131
+ "tile_size": [32, 32],
132
+ "grid_offset": [128, 256],
133
+ "animations": {},
134
+ }
135
+ lib = AnimationLibrary.from_dict(data)
136
+ assert lib.grid_offset == (128, 256)
137
+
138
+ def test_json_file_contains_grid_offset_key(self):
139
+ """The written JSON file contains the grid_offset key."""
140
+ from plugins.sprite_animation.models import AnimationLibrary
141
+
142
+ lib = AnimationLibrary(grid_offset=(3, 9))
143
+ with tempfile.TemporaryDirectory() as tmp:
144
+ path = Path(tmp) / "anim.json"
145
+ lib.save(path)
146
+ with open(path) as f:
147
+ raw = json.load(f)
148
+
149
+ assert "grid_offset" in raw
150
+ assert raw["grid_offset"] == [3, 9]