tilemap-editor 4.3.6__tar.gz → 4.3.8__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 (248) hide show
  1. tilemap_editor-4.3.8/CHANGELOG.md +231 -0
  2. {tilemap_editor-4.3.6/src/tilemap_editor.egg-info → tilemap_editor-4.3.8}/PKG-INFO +3 -1
  3. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/pyproject.toml +36 -7
  4. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/editor.py +27 -78
  5. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/layers.py +8 -1
  6. tilemap_editor-4.3.8/src/plugins/sprite_editor/camera.py +97 -0
  7. tilemap_editor-4.3.8/src/plugins/sprite_editor/clipboard.py +74 -0
  8. tilemap_editor-4.3.8/src/plugins/sprite_editor/commands.py +248 -0
  9. tilemap_editor-4.3.8/src/plugins/sprite_editor/document.py +352 -0
  10. tilemap_editor-4.3.8/src/plugins/sprite_editor/editor.py +658 -0
  11. tilemap_editor-4.3.8/src/plugins/sprite_editor/overlays.py +155 -0
  12. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_editor/region_export.py +3 -3
  13. tilemap_editor-4.3.8/src/plugins/sprite_editor/selection.py +99 -0
  14. tilemap_editor-4.3.8/src/plugins/sprite_editor/tools.py +745 -0
  15. tilemap_editor-4.3.8/src/plugins/sprite_editor/viewport.py +179 -0
  16. tilemap_editor-4.3.8/src/run.py +3 -0
  17. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap.py +21 -49
  18. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8/src/tilemap_editor.egg-info}/PKG-INFO +3 -1
  19. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor.egg-info/SOURCES.txt +17 -1
  20. tilemap_editor-4.3.8/src/tilemap_editor.egg-info/requires.txt +4 -0
  21. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/font_manager.py +4 -0
  22. tilemap_editor-4.3.8/src/utils/natural_sort.py +29 -0
  23. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/filemanager.py +4 -3
  24. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/input.py +31 -6
  25. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/tile_grid.py +91 -76
  26. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/menubar.py +36 -3
  27. tilemap_editor-4.3.8/src/widgets/ui/resize_map_dialog.py +223 -0
  28. tilemap_editor-4.3.8/tests/test_map_resize_model.py +50 -0
  29. tilemap_editor-4.3.8/tests/test_natural_sort.py +80 -0
  30. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_serialization_regression.py +19 -5
  31. tilemap_editor-4.3.8/tests/test_sprite_editor_commands.py +271 -0
  32. tilemap_editor-4.3.8/tests/test_sprite_editor_interaction.py +610 -0
  33. tilemap_editor-4.3.8/tests/test_sprite_editor_models.py +380 -0
  34. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_tile_grid_selection.py +1 -1
  35. tilemap_editor-4.3.6/src/plugins/sprite_editor/editor.py +0 -631
  36. tilemap_editor-4.3.6/src/tilemap_editor.egg-info/requires.txt +0 -1
  37. tilemap_editor-4.3.6/src/widgets/spritesheet_grid.py +0 -707
  38. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/LICENSE +0 -0
  39. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/MANIFEST.in +0 -0
  40. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/README.md +0 -0
  41. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  42. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  43. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  44. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  45. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  46. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  47. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  48. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  49. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/arrow-down.svg +0 -0
  50. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/check.svg +0 -0
  51. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/checked.svg +0 -0
  52. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/close.svg +0 -0
  53. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/duplicate.svg +0 -0
  54. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/error.svg +0 -0
  55. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/file.svg +0 -0
  56. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/filedead.svg +0 -0
  57. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/fit.svg +0 -0
  58. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/folder.svg +0 -0
  59. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/grid.svg +0 -0
  60. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/image.svg +0 -0
  61. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/info.svg +0 -0
  62. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/load.svg +0 -0
  63. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/loop.svg +0 -0
  64. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/onion.svg +0 -0
  65. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/pan.svg +0 -0
  66. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/pause.svg +0 -0
  67. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/pencil.svg +0 -0
  68. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/play.svg +0 -0
  69. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/plus.svg +0 -0
  70. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/radio.svg +0 -0
  71. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/reset.svg +0 -0
  72. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/save.svg +0 -0
  73. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/skip-back.svg +0 -0
  74. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/skip-forward.svg +0 -0
  75. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/stop.svg +0 -0
  76. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/tilemap.svg +0 -0
  77. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/tileset.svg +0 -0
  78. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/unchecked.svg +0 -0
  79. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/warning.svg +0 -0
  80. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/zoomin.svg +0 -0
  81. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/assets/icons/zoomout.svg +0 -0
  82. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/setup.cfg +0 -0
  83. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/constants.py +0 -0
  84. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/event_map.py +0 -0
  85. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/main.py +0 -0
  86. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/node_manager.py +0 -0
  87. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/nodes.py +0 -0
  88. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/__init__.py +0 -0
  89. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/__init__.py +0 -0
  90. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/editor.py +0 -0
  91. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/models.py +0 -0
  92. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/protocols.py +0 -0
  93. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/shape_editor.py +0 -0
  94. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/character_collision/standalone.py +0 -0
  95. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/object_tileset_collision/__init__.py +0 -0
  96. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/object_tileset_collision/editor.py +0 -0
  97. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/object_tileset_collision/models.py +0 -0
  98. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/object_tileset_collision/protocols.py +0 -0
  99. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/object_tileset_collision/standalone.py +0 -0
  100. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/__init__.py +0 -0
  101. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/__main__.py +0 -0
  102. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  103. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/editor.py +0 -0
  104. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/frame_picker.py +0 -0
  105. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/models.py +0 -0
  106. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/preview.py +0 -0
  107. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/protocols.py +0 -0
  108. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/runtime_load.py +0 -0
  109. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/standalone.py +0 -0
  110. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/timeline.py +0 -0
  111. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_animation/validation.py +0 -0
  112. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_editor/__init__.py +0 -0
  113. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_editor/dialogs.py +0 -0
  114. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/sprite_editor/standalone.py +0 -0
  115. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/__init__.py +0 -0
  116. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/collision_painter.py +0 -0
  117. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/editor.py +0 -0
  118. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/models.py +0 -0
  119. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/protocols.py +0 -0
  120. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/plugins/tileset_collision/standalone.py +0 -0
  121. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/standalone_automap.py +0 -0
  122. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/standalone_error_console.py +0 -0
  123. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/standalone_filemanager.py +0 -0
  124. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/standalone_image_viewer.py +0 -0
  125. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/__init__.py +0 -0
  126. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/__main__.py +0 -0
  127. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/__init__.py +0 -0
  128. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  129. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  130. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  131. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  132. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  133. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  134. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  135. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  136. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  137. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  138. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/check.svg +0 -0
  139. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  140. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/close.svg +0 -0
  141. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  142. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/error.svg +0 -0
  143. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/file.svg +0 -0
  144. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  145. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  146. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/fold_down_arrow.svg +0 -0
  147. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  148. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/gear.svg +0 -0
  149. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  150. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/image.svg +0 -0
  151. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/info.svg +0 -0
  152. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/load.svg +0 -0
  153. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  154. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/miniobj.svg +0 -0
  155. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/onion.svg +0 -0
  156. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  157. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  158. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  159. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/play.svg +0 -0
  160. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  161. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  162. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  163. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/save.svg +0 -0
  164. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/skip-back.svg +0 -0
  165. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/skip-forward.svg +0 -0
  166. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  167. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  168. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  169. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  170. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/unfold_right_arrow.svg +0 -0
  171. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  172. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  173. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  174. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/cli.py +0 -0
  175. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/main.py +0 -0
  176. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor/settings.py +0 -0
  177. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  178. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  179. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  180. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/ttypes/__init__.py +0 -0
  181. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/ttypes/tilemap.py +0 -0
  182. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/__init__.py +0 -0
  183. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/editor_preference.py +0 -0
  184. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/error_handler.py +0 -0
  185. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/history.py +0 -0
  186. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/icon_manager.py +0 -0
  187. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/icons_cache.py +0 -0
  188. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/log_capture.py +0 -0
  189. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/project_paths.py +0 -0
  190. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/property_suggestions.py +0 -0
  191. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/serialization.py +0 -0
  192. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/standalone.py +0 -0
  193. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/utils/validation.py +0 -0
  194. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/__init__.py +0 -0
  195. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/automap_models.py +0 -0
  196. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/autotile_template.py +0 -0
  197. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/autotiler.py +0 -0
  198. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/layer_selector.py +0 -0
  199. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/map_properties.py +0 -0
  200. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/mapsetup.py +0 -0
  201. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/particle_presets.py +0 -0
  202. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/particle_system.py +0 -0
  203. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/regex_automap_designer.py +0 -0
  204. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/tile_selector.py +0 -0
  205. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/button.py +0 -0
  206. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/checkbox.py +0 -0
  207. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/collision_layer_mask.py +0 -0
  208. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  209. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/confirm_dialog.py +0 -0
  210. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/dialog_base.py +0 -0
  211. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/drag_tracker.py +0 -0
  212. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/draw_utils.py +0 -0
  213. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/fileinput.py +0 -0
  214. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/label.py +0 -0
  215. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/layer_type_dialog.py +0 -0
  216. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/mode_indicator.py +0 -0
  217. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/node_editor.py +0 -0
  218. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/node_selector.py +0 -0
  219. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/notification.py +0 -0
  220. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/particle_config_dialog.py +0 -0
  221. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/property_editor.py +0 -0
  222. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/region_selector.py +0 -0
  223. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/scrollbar.py +0 -0
  224. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/sidebar_container.py +0 -0
  225. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/splitter.py +0 -0
  226. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/status_bar.py +0 -0
  227. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/theme.py +0 -0
  228. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/tileset_type_dialog.py +0 -0
  229. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/toast.py +0 -0
  230. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/tool_manager.py +0 -0
  231. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/toolbar.py +0 -0
  232. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/tooltip.py +0 -0
  233. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/ui/tree_widget.py +0 -0
  234. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/src/widgets/widget_base.py +0 -0
  235. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_animation_library_grid_offset.py +0 -0
  236. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_collision_layer_mask.py +0 -0
  237. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_collision_layer_sidebar.py +0 -0
  238. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_drag_tracker.py +0 -0
  239. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_editor_pan_mode.py +0 -0
  240. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_gid_collision.py +0 -0
  241. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_layers_autotile.py +0 -0
  242. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_project_paths.py +0 -0
  243. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_render_scale.py +0 -0
  244. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_sprite_animation_editor_grid.py +0 -0
  245. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_tile_selector_pick.py +0 -0
  246. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_tilemap_save.py +0 -0
  247. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_timeline_invalidate_cache.py +0 -0
  248. {tilemap_editor-4.3.6 → tilemap_editor-4.3.8}/tests/test_toolbar_tools.py +0 -0
@@ -0,0 +1,231 @@
1
+ # Changelog
2
+
3
+ <!-- towncrier release notes start -->
4
+ # tilemap_editor 4.3.8 (2026-08-04)
5
+
6
+ ## Features
7
+
8
+ - Sprite editor: two-row grouped toolbar (no more clipped buttons at the default window size), natural filename sorting on multi-sheet loads, and a Stack V/H toggle for vertical or horizontal sheet stacking. (sprite-editor-toolbar-sort)
9
+ - Rewrote the sprite editor around a command stack with single-canvas undo memory: shared clipboard with relative-tile pasting that survives scale/grid changes, drag-move and rubber-band selection that can expand the canvas, object-selection undo restore, and a pure camera with cursor-anchored zoom. (sprite-editor-v2)
10
+
11
+ ## Bug Fixes
12
+
13
+ - Fixed sprite editor paste landing in wrong cells after a scale or grid-size change (clipboard now stores relative tile offsets), paste/cut double-clipboard split-brain, paste preview lacking pixel ghost, and moves/pastes past the canvas edge now expanding the canvas. (sprite-editor-paste-fixes)
14
+ - Fixed sprite editor theming and camera gestures: the canvas, header bar, grid lines, and overlays now use theme colors/fonts instead of hardcoded dark values (canvas no longer stays black on light themes), the canvas header no longer covers the sheet's top rows, and mouse wheel zoom/pan work again with the same 30px/1.12x behavior as the old editor. (sprite-editor-theme-wheel)
15
+
16
+
17
+ ## [4.3.7] - 2026-07-30
18
+
19
+ ### Bug Fixes
20
+
21
+ - Replaced buggy auto-resize system with explicit offset + size model for widget positioning
22
+
23
+ ## [4.3.6] - 2026-07-26
24
+
25
+ ### Features
26
+
27
+ - Added tileset properties completion
28
+ - Updated README with credits and Python version info
29
+
30
+ ### Bug Fixes
31
+
32
+ - Fixed UX bugs and node prescale problem
33
+
34
+ ## [4.3.4] - 2026-07-24
35
+
36
+ ### Features
37
+
38
+ - Added y-sort option for tile rendering order
39
+
40
+ ### Changed
41
+
42
+ - Restructured codebase with enhanced UI components and preference persistence
43
+ - Improved shape editor UX with theme integration and viewport centering
44
+
45
+ ## [4.3.1] - 2026-07-17
46
+
47
+ ### Bug Fixes
48
+
49
+ - Fixed create folder blocker in file manager
50
+ - Adjusted input field inner size
51
+
52
+ ## [4.3.0] - 2026-07-16
53
+
54
+ ### Changed
55
+
56
+ - Refactored toolbar and tool system with ToolManager/ToolKind central state
57
+ - Replaced editor boolean flags with centralized ToolManager mutual exclusion
58
+ - CLI `--theme` support
59
+
60
+ ### Added
61
+
62
+ - Icon-only compact toolbar (28px) with separator bars and tooltips
63
+
64
+ ### Bug Fixes
65
+
66
+ - Fixed node and object render_scale bugs (selection rect, move offset, hit-test)
67
+
68
+ ## [4.2.0] - 2026-07-15
69
+
70
+ ### Features
71
+
72
+ - Separated autotile group from layer tile data
73
+ - Added global ID system for tiles
74
+ - Re-added autotile early-out optimization
75
+ - Added auto-detect group from variant
76
+
77
+ ## [4.1.0] - 2026-07-13
78
+
79
+ ### Features
80
+
81
+ - Added .tmx file open/save support with TMX-to-dict converter
82
+
83
+ ### Bug Fixes
84
+
85
+ - Fixed alignment of tmx converter with parser fixes (mask, props, gid count)
86
+
87
+ ### Misc
88
+
89
+ - Formatted code and applied unsafe fixes with ruff
90
+
91
+ ## [4.0.0] - 2026-07-11
92
+
93
+ ### Changed
94
+
95
+ - Refactored widget theme system with dynamic COLORS proxy, SHAPE, FONTS, SPACING
96
+ - Applied theme from settings.json with custom theme loading support
97
+ - Added theme-aware WidgetBase with box model (padding, border, content_rect)
98
+
99
+ ### Added
100
+
101
+ - CLI `--theme` argument accepting name or path to .json file
102
+
103
+ ### Bug Fixes
104
+
105
+ - Fixed tile grid issues and serialization
106
+ - Improved node ui/ux with ctrl/cmd+shift+n toggle for node manager
107
+ - Improved particle rendering
108
+ - Temporarily disabled autotile propagation on collision paint
109
+
110
+ ## [3.3.8] - 2026-07-01
111
+
112
+ ### Bug Fixes
113
+
114
+ - Replaced smoothscale with scale for broader compatibility
115
+ - Fixed fallback to scale when smoothscale fails on non-32bit surfaces
116
+ - Replaced unicode characters with SVG icons for frame nav and onion skin
117
+
118
+ ## [3.3.4] - 2026-06-17
119
+
120
+ ### Features
121
+
122
+ - Enhanced sprite editor with cut/copy/paste functionality
123
+ - Added checkbox widget for UI controls
124
+
125
+ ### Documentation
126
+
127
+ - Added documentation for tilemap-editor (setup, project structure, architecture, usage)
128
+
129
+ ## [3.3.3] - 2026-06-10
130
+
131
+ ### Features
132
+
133
+ - Added particle system with 66 presets across 11 categories
134
+ - Added particle system editor integration with config dialog
135
+ - Added particle preview in TileGrid
136
+
137
+ ### Bug Fixes
138
+
139
+ - Fixed propagation of negative grid offsets
140
+ - Fixed zero animation frame_stride guard
141
+ - Fixed preset dropdown refresh on node switch
142
+ - Fixed particle preview reset on config save
143
+
144
+ ### Misc
145
+
146
+ - Added 'synchronize' type to PR agent workflow triggers
147
+
148
+ ## [3.2.10] - 2026-06-07
149
+
150
+ ### Bug Fixes
151
+
152
+ - Fixed tab click offset ignoring scroll_x
153
+
154
+ ### Added
155
+
156
+ - Hover-only arrow buttons for tab navigation
157
+
158
+ ## [3.2.9] - 2026-06-07
159
+
160
+ ### Bug Fixes
161
+
162
+ - Fixed stride normalization — removed % stride normalization, auto-compute stride
163
+ - Fixed dialog UI overlap
164
+
165
+ ## [3.2.8] - 2026-06-07
166
+
167
+ ### Features
168
+
169
+ - Added node system with NodeManager, NodeSelector, NodeEditor, and TileGrid overlay
170
+ - Added lenient tileset loading with warn dialog instead of reject on size mismatch
171
+
172
+ ### Bug Fixes
173
+
174
+ - Fixed layer rename text not visible during editing
175
+ - Fixed object layer position offset from render_scale
176
+ - Fixed capsule move icon and animation preview grid_offset
177
+ - Fixed layer rename Cmd+Backspace interaction
178
+
179
+ ## [3.2.4] - 2026-06-04
180
+
181
+ ### Features
182
+
183
+ - Added copy/paste collision shapes with toast feedback and painted tiles focus mode
184
+ - Added sprite editor integration with flip ghosting fix, tileset zoom, autotiler import fix
185
+ - Added auto-expand spritesheet canvas on paste overflow
186
+ - Added editable name field in character collision editor
187
+ - Added renaming support in character collision
188
+ - Added animation library loading and tool state management
189
+ - Added auto-propagation of collision shapes to auto-tile variant groups on save
190
+
191
+ ### Bug Fixes
192
+
193
+ - Fixed animation rename shortcuts, path resolution, file input overflow, and dual-focus metadata fields
194
+ - Fixed sprite editor multi-row paste flattening and missing tile-size arg
195
+ - Fixed dynamic grid span
196
+ - Fixed L shortcut conflict with name input
197
+
198
+ ### Misc
199
+
200
+ - Added unit tests
201
+
202
+ ## [3.1.6] - 2026-05-21
203
+
204
+ ### Bug Fixes
205
+
206
+ - Fixed NameError in save_map
207
+ - Fixed asymmetry in load path resolution
208
+ - Fixed path resolution in init
209
+
210
+ ### Added
211
+
212
+ - Added render_scale to map properties with dialog UI and TileGrid support
213
+ - Added auto-creation of data directory on init
214
+
215
+ ## [3.1.0] - 2026-05-18
216
+
217
+ ### Features
218
+
219
+ - Added Godot-inspired physics layer (radio) + mask (checkbox) bit selector (16 layers)
220
+ - Added collision layer sidebar overlay with toggle/close/dim
221
+ - Added object tileset collision editor with region support
222
+ - Added reusable text input system with cursor, selection, and shortcuts
223
+ - Added project initialization, asset management, and data structure improvements
224
+ - Added theme support
225
+ - Added collision mask support
226
+ - Implemented event priority system and modal overlays in autotiler
227
+
228
+ ### Changed
229
+
230
+ - Improved file manager path handling and directory initialization
231
+ - Improved tileset collision help panel and macOS HiDPI support
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 4.3.6
3
+ Version: 4.3.8
4
4
  Summary: Pygame tilemap editor with collision, animation, sprite & particle tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -12,6 +12,8 @@ Requires-Python: >=3.11
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: pygame-ce>=2.5
15
+ Provides-Extra: dev
16
+ Requires-Dist: towncrier; extra == "dev"
15
17
  Dynamic: license-file
16
18
 
17
19
  # tilemap-editor
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-editor"
7
- version = "4.3.6"
7
+ version = "4.3.8"
8
8
  description = "Pygame tilemap editor with collision, animation, sprite & particle tools"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -24,6 +24,41 @@ classifiers = [
24
24
  tilemap-editor = "tilemap_editor.cli:main"
25
25
  tilemap-anim-editor = "plugins.sprite_animation.standalone:main"
26
26
 
27
+ [project.optional-dependencies]
28
+ dev = ["towncrier"]
29
+
30
+ [tool.towncrier]
31
+ package = "tilemap_editor"
32
+ directory = "changes"
33
+ filename = "CHANGELOG.md"
34
+ start_string = "<!-- towncrier release notes start -->"
35
+ underlines = ["-", "~", "^"]
36
+
37
+ [[tool.towncrier.type]]
38
+ directory = "feature"
39
+ name = "Features"
40
+ showcontent = true
41
+
42
+ [[tool.towncrier.type]]
43
+ directory = "bugfix"
44
+ name = "Bug Fixes"
45
+ showcontent = true
46
+
47
+ [[tool.towncrier.type]]
48
+ directory = "doc"
49
+ name = "Documentation"
50
+ showcontent = true
51
+
52
+ [[tool.towncrier.type]]
53
+ directory = "removal"
54
+ name = "Deprecations and Removals"
55
+ showcontent = true
56
+
57
+ [[tool.towncrier.type]]
58
+ directory = "misc"
59
+ name = "Misc"
60
+ showcontent = true
61
+
27
62
  [tool.setuptools]
28
63
  package-dir = {"" = "src"}
29
64
  include-package-data = true
@@ -62,9 +97,3 @@ namespaces = true
62
97
 
63
98
  [tool.setuptools.exclude-package-data]
64
99
  "*" = ["*.spec", "*.sh"]
65
-
66
- # Keep data-files for backward compatibility (one release cycle)
67
- [tool.setuptools.data-files]
68
- "share/tilemap_editor/assets/icons" = ["assets/icons/*.svg"]
69
- "share/tilemap_editor/assets/fonts/noto" = ["assets/fonts/noto/*.ttf"]
70
- "share/tilemap_editor/assets/fonts/jetbrain-fonts" = ["assets/fonts/jetbrain-fonts/*.ttf"]
@@ -39,6 +39,7 @@ from widgets.ui.node_selector import NodeSelector
39
39
  from widgets.ui.notification import NotificationManager
40
40
  from widgets.ui.particle_config_dialog import ParticleConfigDialog
41
41
  from widgets.ui.property_editor import PropertyEditor
42
+ from widgets.ui.resize_map_dialog import ResizeMapDialog
42
43
  from widgets.ui.sidebar_container import SidebarContainer, ToolbarAction
43
44
  from widgets.ui.theme import COLORS, THEMES, get_theme_manager, set_theme
44
45
  from widgets.ui.tileset_type_dialog import TilesetTypeDialog
@@ -206,8 +207,7 @@ class Editor:
206
207
  self.tile_grid_widget: TileGrid | None = None
207
208
 
208
209
  self.left_panel_visible = False
209
- self.animation_panel: SpriteAnimationEditor | None = None
210
- self._animation_panel_surface: pygame.Surface | None = None
210
+ self.left_panel_w = 300
211
211
 
212
212
  self.autotiler = AutotileRuleDesigner(self, 100, 100)
213
213
  self.regex_automap_designer = RegexAutomapDesigner(self, 150, 100)
@@ -240,6 +240,8 @@ class Editor:
240
240
  self.tileset_type_dialog = TilesetTypeDialog(editor_rect)
241
241
  self.confirm_dialog = ConfirmDialog(editor_rect)
242
242
  self.layer_type_dialog = LayerTypeDialog(editor_rect)
243
+ self.resize_map_dialog = ResizeMapDialog(editor_rect)
244
+ self.resize_map_dialog.editor = self
243
245
 
244
246
  self.menubar = MenuBar(self, self.width, 30)
245
247
  self.toolbar = Toolbar(self, 0, 30, self.width, 35)
@@ -622,13 +624,6 @@ class Editor:
622
624
 
623
625
  self._update_side_panel_layout()
624
626
 
625
- if self.left_panel_visible and self.animation_panel:
626
- panel_rect = Rect(0, menu_h + toolbar_h, self.left_panel_w, height - (menu_h + toolbar_h))
627
- if hasattr(self.animation_panel, "rect"):
628
- self.animation_panel.rect = panel_rect
629
- if hasattr(self.animation_panel, "_relayout"):
630
- self.animation_panel._relayout()
631
-
632
627
  rect_full = Rect(0, 0, width, height)
633
628
 
634
629
  if hasattr(self, "tileset_type_dialog") and self.tileset_type_dialog:
@@ -663,6 +658,12 @@ class Editor:
663
658
  return
664
659
  self.map_properties_dialog.open()
665
660
 
661
+ def open_resize_map_dialog(self):
662
+ if self.resize_map_dialog is None:
663
+ logger.warning({"msg": "resize_map_dialog is not initialized"})
664
+ return
665
+ self.resize_map_dialog.open()
666
+
666
667
  def toggle_autotiler(self):
667
668
  if self.autotiler.visible:
668
669
  self.autotiler.hide()
@@ -675,47 +676,6 @@ class Editor:
675
676
  else:
676
677
  self.regex_automap_designer.show()
677
678
 
678
- def toggle_animation_panel(self):
679
- """Toggle the dockable animation panel visibility (Cmd/Ctrl+B)."""
680
- if not self.left_panel_visible:
681
- if self.animation_panel is None:
682
- self._init_animation_panel()
683
- if self.animation_panel is not None:
684
- self.left_panel_visible = True
685
- else:
686
- self.left_panel_visible = False
687
- self.handle_resize(self.width, self.height)
688
-
689
- def _init_animation_panel(self):
690
- """Initialize the animation panel without loading any tileset."""
691
- from plugins.sprite_animation.editor import SpriteAnimationEditor
692
-
693
- try:
694
-
695
- class _PanelConsumer:
696
- editor_instance = self
697
-
698
- def on_animation_saved(self, name: str, data: dict) -> None:
699
- self.editor_instance.notifications.notify(f"Animation saved: {name}")
700
-
701
- def on_animation_deleted(self, name: str) -> None:
702
- self.editor_instance.notifications.notify(f"Animation deleted: {name}")
703
-
704
- consumer = _PanelConsumer()
705
-
706
- panel_rect = Rect(0, 65, self.left_panel_w, self.height - 65)
707
-
708
- self.animation_panel = SpriteAnimationEditor(
709
- panel_rect,
710
- surface=None,
711
- tile_size=(32, 32),
712
- consumer=consumer,
713
- )
714
- self.animation_panel._data_root = self.data_root
715
- except Exception as e:
716
- error_handler.capture(e, context="init_animation_panel")
717
- self.notifications.notify(f"Failed to init animation panel: {e}")
718
-
719
679
  def undo(self):
720
680
  self.tilemap.undo()
721
681
  if self.tile_grid_widget:
@@ -730,6 +690,12 @@ class Editor:
730
690
  if self.tile_grid_widget:
731
691
  self.tile_grid_widget.show_grid = not self.tile_grid_widget.show_grid
732
692
 
693
+ def toggle_map_boundary(self):
694
+ if self.tile_grid_widget:
695
+ self.tile_grid_widget.show_map_boundary = (
696
+ not self.tile_grid_widget.show_map_boundary
697
+ )
698
+
733
699
  def cycle_theme(self):
734
700
  """Cycle through available themes."""
735
701
  theme_names = list(THEMES.keys())
@@ -1145,6 +1111,10 @@ class Editor:
1145
1111
  self.layer_type_dialog.handle_event(event)
1146
1112
  continue
1147
1113
 
1114
+ if self.resize_map_dialog and self.resize_map_dialog.active:
1115
+ self.resize_map_dialog.handle_event(event)
1116
+ continue
1117
+
1148
1118
  if self.map_setup_widget and self.map_setup_widget.visible:
1149
1119
  if self.map_setup_widget.handle_event(event):
1150
1120
  continue
@@ -1242,7 +1212,7 @@ class Editor:
1242
1212
  self.cycle_theme()
1243
1213
  continue
1244
1214
  if event.key == pygame.K_b and (ctrl_held or meta_held):
1245
- self.toggle_animation_panel()
1215
+ self.toggle_map_boundary()
1246
1216
  continue
1247
1217
  if pygame.K_1 <= event.key <= pygame.K_9:
1248
1218
  if not (self.node_editor and self.node_editor.visible and self.node_editor.editing_field):
@@ -1259,11 +1229,6 @@ class Editor:
1259
1229
  if self.toolbar and self.toolbar.handle_event(event):
1260
1230
  continue
1261
1231
 
1262
- if self.left_panel_visible and self.animation_panel:
1263
- if hasattr(self.animation_panel, "handle_event"):
1264
- if self.animation_panel.handle_event(event):
1265
- continue
1266
-
1267
1232
  if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
1268
1233
  mx, my = event.pos
1269
1234
  edge_x = self.width - self._effective_selector_w
@@ -1310,10 +1275,6 @@ class Editor:
1310
1275
  if self.tile_grid_widget:
1311
1276
  self.tile_grid_widget.update()
1312
1277
 
1313
- if self.left_panel_visible and self.animation_panel:
1314
- if hasattr(self.animation_panel, "update"):
1315
- self.animation_panel.update()
1316
-
1317
1278
  self.screen.fill(COLORS.bg)
1318
1279
  self.tooltip.hide()
1319
1280
 
@@ -1341,20 +1302,6 @@ class Editor:
1341
1302
  self.screen.blit(overlay, (0, 0))
1342
1303
  self.regex_automap_designer.draw(self.screen)
1343
1304
 
1344
- if self.left_panel_visible and self.animation_panel:
1345
- panel_surf = pygame.Surface((self.left_panel_w, self.height), pygame.SRCALPHA)
1346
- panel_surf.fill((*COLORS.panel_alt, 255))
1347
- self.screen.blit(panel_surf, (0, 65))
1348
-
1349
- pygame.draw.rect(
1350
- self.screen,
1351
- COLORS.border,
1352
- Rect(0, 65, self.left_panel_w, self.height - 65),
1353
- 1,
1354
- )
1355
- if hasattr(self.animation_panel, "draw"):
1356
- self.animation_panel.draw(self.screen)
1357
-
1358
1305
  self.notifications.draw(self.screen)
1359
1306
 
1360
1307
  if self.map_setup_widget and self.map_setup_widget.visible:
@@ -1373,16 +1320,18 @@ class Editor:
1373
1320
  overlay.fill((0, 0, 0, 150))
1374
1321
  self.screen.blit(overlay, (0, 0))
1375
1322
  self.tileset_type_dialog.draw(self.screen)
1376
- if self.confirm_dialog.active:
1323
+ if self.resize_map_dialog and self.resize_map_dialog.active:
1324
+ self.resize_map_dialog.draw(self.screen)
1325
+ if self.layer_type_dialog.active:
1377
1326
  overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
1378
1327
  overlay.fill((0, 0, 0, 150))
1379
1328
  self.screen.blit(overlay, (0, 0))
1380
- self.confirm_dialog.draw(self.screen)
1381
- if self.layer_type_dialog.active:
1329
+ self.layer_type_dialog.draw(self.screen)
1330
+ if self.confirm_dialog.active:
1382
1331
  overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
1383
1332
  overlay.fill((0, 0, 0, 150))
1384
1333
  self.screen.blit(overlay, (0, 0))
1385
- self.layer_type_dialog.draw(self.screen)
1334
+ self.confirm_dialog.draw(self.screen)
1386
1335
 
1387
1336
  if self.loading_state["active"]:
1388
1337
  overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
@@ -217,6 +217,7 @@ class Layer:
217
217
  start_pos: tuple[int, int],
218
218
  new_tile_data: TypeTile,
219
219
  map_size: tuple[int, int],
220
+ offset: tuple[int, int] = (0, 0),
220
221
  ) -> None:
221
222
  """Replace contiguous tiles of the same type starting from start_pos."""
222
223
  if self.locked or self.layer_type != "tile":
@@ -238,7 +239,13 @@ class Layer:
238
239
  while queue:
239
240
  curr = queue.pop(0)
240
241
 
241
- if curr[0] < 0 or curr[0] >= map_size[0] or curr[1] < 0 or curr[1] >= map_size[1]:
242
+ ox, oy = offset
243
+ if (
244
+ curr[0] < ox
245
+ or curr[0] >= ox + map_size[0]
246
+ or curr[1] < oy
247
+ or curr[1] >= oy + map_size[1]
248
+ ):
242
249
  continue
243
250
 
244
251
  curr_tile = self.tiles.get(curr)
@@ -0,0 +1,97 @@
1
+ """Pure camera math — world (document) <-> screen transforms.
2
+
3
+ No pygame imports: this module is fully usable and testable headlessly.
4
+ Holds viewport origin and scroll as plain floats; the viewport provides
5
+ the pygame-side rect/bilt machinery.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ MIN_ZOOM = 0.1
11
+ MAX_ZOOM = 16.0
12
+
13
+
14
+ def _clamp_zoom(value: float) -> float:
15
+ return max(MIN_ZOOM, min(MAX_ZOOM, value))
16
+
17
+
18
+ class Camera:
19
+ """One monotonic linear transform between document and screen space.
20
+
21
+ screen = (local - origin) * zoom + viewport_topleft + scroll
22
+ local = (screen - viewport_topleft - scroll) / zoom + origin
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ viewport_x: float = 0.0,
28
+ viewport_y: float = 0.0,
29
+ zoom: float = 1.0,
30
+ scroll_x: float = 0.0,
31
+ scroll_y: float = 0.0,
32
+ ):
33
+ self.viewport_x = float(viewport_x)
34
+ self.viewport_y = float(viewport_y)
35
+ self._zoom = _clamp_zoom(float(zoom))
36
+ self.scroll_x = float(scroll_x)
37
+ self.scroll_y = float(scroll_y)
38
+
39
+ @property
40
+ def zoom(self) -> float:
41
+ return self._zoom
42
+
43
+ @zoom.setter
44
+ def zoom(self, value: float) -> None:
45
+ self._zoom = _clamp_zoom(float(value))
46
+
47
+ def world_to_screen(self, x: float, y: float) -> tuple[float, float]:
48
+ return (
49
+ self.viewport_x + self.scroll_x + x * self._zoom,
50
+ self.viewport_y + self.scroll_y + y * self._zoom,
51
+ )
52
+
53
+ def screen_to_world(self, sx: float, sy: float) -> tuple[float, float]:
54
+ if self._zoom <= 0:
55
+ return (0.0, 0.0)
56
+ return (
57
+ (sx - self.viewport_x - self.scroll_x) / self._zoom,
58
+ (sy - self.viewport_y - self.scroll_y) / self._zoom,
59
+ )
60
+
61
+ def fit(self, world_size: tuple[float, float], viewport_size: tuple[float, float]) -> None:
62
+ """Zoom so the whole document fits the viewport, centered."""
63
+ ww, wh = world_size
64
+ vw, vh = viewport_size
65
+ if ww <= 0 or wh <= 0 or vw <= 0 or vh <= 0:
66
+ self.reset()
67
+ return
68
+ self._zoom = _clamp_zoom(min(vw / ww, vh / wh))
69
+ self.scroll_x = (vw - ww * self._zoom) / 2.0
70
+ self.scroll_y = (vh - wh * self._zoom) / 2.0
71
+
72
+ def reset(self) -> None:
73
+ """100% zoom, document origin at the viewport top-left."""
74
+ self._zoom = 1.0
75
+ self.scroll_x = 0.0
76
+ self.scroll_y = 0.0
77
+
78
+ def zoom_at(self, screen_point: tuple[float, float], factor: float) -> None:
79
+ """Zoom by factor while keeping the world point under the cursor fixed."""
80
+ sx, sy = screen_point
81
+ wx, wy = self.screen_to_world(sx, sy)
82
+ new_zoom = _clamp_zoom(self._zoom * factor)
83
+ if abs(new_zoom - self._zoom) < 1e-9:
84
+ return
85
+ self._zoom = new_zoom
86
+ self.scroll_x = sx - self.viewport_x - wx * self._zoom
87
+ self.scroll_y = sy - self.viewport_y - wy * self._zoom
88
+
89
+ def pan(self, dx: float, dy: float) -> None:
90
+ """Scroll by a screen-space delta (content follows the cursor)."""
91
+ self.scroll_x += float(dx)
92
+ self.scroll_y += float(dy)
93
+
94
+ def world_to_screen_rect(self, x: float, y: float, w: float, h: float) -> tuple[float, float, float, float]:
95
+ """Screen-space rect for a world-space rect (floats)."""
96
+ sx, sy = self.world_to_screen(x, y)
97
+ return (sx, sy, w * self._zoom, h * self._zoom)