tilemap-editor 3.1.7__tar.gz → 3.2.0__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 (186) hide show
  1. {tilemap_editor-3.1.7/src/tilemap_editor.egg-info → tilemap_editor-3.2.0}/PKG-INFO +1 -1
  2. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/pyproject.toml +1 -1
  3. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/editor.py +24 -0
  4. tilemap_editor-3.2.0/src/plugins/sprite_editor/__init__.py +3 -0
  5. tilemap_editor-3.2.0/src/plugins/sprite_editor/editor.py +323 -0
  6. tilemap_editor-3.2.0/src/plugins/sprite_editor/standalone.py +118 -0
  7. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
  8. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor.egg-info/SOURCES.txt +4 -0
  9. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/autotiler.py +2 -0
  10. tilemap_editor-3.2.0/src/widgets/spritesheet_grid.py +580 -0
  11. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/tile_selector.py +50 -14
  12. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/menubar.py +1 -0
  13. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/LICENSE +0 -0
  14. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/MANIFEST.in +0 -0
  15. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/README.md +0 -0
  16. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  17. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  18. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  19. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  20. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  21. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  22. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  23. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  24. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/arrow-down.svg +0 -0
  25. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/check.svg +0 -0
  26. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/checked.svg +0 -0
  27. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/close.svg +0 -0
  28. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/duplicate.svg +0 -0
  29. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/error.svg +0 -0
  30. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/file.svg +0 -0
  31. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/filedead.svg +0 -0
  32. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/fit.svg +0 -0
  33. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/folder.svg +0 -0
  34. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/grid.svg +0 -0
  35. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/image.svg +0 -0
  36. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/info.svg +0 -0
  37. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/load.svg +0 -0
  38. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/loop.svg +0 -0
  39. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/pan.svg +0 -0
  40. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/pause.svg +0 -0
  41. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/pencil.svg +0 -0
  42. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/play.svg +0 -0
  43. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/plus.svg +0 -0
  44. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/radio.svg +0 -0
  45. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/reset.svg +0 -0
  46. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/save.svg +0 -0
  47. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/stop.svg +0 -0
  48. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/tilemap.svg +0 -0
  49. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/tileset.svg +0 -0
  50. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/unchecked.svg +0 -0
  51. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/warning.svg +0 -0
  52. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/zoomin.svg +0 -0
  53. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/assets/icons/zoomout.svg +0 -0
  54. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/setup.cfg +0 -0
  55. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/configs/themes.py +0 -0
  56. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/constants.py +0 -0
  57. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/event_map.py +0 -0
  58. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/layers.py +0 -0
  59. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/main.py +0 -0
  60. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/__init__.py +0 -0
  61. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/__init__.py +0 -0
  62. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/editor.py +0 -0
  63. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/models.py +0 -0
  64. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/protocols.py +0 -0
  65. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/shape_editor.py +0 -0
  66. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/character_collision/standalone.py +0 -0
  67. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/object_tileset_collision/__init__.py +0 -0
  68. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/object_tileset_collision/editor.py +0 -0
  69. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/object_tileset_collision/models.py +0 -0
  70. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/object_tileset_collision/protocols.py +0 -0
  71. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/object_tileset_collision/standalone.py +0 -0
  72. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/__init__.py +0 -0
  73. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/__main__.py +0 -0
  74. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  75. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/editor.py +0 -0
  76. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/frame_picker.py +0 -0
  77. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/models.py +0 -0
  78. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/preview.py +0 -0
  79. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/protocols.py +0 -0
  80. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/runtime_load.py +0 -0
  81. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/standalone.py +0 -0
  82. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/timeline.py +0 -0
  83. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/sprite_animation/validation.py +0 -0
  84. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/__init__.py +0 -0
  85. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/collision_painter.py +0 -0
  86. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/editor.py +0 -0
  87. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/models.py +0 -0
  88. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/protocols.py +0 -0
  89. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/plugins/tileset_collision/standalone.py +0 -0
  90. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/standalone_automap.py +0 -0
  91. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/standalone_error_console.py +0 -0
  92. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/standalone_filemanager.py +0 -0
  93. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/standalone_image_viewer.py +0 -0
  94. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap.py +0 -0
  95. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/__init__.py +0 -0
  96. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/__main__.py +0 -0
  97. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/__init__.py +0 -0
  98. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  99. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  100. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  101. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  102. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  103. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  104. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  105. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  106. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  107. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  108. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/check.svg +0 -0
  109. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  110. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/close.svg +0 -0
  111. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  112. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/error.svg +0 -0
  113. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/file.svg +0 -0
  114. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  115. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  116. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  117. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  118. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/image.svg +0 -0
  119. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/info.svg +0 -0
  120. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/load.svg +0 -0
  121. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  122. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  123. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  124. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  125. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/play.svg +0 -0
  126. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  127. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  128. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  129. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/save.svg +0 -0
  130. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  131. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  132. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  133. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  134. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  135. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  136. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  137. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/cli.py +0 -0
  138. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/main.py +0 -0
  139. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor/settings.py +0 -0
  140. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  141. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  142. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor.egg-info/requires.txt +0 -0
  143. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  144. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/ttypes/__init__.py +0 -0
  145. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/ttypes/tilemap.py +0 -0
  146. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/__init__.py +0 -0
  147. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/editor_preference.py +0 -0
  148. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/error_handler.py +0 -0
  149. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/font_manager.py +0 -0
  150. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/history.py +0 -0
  151. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/icon_manager.py +0 -0
  152. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/icons_cache.py +0 -0
  153. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/log_capture.py +0 -0
  154. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/project_paths.py +0 -0
  155. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/serialization.py +0 -0
  156. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/standalone.py +0 -0
  157. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/utils/validation.py +0 -0
  158. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/__init__.py +0 -0
  159. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/automap_models.py +0 -0
  160. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/autotile_template.py +0 -0
  161. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/filemanager.py +0 -0
  162. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/input.py +0 -0
  163. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/layer_selector.py +0 -0
  164. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/map_properties.py +0 -0
  165. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/mapsetup.py +0 -0
  166. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/regex_automap_designer.py +0 -0
  167. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/tile_grid.py +0 -0
  168. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/collision_layer_mask.py +0 -0
  169. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  170. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/draw_utils.py +0 -0
  171. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/fileinput.py +0 -0
  172. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/layer_type_dialog.py +0 -0
  173. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/mode_indicator.py +0 -0
  174. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/notification.py +0 -0
  175. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/property_editor.py +0 -0
  176. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/region_selector.py +0 -0
  177. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/status_bar.py +0 -0
  178. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/theme.py +0 -0
  179. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/tileset_type_dialog.py +0 -0
  180. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/toolbar.py +0 -0
  181. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/src/widgets/ui/tooltip.py +0 -0
  182. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/tests/test_collision_layer_mask.py +0 -0
  183. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/tests/test_collision_layer_sidebar.py +0 -0
  184. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/tests/test_project_paths.py +0 -0
  185. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/tests/test_render_scale.py +0 -0
  186. {tilemap_editor-3.1.7 → tilemap_editor-3.2.0}/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.1.7
3
+ Version: 3.2.0
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.1.7"
7
+ version = "3.2.0"
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"
@@ -40,6 +40,7 @@ from utils import error_handler, error_context
40
40
 
41
41
  if TYPE_CHECKING:
42
42
  from plugins.sprite_animation import SpriteAnimationEditor
43
+ from plugins.sprite_editor import SpriteEditor
43
44
 
44
45
 
45
46
  def setup_error_logging():
@@ -710,6 +711,29 @@ class Editor:
710
711
  except Exception as e:
711
712
  error_handler.capture(e, context="launch_animation_editor")
712
713
 
714
+ def launch_sprite_editor(self):
715
+ """Launch the sprite editor in a new window."""
716
+ self.open_file_manager(
717
+ on_select=self._launch_sprite_editor_with_image,
718
+ initial_dir=self.data_root,
719
+ allowed_exts=[".png", ".jpg", ".jpeg"],
720
+ mode="open",
721
+ )
722
+
723
+ def _launch_sprite_editor_with_image(self, path: Path):
724
+ """Launch sprite editor subprocess with selected image."""
725
+ try:
726
+ args = [str(path), "--data-root", str(self.data_root)]
727
+ process = launch_standalone(
728
+ "plugins.sprite_editor.standalone",
729
+ args,
730
+ cwd=self.base_path,
731
+ text=True,
732
+ )
733
+ self.child_processes.append(process)
734
+ except Exception as e:
735
+ error_handler.capture(e, context="launch_sprite_editor")
736
+
713
737
  def launch_collision_editor(self, tileset_type: str = "tile"):
714
738
  """Launch the collision editor in a new window.
715
739
 
@@ -0,0 +1,3 @@
1
+ from .editor import SpriteEditor
2
+
3
+ __all__ = ["SpriteEditor"]
@@ -0,0 +1,323 @@
1
+ """
2
+ SpriteEditor — standalone widget wrapping SpritesheetGrid with editing toolbar.
3
+
4
+ Toolbar:
5
+ [Flip X] [Flip Y] [Copy] [Paste] [Undo] [Redo] [Scale...] [Save PNG]
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from pathlib import Path
11
+ from typing import Dict, Optional
12
+
13
+ import pygame
14
+ from pygame import Rect, Surface
15
+
16
+ from widgets.spritesheet_grid import SpritesheetGrid
17
+ from widgets.ui.theme import COLORS
18
+ from widgets.ui.draw_utils import draw_panel, draw_button
19
+ from utils.font_manager import font_manager, FontWeight
20
+ from utils.icon_manager import icon_manager
21
+
22
+
23
+ TOOLBAR_H = 42
24
+ STATUS_H = 22
25
+ BTN_W = 64
26
+ BTN_H = 28
27
+
28
+ # Map toolbar labels to icon_manager keys (None = text only)
29
+ _BUTTON_ICONS: dict[str, str | None] = {
30
+ "Flip X": None,
31
+ "Flip Y": None,
32
+ "Copy": "duplicate",
33
+ "Paste": None,
34
+ "Undo": None,
35
+ "Redo": None,
36
+ "Scale": None,
37
+ "Save": "save",
38
+ }
39
+
40
+
41
+ class SpriteEditor:
42
+ def __init__(
43
+ self,
44
+ rect: Rect,
45
+ surface: Surface,
46
+ tile_size: tuple[int, int],
47
+ image_path: Optional[Path] = None,
48
+ data_root: Optional[Path] = None,
49
+ ):
50
+ self.rect = rect
51
+ self.image_path = image_path
52
+ self._data_root = data_root or (image_path.parent if image_path else Path.cwd())
53
+
54
+ # Grid
55
+ grid_rect = Rect(rect.x, rect.y + TOOLBAR_H, rect.w, rect.h - TOOLBAR_H - STATUS_H)
56
+ self.grid = SpritesheetGrid(grid_rect, surface, tile_size)
57
+
58
+ # Clipboard for copy/paste
59
+ self._clipboard: Dict[int, Surface] = {}
60
+ self._paste_mode: bool = False
61
+
62
+ # Scale dialog state
63
+ self._scale_active: bool = False
64
+ self._scale_text: str = "2.0"
65
+ self._scale_error: Optional[str] = None
66
+
67
+ # Save path — never auto-overwrite original
68
+ self._save_path: Optional[Path] = None
69
+
70
+ # File manager modal
71
+ self._file_manager: Optional[object] = None
72
+
73
+ # Toolbar button rects
74
+ self._btn_rects: dict[str, Rect] = {}
75
+ self._layout_toolbar()
76
+
77
+ self._font = font_manager.get_font("monospace", 13, FontWeight.BOLD)
78
+ self._font_sm = font_manager.get_font("monospace", 11, FontWeight.BOLD)
79
+
80
+ def _layout_toolbar(self) -> None:
81
+ ty = self.rect.y + (TOOLBAR_H - BTN_H) // 2
82
+ gap = 6
83
+ x = self.rect.x + gap
84
+ labels = ["Flip X", "Flip Y", "Copy", "Paste", "Undo", "Redo", "Scale", "Save"]
85
+ for lbl in labels:
86
+ self._btn_rects[lbl] = Rect(x, ty, BTN_W, BTN_H)
87
+ x += BTN_W + gap
88
+
89
+ def _get_status_text(self) -> str:
90
+ parts = [f"Zoom: {self.grid.zoom:.1f}x"]
91
+ sel = len(self.grid.selected_indices)
92
+ if sel:
93
+ parts.append(f"Selected: {sel}")
94
+ if self._paste_mode:
95
+ parts.append("Click grid to paste")
96
+ if self.grid.can_undo:
97
+ parts.append(f"Undo ({len(self.grid._undo_stack)})")
98
+ return " | ".join(parts)
99
+
100
+ # ------------------------------------------------------------------
101
+ # Events
102
+ # ------------------------------------------------------------------
103
+
104
+ def handle_event(self, event: pygame.event.Event) -> bool:
105
+ # File manager modal blocks everything
106
+ if self._file_manager is not None:
107
+ return self._file_manager.handle_event(event)
108
+
109
+ if self._scale_active:
110
+ return self._handle_scale_dialog(event)
111
+
112
+ mouse = pygame.mouse.get_pos()
113
+
114
+ # Keyboard shortcuts
115
+ if event.type == pygame.KEYDOWN:
116
+ mods = pygame.key.get_mods()
117
+ ctrl = mods & (pygame.KMOD_LCTRL | pygame.KMOD_LMETA)
118
+
119
+ if ctrl:
120
+ if event.key == pygame.K_z:
121
+ if self.grid.undo():
122
+ self.grid.selected_indices.clear()
123
+ return True
124
+ elif event.key == pygame.K_y:
125
+ if self.grid.redo():
126
+ self.grid.selected_indices.clear()
127
+ return True
128
+
129
+ # Toolbar clicks
130
+ if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
131
+ for lbl, r in self._btn_rects.items():
132
+ if r.collidepoint(mouse):
133
+ return self._handle_tool(lbl)
134
+
135
+ # Paste mode: next grid click pastes
136
+ if self._paste_mode and event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
137
+ idx = self.grid.index_at_pos(mouse)
138
+ if idx >= 0 and self.grid.rect.collidepoint(mouse):
139
+ self.grid.paste_at(idx, self._clipboard)
140
+ self._paste_mode = False
141
+ self.grid.paste_preview_idx = -1
142
+ return True
143
+
144
+ # Paste preview on hover
145
+ if self._paste_mode and event.type == pygame.MOUSEMOTION:
146
+ idx = self.grid.index_at_pos(mouse)
147
+ self.grid.paste_preview_idx = idx if idx >= 0 else -1
148
+
149
+ return self.grid.handle_event(event)
150
+
151
+ def _handle_tool(self, lbl: str) -> bool:
152
+ if lbl == "Flip X":
153
+ if self.grid.has_selection():
154
+ self.grid.flip_selected(True, False)
155
+ return True
156
+ elif lbl == "Flip Y":
157
+ if self.grid.has_selection():
158
+ self.grid.flip_selected(False, True)
159
+ return True
160
+ elif lbl == "Copy":
161
+ if self.grid.has_selection():
162
+ self._clipboard = self.grid.copy_selected()
163
+ self._paste_mode = False
164
+ self.grid.paste_preview_idx = -1
165
+ return True
166
+ elif lbl == "Paste":
167
+ if self._clipboard:
168
+ self._paste_mode = not self._paste_mode
169
+ if not self._paste_mode:
170
+ self.grid.paste_preview_idx = -1
171
+ return True
172
+ elif lbl == "Undo":
173
+ self.grid.undo()
174
+ self.grid.selected_indices.clear()
175
+ return True
176
+ elif lbl == "Redo":
177
+ self.grid.redo()
178
+ self.grid.selected_indices.clear()
179
+ return True
180
+ elif lbl == "Scale":
181
+ self._scale_active = True
182
+ self._scale_text = "2.0"
183
+ self._scale_error = None
184
+ return True
185
+ elif lbl == "Save":
186
+ self._open_save_dialog()
187
+ return True
188
+ return False
189
+
190
+ def _handle_scale_dialog(self, event: pygame.event.Event) -> bool:
191
+ if event.type == pygame.KEYDOWN:
192
+ if event.key in (pygame.K_RETURN, pygame.K_KP_ENTER):
193
+ try:
194
+ factor = float(self._scale_text)
195
+ if factor <= 0:
196
+ self._scale_error = "Must be > 0"
197
+ else:
198
+ self.grid.scale(factor)
199
+ self._scale_active = False
200
+ self._scale_error = None
201
+ except ValueError:
202
+ self._scale_error = "Invalid number"
203
+ return True
204
+ elif event.key == pygame.K_ESCAPE:
205
+ self._scale_active = False
206
+ self._scale_error = None
207
+ return True
208
+ elif event.key == pygame.K_BACKSPACE:
209
+ self._scale_text = self._scale_text[:-1]
210
+ return True
211
+ elif event.unicode and event.unicode in "0123456789." and len(self._scale_text) < 8:
212
+ self._scale_text += event.unicode
213
+ return True
214
+ return False
215
+
216
+ def _open_save_dialog(self) -> None:
217
+ """Open FileManager in save mode to pick a PNG path."""
218
+ from widgets.filemanager import FileManager
219
+
220
+ initial_dir = self._save_path.parent if self._save_path else self._data_root
221
+ default_name = self._save_path.name if self._save_path else (
222
+ f"{self.image_path.stem}_edited.png" if self.image_path else "spritesheet.png"
223
+ )
224
+
225
+ fm_rect = self._file_manager_rect()
226
+ self._file_manager = FileManager(
227
+ rect=fm_rect,
228
+ initial_dir=initial_dir,
229
+ allowed_exts=[".png"],
230
+ on_save=self._on_save_path_selected,
231
+ mode="save",
232
+ default_name=default_name,
233
+ on_cancel=self._close_file_manager,
234
+ data_root=self._data_root,
235
+ )
236
+
237
+ def _on_save_path_selected(self, path: Path) -> None:
238
+ try:
239
+ self.grid.save_png(path)
240
+ self._save_path = path
241
+ except Exception as e:
242
+ print(f"Save failed: {e}")
243
+ self._close_file_manager()
244
+
245
+ def _close_file_manager(self) -> None:
246
+ self._file_manager = None
247
+
248
+ def _file_manager_rect(self) -> Rect:
249
+ w, h = 600, 400
250
+ cx, cy = self.rect.center
251
+ return Rect(cx - w // 2, cy - h // 2, w, h)
252
+
253
+ def set_save_path(self, path: Path) -> None:
254
+ self._save_path = path
255
+
256
+ # ------------------------------------------------------------------
257
+ # Drawing
258
+ # ------------------------------------------------------------------
259
+
260
+ def draw(self, screen: Surface) -> None:
261
+ draw_panel(screen, self.rect, COLORS.bg, COLORS.border)
262
+
263
+ # Toolbar
264
+ toolbar_rect = Rect(self.rect.x, self.rect.y, self.rect.w, TOOLBAR_H)
265
+ draw_panel(screen, toolbar_rect, COLORS.header, COLORS.border)
266
+
267
+ mouse = pygame.mouse.get_pos()
268
+ for lbl, r in self._btn_rects.items():
269
+ hover = r.collidepoint(mouse)
270
+ active = (lbl == "Paste" and self._paste_mode)
271
+ disable = (lbl in ("Undo",) and not self.grid.can_undo) or \
272
+ (lbl in ("Redo",) and not self.grid.can_redo)
273
+
274
+ icon_key = _BUTTON_ICONS.get(lbl)
275
+ if icon_key and icon_manager.has_icon(icon_key):
276
+ color = COLORS.text_dim if disable else COLORS.text
277
+ icon = icon_manager.get_icon(icon_key, 18, color)
278
+ draw_button(screen, r, icon, hover=hover and not disable, active=active and not disable)
279
+ else:
280
+ label_surf = self._font_sm.render(lbl, True, COLORS.text_dim if disable else COLORS.text)
281
+ draw_button(screen, r, label_surf, hover=hover and not disable, active=active and not disable)
282
+
283
+ # Grid
284
+ if self._file_manager is None:
285
+ self.grid.draw(screen)
286
+
287
+ # Status bar
288
+ status_rect = Rect(self.rect.x, self.rect.bottom - STATUS_H, self.rect.w, STATUS_H)
289
+ draw_panel(screen, status_rect, COLORS.header, COLORS.border)
290
+ st = self._get_status_text()
291
+ screen.blit(
292
+ self._font_sm.render(st, True, COLORS.text_dim),
293
+ (status_rect.x + 6, status_rect.y + 4),
294
+ )
295
+
296
+ if self._scale_active:
297
+ self._draw_scale_dialog(screen)
298
+
299
+ # File manager overlay
300
+ if self._file_manager is not None:
301
+ self._file_manager.draw(screen)
302
+
303
+ def _draw_scale_dialog(self, screen: Surface) -> None:
304
+ dw, dh = 260, 100
305
+ cx, cy = self.rect.center
306
+ dlg = Rect(cx - dw // 2, cy - dh // 2, dw, dh)
307
+ draw_panel(screen, dlg, COLORS.panel, COLORS.border)
308
+
309
+ title = self._font.render("Scale Factor", True, COLORS.text)
310
+ screen.blit(title, title.get_rect(centerx=dlg.centerx, top=dlg.top + 10))
311
+
312
+ inp = Rect(dlg.x + 20, dlg.top + 36, dw - 40, 28)
313
+ pygame.draw.rect(screen, COLORS.selected, inp, border_radius=4)
314
+ pygame.draw.rect(screen, COLORS.accent, inp, 2, border_radius=4)
315
+ txt = self._scale_text + ("|" if (pygame.time.get_ticks() // 400) % 2 else "")
316
+ screen.blit(self._font_sm.render(txt, True, COLORS.text), (inp.x + 6, inp.y + 5))
317
+
318
+ if self._scale_error:
319
+ err = self._font_sm.render(self._scale_error, True, COLORS.danger)
320
+ screen.blit(err, (dlg.x + 20, dlg.bottom - 22))
321
+
322
+ hint = self._font_sm.render("Enter / Esc", True, COLORS.text_dim)
323
+ screen.blit(hint, (dlg.right - 90, dlg.bottom - 22))
@@ -0,0 +1,118 @@
1
+ """
2
+ Standalone launcher for the Sprite Editor.
3
+
4
+ Usage:
5
+ python standalone.py path/to/spritesheet.png
6
+ python standalone.py path/to/spritesheet.png --tile-size 32
7
+ python standalone.py path/to/spritesheet.png --save output.png
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ _current_file = Path(__file__).resolve()
17
+ _src_dir = _current_file.parent.parent.parent
18
+ if str(_src_dir) not in sys.path:
19
+ sys.path.insert(0, str(_src_dir))
20
+
21
+ import pygame
22
+ from pygame import Rect
23
+
24
+ try:
25
+ from .editor import SpriteEditor, TOOLBAR_H, STATUS_H
26
+ except ImportError:
27
+ from plugins.sprite_editor.editor import SpriteEditor, TOOLBAR_H, STATUS_H
28
+ from utils import error_handler, error_context
29
+
30
+
31
+ def parse_window_size(s: str) -> tuple[int, int]:
32
+ parts = s.lower().split("x")
33
+ if len(parts) == 2:
34
+ return int(parts[0]), int(parts[1])
35
+ v = int(parts[0])
36
+ return v, v
37
+
38
+
39
+ def main(argv: list[str] | None = None) -> None:
40
+ def handle_exception(exc_type, exc_value, exc_traceback):
41
+ if issubclass(exc_type, KeyboardInterrupt):
42
+ sys.__excepthook__(exc_type, exc_value, exc_traceback)
43
+ return
44
+ error_handler.capture(exc_value, context="sprite_editor_exception")
45
+ sys.__excepthook__(exc_type, exc_value, exc_traceback)
46
+
47
+ sys.excepthook = handle_exception
48
+
49
+ parser = argparse.ArgumentParser(description="Grid Sprite Editor")
50
+ parser.add_argument("image", type=str, help="Path to spritesheet image")
51
+ parser.add_argument("--tile-size", type=str, default="32",
52
+ help="Tile size (e.g. 32 or 32x32)")
53
+ parser.add_argument("--save", type=str, default=None,
54
+ help="Output path for modified spritesheet")
55
+ parser.add_argument("--window-size", type=str, default="1000x700",
56
+ help="Window size WxH (default 1000x700)")
57
+ parser.add_argument("--data-root", type=str, default=None,
58
+ help="Project data root (for file dialogs)")
59
+
60
+ args = parser.parse_args(argv)
61
+
62
+ image_path = Path(args.image)
63
+ if not image_path.is_file():
64
+ print(f"Error: file not found: {image_path}")
65
+ sys.exit(1)
66
+
67
+ ts_parts = args.tile_size.lower().split("x")
68
+ tw = int(ts_parts[0])
69
+ th = int(ts_parts[1]) if len(ts_parts) > 1 else tw
70
+
71
+ window_size = parse_window_size(args.window_size)
72
+ data_root = Path(args.data_root) if args.data_root else image_path.parent
73
+
74
+ pygame.init()
75
+ screen = pygame.display.set_mode(window_size, pygame.RESIZABLE)
76
+ pygame.display.set_caption(f"Sprite Editor - {image_path.name}")
77
+
78
+ surface = pygame.image.load(str(image_path)).convert_alpha()
79
+
80
+ editor = SpriteEditor(
81
+ screen.get_rect(), surface, (tw, th),
82
+ image_path=image_path, data_root=data_root,
83
+ )
84
+ if args.save:
85
+ editor.set_save_path(Path(args.save))
86
+
87
+ clock = pygame.time.Clock()
88
+ running = True
89
+
90
+ with error_context("sprite_editor"):
91
+ while running:
92
+ clock.tick(60)
93
+ for event in pygame.event.get():
94
+ if event.type == pygame.QUIT:
95
+ running = False
96
+ elif event.type == pygame.VIDEORESIZE:
97
+ screen = pygame.display.set_mode(
98
+ (event.w, event.h), pygame.RESIZABLE
99
+ )
100
+ editor.rect = screen.get_rect()
101
+ editor.grid.rect = Rect(
102
+ editor.rect.x,
103
+ editor.rect.y + TOOLBAR_H,
104
+ editor.rect.w,
105
+ editor.rect.h - TOOLBAR_H - STATUS_H,
106
+ )
107
+ else:
108
+ editor.handle_event(event)
109
+
110
+ screen.fill((0, 0, 0))
111
+ editor.draw(screen)
112
+ pygame.display.flip()
113
+
114
+ pygame.quit()
115
+
116
+
117
+ if __name__ == "__main__":
118
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 3.1.7
3
+ Version: 3.2.0
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
@@ -75,6 +75,9 @@ src/plugins/sprite_animation/runtime_load.py
75
75
  src/plugins/sprite_animation/standalone.py
76
76
  src/plugins/sprite_animation/timeline.py
77
77
  src/plugins/sprite_animation/validation.py
78
+ src/plugins/sprite_editor/__init__.py
79
+ src/plugins/sprite_editor/editor.py
80
+ src/plugins/sprite_editor/standalone.py
78
81
  src/plugins/tileset_collision/__init__.py
79
82
  src/plugins/tileset_collision/collision_painter.py
80
83
  src/plugins/tileset_collision/editor.py
@@ -156,6 +159,7 @@ src/widgets/layer_selector.py
156
159
  src/widgets/map_properties.py
157
160
  src/widgets/mapsetup.py
158
161
  src/widgets/regex_automap_designer.py
162
+ src/widgets/spritesheet_grid.py
159
163
  src/widgets/tile_grid.py
160
164
  src/widgets/tile_selector.py
161
165
  src/widgets/ui/collision_layer_mask.py
@@ -1,8 +1,10 @@
1
1
  import pygame
2
2
  from pygame import Surface, Rect, Color
3
3
  from typing import TYPE_CHECKING, List, Tuple, Set, Optional
4
+ from pathlib import Path
4
5
  import time
5
6
 
7
+ from constants import BASE_PATH
6
8
  from utils.error_handler import error_handler
7
9
  from utils.icon_manager import icon_manager
8
10
  from .autotile_template import AutotileTemplateApplier