tilemap-editor 4.3.4__tar.gz → 4.3.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 (228) hide show
  1. {tilemap_editor-4.3.4/src/tilemap_editor.egg-info → tilemap_editor-4.3.5}/PKG-INFO +13 -1
  2. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/README.md +12 -0
  3. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/pyproject.toml +1 -1
  4. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/node_manager.py +23 -7
  5. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/editor.py +25 -2
  6. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/shape_editor.py +39 -6
  7. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/object_tileset_collision/editor.py +3 -2
  8. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/collision_painter.py +13 -6
  9. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/editor.py +19 -4
  10. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5/src/tilemap_editor.egg-info}/PKG-INFO +13 -1
  11. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/tile_grid.py +3 -1
  12. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/region_selector.py +23 -12
  13. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/LICENSE +0 -0
  14. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/MANIFEST.in +0 -0
  15. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  16. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  17. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  18. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  19. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  20. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  21. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  22. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  23. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/arrow-down.svg +0 -0
  24. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/check.svg +0 -0
  25. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/checked.svg +0 -0
  26. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/close.svg +0 -0
  27. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/duplicate.svg +0 -0
  28. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/error.svg +0 -0
  29. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/file.svg +0 -0
  30. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/filedead.svg +0 -0
  31. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/fit.svg +0 -0
  32. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/folder.svg +0 -0
  33. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/grid.svg +0 -0
  34. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/image.svg +0 -0
  35. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/info.svg +0 -0
  36. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/load.svg +0 -0
  37. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/loop.svg +0 -0
  38. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/onion.svg +0 -0
  39. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/pan.svg +0 -0
  40. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/pause.svg +0 -0
  41. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/pencil.svg +0 -0
  42. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/play.svg +0 -0
  43. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/plus.svg +0 -0
  44. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/radio.svg +0 -0
  45. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/reset.svg +0 -0
  46. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/save.svg +0 -0
  47. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/skip-back.svg +0 -0
  48. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/skip-forward.svg +0 -0
  49. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/stop.svg +0 -0
  50. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/tilemap.svg +0 -0
  51. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/tileset.svg +0 -0
  52. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/unchecked.svg +0 -0
  53. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/warning.svg +0 -0
  54. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/zoomin.svg +0 -0
  55. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/assets/icons/zoomout.svg +0 -0
  56. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/setup.cfg +0 -0
  57. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/constants.py +0 -0
  58. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/editor.py +0 -0
  59. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/event_map.py +0 -0
  60. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/layers.py +0 -0
  61. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/main.py +0 -0
  62. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/nodes.py +0 -0
  63. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/__init__.py +0 -0
  64. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/__init__.py +0 -0
  65. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/models.py +0 -0
  66. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/protocols.py +0 -0
  67. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/character_collision/standalone.py +0 -0
  68. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/object_tileset_collision/__init__.py +0 -0
  69. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/object_tileset_collision/models.py +0 -0
  70. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/object_tileset_collision/protocols.py +0 -0
  71. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/object_tileset_collision/standalone.py +0 -0
  72. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/__init__.py +0 -0
  73. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/__main__.py +0 -0
  74. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  75. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/editor.py +0 -0
  76. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/frame_picker.py +0 -0
  77. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/models.py +0 -0
  78. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/preview.py +0 -0
  79. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/protocols.py +0 -0
  80. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/runtime_load.py +0 -0
  81. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/standalone.py +0 -0
  82. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/timeline.py +0 -0
  83. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_animation/validation.py +0 -0
  84. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_editor/__init__.py +0 -0
  85. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_editor/dialogs.py +0 -0
  86. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_editor/editor.py +0 -0
  87. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_editor/region_export.py +0 -0
  88. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/sprite_editor/standalone.py +0 -0
  89. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/__init__.py +0 -0
  90. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/models.py +0 -0
  91. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/protocols.py +0 -0
  92. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/plugins/tileset_collision/standalone.py +0 -0
  93. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/standalone_automap.py +0 -0
  94. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/standalone_error_console.py +0 -0
  95. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/standalone_filemanager.py +0 -0
  96. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/standalone_image_viewer.py +0 -0
  97. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap.py +0 -0
  98. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/__init__.py +0 -0
  99. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/__main__.py +0 -0
  100. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/__init__.py +0 -0
  101. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  102. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  103. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  104. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  105. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  106. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  107. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  108. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  109. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  110. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  111. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/check.svg +0 -0
  112. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  113. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/close.svg +0 -0
  114. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  115. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/error.svg +0 -0
  116. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/file.svg +0 -0
  117. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  118. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  119. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/fold_down_arrow.svg +0 -0
  120. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  121. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/gear.svg +0 -0
  122. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  123. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/image.svg +0 -0
  124. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/info.svg +0 -0
  125. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/load.svg +0 -0
  126. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  127. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/miniobj.svg +0 -0
  128. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/onion.svg +0 -0
  129. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  130. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  131. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  132. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/play.svg +0 -0
  133. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  134. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  135. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  136. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/save.svg +0 -0
  137. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/skip-back.svg +0 -0
  138. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/skip-forward.svg +0 -0
  139. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  140. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  141. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  142. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  143. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/unfold_right_arrow.svg +0 -0
  144. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  145. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  146. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  147. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/cli.py +0 -0
  148. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/main.py +0 -0
  149. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor/settings.py +0 -0
  150. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor.egg-info/SOURCES.txt +0 -0
  151. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  152. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  153. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor.egg-info/requires.txt +0 -0
  154. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  155. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/ttypes/__init__.py +0 -0
  156. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/ttypes/tilemap.py +0 -0
  157. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/__init__.py +0 -0
  158. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/editor_preference.py +0 -0
  159. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/error_handler.py +0 -0
  160. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/font_manager.py +0 -0
  161. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/history.py +0 -0
  162. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/icon_manager.py +0 -0
  163. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/icons_cache.py +0 -0
  164. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/log_capture.py +0 -0
  165. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/project_paths.py +0 -0
  166. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/serialization.py +0 -0
  167. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/standalone.py +0 -0
  168. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/utils/validation.py +0 -0
  169. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/__init__.py +0 -0
  170. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/automap_models.py +0 -0
  171. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/autotile_template.py +0 -0
  172. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/autotiler.py +0 -0
  173. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/filemanager.py +0 -0
  174. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/input.py +0 -0
  175. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/layer_selector.py +0 -0
  176. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/map_properties.py +0 -0
  177. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/mapsetup.py +0 -0
  178. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/particle_presets.py +0 -0
  179. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/particle_system.py +0 -0
  180. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/regex_automap_designer.py +0 -0
  181. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/spritesheet_grid.py +0 -0
  182. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/tile_selector.py +0 -0
  183. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/button.py +0 -0
  184. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/checkbox.py +0 -0
  185. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/collision_layer_mask.py +0 -0
  186. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  187. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/confirm_dialog.py +0 -0
  188. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/dialog_base.py +0 -0
  189. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/drag_tracker.py +0 -0
  190. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/draw_utils.py +0 -0
  191. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/fileinput.py +0 -0
  192. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/label.py +0 -0
  193. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/layer_type_dialog.py +0 -0
  194. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/menubar.py +0 -0
  195. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/mode_indicator.py +0 -0
  196. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/node_editor.py +0 -0
  197. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/node_selector.py +0 -0
  198. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/notification.py +0 -0
  199. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/particle_config_dialog.py +0 -0
  200. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/property_editor.py +0 -0
  201. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/scrollbar.py +0 -0
  202. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/sidebar_container.py +0 -0
  203. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/splitter.py +0 -0
  204. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/status_bar.py +0 -0
  205. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/theme.py +0 -0
  206. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/tileset_type_dialog.py +0 -0
  207. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/toast.py +0 -0
  208. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/tool_manager.py +0 -0
  209. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/toolbar.py +0 -0
  210. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/tooltip.py +0 -0
  211. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/ui/tree_widget.py +0 -0
  212. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/src/widgets/widget_base.py +0 -0
  213. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_animation_library_grid_offset.py +0 -0
  214. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_collision_layer_mask.py +0 -0
  215. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_collision_layer_sidebar.py +0 -0
  216. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_drag_tracker.py +0 -0
  217. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_editor_pan_mode.py +0 -0
  218. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_gid_collision.py +0 -0
  219. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_layers_autotile.py +0 -0
  220. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_project_paths.py +0 -0
  221. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_render_scale.py +0 -0
  222. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_serialization_regression.py +0 -0
  223. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_sprite_animation_editor_grid.py +0 -0
  224. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_tile_grid_selection.py +0 -0
  225. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_tile_selector_pick.py +0 -0
  226. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_tilemap_save.py +0 -0
  227. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_timeline_invalidate_cache.py +0 -0
  228. {tilemap_editor-4.3.4 → tilemap_editor-4.3.5}/tests/test_toolbar_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 4.3.4
3
+ Version: 4.3.5
4
4
  Summary: Pygame tilemap editor with collision, animation, sprite & particle tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -18,6 +18,15 @@ Dynamic: license-file
18
18
 
19
19
  `tilemap-editor` is a pygame-based map editor focused on fast iteration for 2D games.
20
20
 
21
+ # tilemap-editor
22
+
23
+ `tilemap-editor` is a Pygame-based map editor focused on fast iteration for 2D games.
24
+
25
+ > **Credits:** The initial version of this project was based on DaFluffyPotato's platformer tutorial which is about 6-hours. If you want to understand the foundation this project started from, I highly recommend watching his video: https://www.youtube.com/watch?v=2gABYM5M0ww. While the editor has since evolved with many additional features and improvements, the original map format has been preserved for compatibility.
26
+
27
+ Several features and design ideas were also inspired by the Godot Engine, including the animation workflow, polygon collision editing, and character collision (Sprite2D-style) editing.
28
+
29
+
21
30
  ## Installation
22
31
 
23
32
  [tilemap-editor on PyPI](https://pypi.org/project/tilemap-editor/)
@@ -55,3 +64,6 @@ if __name__ == "__main__":
55
64
  editor = Editor()
56
65
  editor.run()
57
66
  ```
67
+
68
+ > [!WARNING]
69
+ > The current release requires **Python 3.11+**. The documentation incorrectly lists Python 3.10 support due to an accidental dependency on `typing.NotRequired`. This will be fixed in a future update.
@@ -2,6 +2,15 @@
2
2
 
3
3
  `tilemap-editor` is a pygame-based map editor focused on fast iteration for 2D games.
4
4
 
5
+ # tilemap-editor
6
+
7
+ `tilemap-editor` is a Pygame-based map editor focused on fast iteration for 2D games.
8
+
9
+ > **Credits:** The initial version of this project was based on DaFluffyPotato's platformer tutorial which is about 6-hours. If you want to understand the foundation this project started from, I highly recommend watching his video: https://www.youtube.com/watch?v=2gABYM5M0ww. While the editor has since evolved with many additional features and improvements, the original map format has been preserved for compatibility.
10
+
11
+ Several features and design ideas were also inspired by the Godot Engine, including the animation workflow, polygon collision editing, and character collision (Sprite2D-style) editing.
12
+
13
+
5
14
  ## Installation
6
15
 
7
16
  [tilemap-editor on PyPI](https://pypi.org/project/tilemap-editor/)
@@ -39,3 +48,6 @@ if __name__ == "__main__":
39
48
  editor = Editor()
40
49
  editor.run()
41
50
  ```
51
+
52
+ > [!WARNING]
53
+ > The current release requires **Python 3.11+**. The documentation incorrectly lists Python 3.10 support due to an accidental dependency on `typing.NotRequired`. This will be fixed in a future update.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-editor"
7
- version = "4.3.4"
7
+ version = "4.3.5"
8
8
  description = "Pygame tilemap editor with collision, animation, sprite & particle tools"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -13,7 +13,7 @@ def create_node_id() -> str:
13
13
  return str(uuid.uuid4())
14
14
 
15
15
 
16
- SIDECAR_VERSION = 1
16
+ SIDECAR_VERSION = 2
17
17
 
18
18
 
19
19
  class NodeManager:
@@ -49,10 +49,15 @@ class NodeManager:
49
49
  raw = json.loads(sidecar.read_text(encoding="utf-8"))
50
50
  if not isinstance(raw, dict):
51
51
  return
52
+ version = raw.get("version", 1)
52
53
  self.groups = list(raw.get("groups", []))
54
+ rs = self.editor.tilemap.render_scale
53
55
  for item in raw.get("nodes", []):
54
56
  if isinstance(item, dict):
55
57
  node = Node.from_dict(item)
58
+ if version >= 2:
59
+ node.area.x = int(node.area.x * rs)
60
+ node.area.y = int(node.area.y * rs)
56
61
  self.nodes[node.node_id] = node
57
62
  except (json.JSONDecodeError, KeyError, ValueError, TypeError):
58
63
  import logging
@@ -62,12 +67,23 @@ class NodeManager:
62
67
  def save(self, map_path: Path) -> None:
63
68
  sidecar = self._sidecar_path_for(map_path)
64
69
  self.nodes_dir.mkdir(parents=True, exist_ok=True)
65
- data: dict[str, Any] = {
66
- "version": SIDECAR_VERSION,
67
- "groups": self.groups,
68
- "nodes": [node.to_dict() for node in self.nodes.values()],
69
- }
70
- sidecar.write_text(json.dumps(data, indent=2), encoding="utf-8")
70
+ rs = self.editor.tilemap.render_scale
71
+ orig_areas: dict[str, tuple[int, int]] = {}
72
+ for nid, node in self.nodes.items():
73
+ orig_areas[nid] = (node.area.x, node.area.y)
74
+ node.area.x = int(node.area.x / rs)
75
+ node.area.y = int(node.area.y / rs)
76
+ try:
77
+ data: dict[str, Any] = {
78
+ "version": SIDECAR_VERSION,
79
+ "groups": self.groups,
80
+ "nodes": [node.to_dict() for node in self.nodes.values()],
81
+ }
82
+ sidecar.write_text(json.dumps(data, indent=2), encoding="utf-8")
83
+ finally:
84
+ for nid, (ox, oy) in orig_areas.items():
85
+ self.nodes[nid].area.x = ox
86
+ self.nodes[nid].area.y = oy
71
87
 
72
88
  def add_node(self, node: Node) -> str:
73
89
  self.nodes[node.node_id] = node
@@ -182,11 +182,32 @@ class CharacterCollisionEditor:
182
182
  self._image_path = self._rel_path(path)
183
183
  pygame.display.set_caption(f"Character Collision Editor — {path.stem}")
184
184
  self._toast_manager.success(f"Loaded sprite: {path.name}")
185
+ self._auto_load_collision()
185
186
  except Exception as e:
186
187
  self._toast_manager.error(f"Failed to load image: {e}")
187
188
  finally:
188
189
  self._image_dialog = None
189
190
 
191
+ def _auto_load_collision(self) -> bool:
192
+ name = self._name_input.text.strip()
193
+ if not name:
194
+ return False
195
+ safe = re.sub(r"[^\w\-]+", "-", name).strip("-").lower()
196
+ coll_filename = f"{safe}.collision.json"
197
+ try:
198
+ coll_dir = self._get_collision_dir()
199
+ except RuntimeError:
200
+ return False
201
+ coll_path = coll_dir / coll_filename
202
+ if coll_path.exists():
203
+ try:
204
+ self.load_from_file(coll_path)
205
+ self._toast_manager.success(f"Loaded collision: {coll_path.name}")
206
+ return True
207
+ except Exception:
208
+ pass
209
+ return False
210
+
190
211
  def _open_image_dialog(self) -> None:
191
212
  try:
192
213
  data_root = self._data_root or Path.cwd()
@@ -281,7 +302,6 @@ class CharacterCollisionEditor:
281
302
  self.character_name = data.name
282
303
  self._name_input.text = data.name
283
304
  self._name_input.cursor_pos = len(data.name)
284
- self.shape_editor.load_shape_data(data.shape.to_dict())
285
305
  layer = data.properties.get("collision_layer", 1)
286
306
  mask = data.properties.get("collision_mask", 0xFFFF)
287
307
  self.layer_sidebar.set_layer(layer)
@@ -293,7 +313,9 @@ class CharacterCollisionEditor:
293
313
  if resolved:
294
314
  self._load_sprite_from_path(resolved)
295
315
  self._toast_manager.success(f"Sprite loaded: {resolved.name}")
296
- return
316
+
317
+ self.shape_editor.load_shape_data(data.shape.to_dict())
318
+ return
297
319
 
298
320
  if data.name:
299
321
  for d in [self._data_root]:
@@ -545,6 +567,7 @@ class CharacterCollisionEditor:
545
567
  editor = cls(rect, surface, character_name)
546
568
  editor._data_root = data_root
547
569
  editor._image_path = image_path
570
+ editor._auto_load_collision()
548
571
  return editor
549
572
 
550
573
  def run(self) -> None:
@@ -100,6 +100,30 @@ class ShapeEditor:
100
100
  self.offset_x = (self.rect.w - sw * self.zoom) / 2
101
101
  self.offset_y = (self.rect.h - sh * self.zoom) / 2
102
102
 
103
+ def _focus_on_shape(self) -> None:
104
+ """Center the viewport on the shape's bounding box"""
105
+ left, top, right, bottom = self._shape_bounds()
106
+ cx = (left + right) / 2
107
+ cy = (top + bottom) / 2
108
+ self.offset_x = self.rect.w / 2 - cx * self.zoom
109
+ self.offset_y = self.rect.h / 2 - cy * self.zoom
110
+
111
+ def _shape_bounds(self) -> tuple[float, float, float, float]:
112
+ """Get shape bounding box in sprite-local coords (left, top, right, bottom)"""
113
+ if self.shape_type == "rectangle":
114
+ return (self.rect_x, self.rect_y, self.rect_x + self.rect_w, self.rect_y + self.rect_h)
115
+ if self.shape_type == "circle":
116
+ return (self.circle_x - self.circle_radius, self.circle_y - self.circle_radius,
117
+ self.circle_x + self.circle_radius, self.circle_y + self.circle_radius)
118
+ if self.shape_type == "capsule":
119
+ return (self.capsule_x - self.capsule_radius, self.capsule_y,
120
+ self.capsule_x + self.capsule_radius, self.capsule_y + self.capsule_height)
121
+ if self.shape_type == "polygon" and self.polygon_vertices:
122
+ xs = [v[0] for v in self.polygon_vertices]
123
+ ys = [v[1] for v in self.polygon_vertices]
124
+ return (min(xs), min(ys), max(xs), max(ys))
125
+ return (0, 0, 0, 0)
126
+
103
127
  def _center_shape(self) -> None:
104
128
  """Center all shape types on the sprite"""
105
129
  sw, sh = self.sprite_surface.get_size()
@@ -195,6 +219,8 @@ class ShapeEditor:
195
219
  elif shape_type == "polygon":
196
220
  self.polygon_vertices = [tuple(v) for v in data.get("vertices", [])]
197
221
 
222
+ self._focus_on_shape()
223
+
198
224
  def resize(self, rect: Rect) -> None:
199
225
  """Update rect"""
200
226
  self.rect = rect
@@ -254,12 +280,19 @@ class ShapeEditor:
254
280
  self.hover_handle = None
255
281
 
256
282
  if event.type == pygame.MOUSEWHEEL and self.rect.collidepoint(mouse):
257
- self.zoom *= 1.15 if event.y > 0 else 0.87
258
- self.zoom = max(0.5, min(self.zoom, 8.0))
259
-
260
- sprite_pos = self._screen_to_sprite(mouse)
261
- self.offset_x = mouse[0] - self.rect.x - sprite_pos[0] * self.zoom
262
- self.offset_y = mouse[1] - self.rect.y - sprite_pos[1] * self.zoom
283
+ mods = pygame.key.get_mods()
284
+ if mods & (pygame.KMOD_CTRL | pygame.KMOD_META):
285
+ self.zoom *= 1.15 if event.y > 0 else 0.87
286
+ self.zoom = max(0.5, min(self.zoom, 8.0))
287
+ sprite_pos = self._screen_to_sprite(mouse)
288
+ self.offset_x = mouse[0] - self.rect.x - sprite_pos[0] * self.zoom
289
+ self.offset_y = mouse[1] - self.rect.y - sprite_pos[1] * self.zoom
290
+ elif mods & pygame.KMOD_SHIFT:
291
+ scroll_val = event.y if event.y != 0 else event.x
292
+ self.offset_x -= scroll_val * 30
293
+ else:
294
+ scroll_val = event.y if event.y != 0 else event.x
295
+ self.offset_y -= scroll_val * 30
263
296
  return True
264
297
 
265
298
  if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
@@ -234,12 +234,13 @@ class ObjectTilesetCollisionEditor:
234
234
  def _layout_toolbar_buttons(self) -> None:
235
235
  x = self.toolbar_rect.x + 10
236
236
  y = self.toolbar_rect.y + 8
237
- for i, btn in enumerate(self._toolbar_buttons):
237
+ for btn in self._toolbar_buttons:
238
238
  if btn.text == "?":
239
239
  w, h = 28, 28
240
240
  else:
241
241
  w, h = 60, 28
242
- btn.resize(x + i * (w + 8), y, w, h)
242
+ btn.resize(x, y, w, h)
243
+ x += w + 8
243
244
 
244
245
  def _on_splitter_drag(self, pos: int) -> None:
245
246
  self.tileset_selector_height = max(
@@ -476,12 +476,19 @@ class CollisionPainter:
476
476
  return True
477
477
 
478
478
  if event.type == pygame.MOUSEWHEEL and self.rect.collidepoint(mouse):
479
- self.zoom *= 1.15 if event.y > 0 else 0.87
480
- self.zoom = max(0.5, min(self.zoom, 8.0))
481
-
482
- tile_pos = self._screen_to_tile(mouse)
483
- self.offset_x = mouse[0] - self.rect.x - tile_pos[0] * self.zoom
484
- self.offset_y = mouse[1] - self.rect.y - tile_pos[1] * self.zoom
479
+ mods = pygame.key.get_mods()
480
+ if mods & (pygame.KMOD_CTRL | pygame.KMOD_META):
481
+ self.zoom *= 1.15 if event.y > 0 else 0.87
482
+ self.zoom = max(0.5, min(self.zoom, 8.0))
483
+ tile_pos = self._screen_to_tile(mouse)
484
+ self.offset_x = mouse[0] - self.rect.x - tile_pos[0] * self.zoom
485
+ self.offset_y = mouse[1] - self.rect.y - tile_pos[1] * self.zoom
486
+ elif mods & pygame.KMOD_SHIFT:
487
+ scroll_val = event.y if event.y != 0 else event.x
488
+ self.offset_x -= scroll_val * 30
489
+ else:
490
+ scroll_val = event.y if event.y != 0 else event.x
491
+ self.offset_y -= scroll_val * 30
485
492
  return True
486
493
 
487
494
  if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
@@ -716,8 +716,18 @@ class TilesetCollisionEditor:
716
716
  return True
717
717
 
718
718
  if event.type == pygame.MOUSEWHEEL:
719
- self.tileset_zoom *= 1.15 if event.y > 0 else 0.87
720
- self.tileset_zoom = max(0.5, min(self.tileset_zoom, 8.0))
719
+ mods = pygame.key.get_mods()
720
+ if mods & (pygame.KMOD_CTRL | pygame.KMOD_META):
721
+ self.tileset_zoom *= 1.15 if event.y > 0 else 0.87
722
+ self.tileset_zoom = max(0.5, min(self.tileset_zoom, 8.0))
723
+ elif mods & pygame.KMOD_SHIFT:
724
+ scroll_val = event.y if event.y != 0 else event.x
725
+ self.tileset_scroll_x -= scroll_val * 30
726
+ else:
727
+ scroll_val = event.y if event.y != 0 else event.x
728
+ self.tileset_scroll_y -= scroll_val * 30
729
+ self.tileset_scroll_x = max(0, self.tileset_scroll_x)
730
+ self.tileset_scroll_y = max(0, self.tileset_scroll_y)
721
731
  return True
722
732
 
723
733
  if event.type == pygame.MOUSEBUTTONUP:
@@ -947,12 +957,17 @@ class TilesetCollisionEditor:
947
957
  tw = int(self._tile_size[0] * self.tileset_zoom)
948
958
  th = int(self._tile_size[1] * self.tileset_zoom)
949
959
 
960
+ tileset_scr_w = self.tile_cols * tw
961
+ tileset_scr_h = self.tile_rows * th
962
+ center_off_x = max(0, (self.tileset_selector_rect.w - tileset_scr_w) // 2)
963
+ center_off_y = max(0, (self.tileset_selector_rect.h - tileset_scr_h) // 2)
964
+
950
965
  for row in range(self.tile_rows):
951
966
  for col in range(self.tile_cols):
952
967
  tile_id = row * self.tile_cols + col
953
968
 
954
- x = self.tileset_selector_rect.x + col * tw - self.tileset_scroll_x
955
- y = self.tileset_selector_rect.y + row * th - self.tileset_scroll_y
969
+ x = self.tileset_selector_rect.x + col * tw - self.tileset_scroll_x + center_off_x
970
+ y = self.tileset_selector_rect.y + row * th - self.tileset_scroll_y + center_off_y
956
971
 
957
972
  if (
958
973
  x + tw < self.tileset_selector_rect.x
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 4.3.4
3
+ Version: 4.3.5
4
4
  Summary: Pygame tilemap editor with collision, animation, sprite & particle tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -18,6 +18,15 @@ Dynamic: license-file
18
18
 
19
19
  `tilemap-editor` is a pygame-based map editor focused on fast iteration for 2D games.
20
20
 
21
+ # tilemap-editor
22
+
23
+ `tilemap-editor` is a Pygame-based map editor focused on fast iteration for 2D games.
24
+
25
+ > **Credits:** The initial version of this project was based on DaFluffyPotato's platformer tutorial which is about 6-hours. If you want to understand the foundation this project started from, I highly recommend watching his video: https://www.youtube.com/watch?v=2gABYM5M0ww. While the editor has since evolved with many additional features and improvements, the original map format has been preserved for compatibility.
26
+
27
+ Several features and design ideas were also inspired by the Godot Engine, including the animation workflow, polygon collision editing, and character collision (Sprite2D-style) editing.
28
+
29
+
21
30
  ## Installation
22
31
 
23
32
  [tilemap-editor on PyPI](https://pypi.org/project/tilemap-editor/)
@@ -55,3 +64,6 @@ if __name__ == "__main__":
55
64
  editor = Editor()
56
65
  editor.run()
57
66
  ```
67
+
68
+ > [!WARNING]
69
+ > The current release requires **Python 3.11+**. The documentation incorrectly lists Python 3.10 support due to an accidental dependency on `typing.NotRequired`. This will be fixed in a future update.
@@ -799,10 +799,12 @@ class TileGrid:
799
799
  elif active_layer.layer_type == "object":
800
800
  mouse_pos = pygame.mouse.get_pos()
801
801
  world_pos = self.screen_to_world(mouse_pos)
802
+ rs = self.editor.tilemap.render_scale
803
+ pick_pos = (int(world_pos[0] / rs), int(world_pos[1] / rs)) if rs else world_pos
802
804
  for _obj_id, obj in active_layer.get_all_objects().items():
803
805
  area = obj["area"]
804
806
  obj_rect = Rect(area["x"], area["y"], area["w"], area["h"])
805
- if obj_rect.collidepoint(world_pos):
807
+ if obj_rect.collidepoint(pick_pos):
806
808
  ttype = int(obj["ttype"])
807
809
  variant = obj["variant"]
808
810
  ts_widget.select_tile_by_variant(ttype, variant)
@@ -329,17 +329,26 @@ class RegionSelector:
329
329
  self._update_hover(mouse)
330
330
 
331
331
  if event.type == pygame.MOUSEWHEEL and in_bounds:
332
- old_zoom = self.zoom
333
- if event.y > 0:
334
- self.zoom = min(self.zoom * 1.15, 8.0)
332
+ mods = pygame.key.get_mods()
333
+ if mods & (pygame.KMOD_CTRL | pygame.KMOD_META):
334
+ old_zoom = self.zoom
335
+ if event.y > 0:
336
+ self.zoom = min(self.zoom * 1.15, 8.0)
337
+ else:
338
+ self.zoom = max(self.zoom * 0.87, 0.25)
339
+ if self.image:
340
+ img_x = (mouse[0] - self.rect.x + self.scroll_x) / old_zoom
341
+ img_y = (mouse[1] - self.rect.y + self.scroll_y) / old_zoom
342
+ self.scroll_x = int(img_x * self.zoom - (mouse[0] - self.rect.x))
343
+ self.scroll_y = int(img_y * self.zoom - (mouse[1] - self.rect.y))
344
+ self._clamp_scroll()
345
+ elif mods & pygame.KMOD_SHIFT:
346
+ scroll_val = event.y if event.y != 0 else event.x
347
+ self.scroll_x -= scroll_val * 30
348
+ self._clamp_scroll()
335
349
  else:
336
- self.zoom = max(self.zoom * 0.87, 0.25)
337
-
338
- if self.image:
339
- img_x = (mouse[0] - self.rect.x + self.scroll_x) / old_zoom
340
- img_y = (mouse[1] - self.rect.y + self.scroll_y) / old_zoom
341
- self.scroll_x = int(img_x * self.zoom - (mouse[0] - self.rect.x))
342
- self.scroll_y = int(img_y * self.zoom - (mouse[1] - self.rect.y))
350
+ scroll_val = event.y if event.y != 0 else event.x
351
+ self.scroll_y -= scroll_val * 30
343
352
  self._clamp_scroll()
344
353
  return True
345
354
 
@@ -501,8 +510,10 @@ class RegionSelector:
501
510
  if self.image:
502
511
  img_w = int(self.image.get_width() * self.zoom)
503
512
  img_h = int(self.image.get_height() * self.zoom)
504
- img_x = self.rect.x - self.scroll_x
505
- img_y = self.rect.y - self.scroll_y
513
+ center_off_x = max(0, (self.rect.w - img_w) // 2)
514
+ center_off_y = max(0, (self.rect.h - img_h) // 2)
515
+ img_x = self.rect.x - self.scroll_x + center_off_x
516
+ img_y = self.rect.y - self.scroll_y + center_off_y
506
517
 
507
518
  clip = screen.get_clip()
508
519
  screen.set_clip(self.rect)
File without changes
File without changes