tilemap-editor 3.1.2__tar.gz → 3.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. {tilemap_editor-3.1.2/src/tilemap_editor.egg-info → tilemap_editor-3.1.4}/PKG-INFO +1 -1
  2. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/pyproject.toml +1 -1
  3. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/editor.py +19 -1
  4. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap.py +9 -1
  5. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/settings.py +4 -0
  6. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
  7. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor.egg-info/SOURCES.txt +3 -1
  8. tilemap_editor-3.1.4/src/widgets/map_properties.py +133 -0
  9. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/tile_grid.py +55 -45
  10. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/menubar.py +1 -0
  11. tilemap_editor-3.1.4/tests/test_project_paths.py +145 -0
  12. tilemap_editor-3.1.4/tests/test_render_scale.py +174 -0
  13. tilemap_editor-3.1.2/tests/test_project_paths.py +0 -73
  14. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/LICENSE +0 -0
  15. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/MANIFEST.in +0 -0
  16. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/README.md +0 -0
  17. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  18. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  19. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  20. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  21. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  22. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  23. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  24. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  25. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/arrow-down.svg +0 -0
  26. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/check.svg +0 -0
  27. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/checked.svg +0 -0
  28. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/close.svg +0 -0
  29. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/duplicate.svg +0 -0
  30. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/error.svg +0 -0
  31. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/file.svg +0 -0
  32. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/filedead.svg +0 -0
  33. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/fit.svg +0 -0
  34. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/folder.svg +0 -0
  35. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/grid.svg +0 -0
  36. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/image.svg +0 -0
  37. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/info.svg +0 -0
  38. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/load.svg +0 -0
  39. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/loop.svg +0 -0
  40. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/pan.svg +0 -0
  41. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/pause.svg +0 -0
  42. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/pencil.svg +0 -0
  43. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/play.svg +0 -0
  44. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/plus.svg +0 -0
  45. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/radio.svg +0 -0
  46. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/reset.svg +0 -0
  47. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/save.svg +0 -0
  48. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/stop.svg +0 -0
  49. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/tilemap.svg +0 -0
  50. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/tileset.svg +0 -0
  51. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/unchecked.svg +0 -0
  52. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/warning.svg +0 -0
  53. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/zoomin.svg +0 -0
  54. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/assets/icons/zoomout.svg +0 -0
  55. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/setup.cfg +0 -0
  56. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/configs/themes.py +0 -0
  57. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/constants.py +0 -0
  58. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/event_map.py +0 -0
  59. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/layers.py +0 -0
  60. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/main.py +0 -0
  61. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/__init__.py +0 -0
  62. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/__init__.py +0 -0
  63. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/editor.py +0 -0
  64. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/models.py +0 -0
  65. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/protocols.py +0 -0
  66. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/shape_editor.py +0 -0
  67. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/character_collision/standalone.py +0 -0
  68. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/object_tileset_collision/__init__.py +0 -0
  69. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/object_tileset_collision/editor.py +0 -0
  70. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/object_tileset_collision/models.py +0 -0
  71. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/object_tileset_collision/protocols.py +0 -0
  72. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/object_tileset_collision/standalone.py +0 -0
  73. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/__init__.py +0 -0
  74. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/__main__.py +0 -0
  75. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/clipboard_util.py +0 -0
  76. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/editor.py +0 -0
  77. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/frame_picker.py +0 -0
  78. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/models.py +0 -0
  79. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/preview.py +0 -0
  80. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/protocols.py +0 -0
  81. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/runtime_load.py +0 -0
  82. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/standalone.py +0 -0
  83. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/timeline.py +0 -0
  84. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/sprite_animation/validation.py +0 -0
  85. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/__init__.py +0 -0
  86. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/collision_painter.py +0 -0
  87. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/editor.py +0 -0
  88. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/models.py +0 -0
  89. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/protocols.py +0 -0
  90. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/plugins/tileset_collision/standalone.py +0 -0
  91. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/standalone_automap.py +0 -0
  92. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/standalone_error_console.py +0 -0
  93. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/standalone_filemanager.py +0 -0
  94. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/standalone_image_viewer.py +0 -0
  95. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/__init__.py +0 -0
  96. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/__main__.py +0 -0
  97. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/__init__.py +0 -0
  98. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
  99. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  100. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
  101. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
  102. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
  103. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
  104. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
  105. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
  106. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
  107. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
  108. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/check.svg +0 -0
  109. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/checked.svg +0 -0
  110. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/close.svg +0 -0
  111. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
  112. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/error.svg +0 -0
  113. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/file.svg +0 -0
  114. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
  115. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/fit.svg +0 -0
  116. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/folder.svg +0 -0
  117. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/grid.svg +0 -0
  118. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/image.svg +0 -0
  119. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/info.svg +0 -0
  120. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/load.svg +0 -0
  121. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/loop.svg +0 -0
  122. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/pan.svg +0 -0
  123. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/pause.svg +0 -0
  124. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
  125. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/play.svg +0 -0
  126. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/plus.svg +0 -0
  127. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/radio.svg +0 -0
  128. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/reset.svg +0 -0
  129. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/save.svg +0 -0
  130. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/stop.svg +0 -0
  131. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
  132. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
  133. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
  134. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/warning.svg +0 -0
  135. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
  136. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
  137. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/cli.py +0 -0
  138. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor/main.py +0 -0
  139. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
  140. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
  141. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor.egg-info/requires.txt +0 -0
  142. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/tilemap_editor.egg-info/top_level.txt +0 -0
  143. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/ttypes/__init__.py +0 -0
  144. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/ttypes/tilemap.py +0 -0
  145. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/__init__.py +0 -0
  146. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/editor_preference.py +0 -0
  147. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/error_handler.py +0 -0
  148. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/font_manager.py +0 -0
  149. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/history.py +0 -0
  150. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/icon_manager.py +0 -0
  151. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/icons_cache.py +0 -0
  152. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/log_capture.py +0 -0
  153. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/project_paths.py +0 -0
  154. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/serialization.py +0 -0
  155. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/standalone.py +0 -0
  156. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/utils/validation.py +0 -0
  157. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/__init__.py +0 -0
  158. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/automap_models.py +0 -0
  159. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/autotile_template.py +0 -0
  160. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/autotiler.py +0 -0
  161. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/filemanager.py +0 -0
  162. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/input.py +0 -0
  163. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/layer_selector.py +0 -0
  164. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/mapsetup.py +0 -0
  165. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/regex_automap_designer.py +0 -0
  166. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/tile_selector.py +0 -0
  167. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/collision_layer_mask.py +0 -0
  168. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/collision_layer_sidebar.py +0 -0
  169. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/draw_utils.py +0 -0
  170. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/fileinput.py +0 -0
  171. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/layer_type_dialog.py +0 -0
  172. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/mode_indicator.py +0 -0
  173. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/notification.py +0 -0
  174. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/property_editor.py +0 -0
  175. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/region_selector.py +0 -0
  176. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/status_bar.py +0 -0
  177. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/theme.py +0 -0
  178. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/tileset_type_dialog.py +0 -0
  179. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/toolbar.py +0 -0
  180. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/src/widgets/ui/tooltip.py +0 -0
  181. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/tests/test_collision_layer_mask.py +0 -0
  182. {tilemap_editor-3.1.2 → tilemap_editor-3.1.4}/tests/test_collision_layer_sidebar.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 3.1.2
3
+ Version: 3.1.4
4
4
  Summary: Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-editor"
7
- version = "3.1.2"
7
+ version = "3.1.4"
8
8
  description = "Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -21,6 +21,7 @@ from tilemap import Tilemap
21
21
  from widgets.autotiler import AutotileRuleDesigner
22
22
  from widgets.regex_automap_designer import RegexAutomapDesigner
23
23
  from widgets.mapsetup import MapSetup
24
+ from widgets.map_properties import MapPropertiesDialog
24
25
  from widgets.tile_selector import TileSelector
25
26
  from widgets.tile_grid import TileGrid
26
27
  from widgets.layer_selector import LayerSelector
@@ -117,7 +118,7 @@ def _load_project_config() -> tuple[Path, Path, dict]:
117
118
  data_root = base_path / data_path
118
119
 
119
120
  if not data_root.exists():
120
- raise RuntimeError(f"Data directory not found: {data_root}. Run 'tilemap-editor init' to create project structure.")
121
+ raise RuntimeError(f"Data directory not found: {data_root}. Run 'tilemap-editor init' to create the project structure.")
121
122
 
122
123
  # Initialize error_handler with proper paths
123
124
  log_root = data_root / "logs"
@@ -166,6 +167,7 @@ class Editor:
166
167
  self.tileset_h = 300
167
168
  self.layer_h = 150
168
169
  self.map_setup_widget: Optional[MapSetup] = None
170
+ self.map_properties_dialog: Optional[MapPropertiesDialog] = None
169
171
  self.tileset_widget: Optional[TileSelector] = None
170
172
  self.layer_widget: Optional[LayerSelector] = None
171
173
  self.tile_grid_widget: Optional[TileGrid] = None
@@ -231,6 +233,7 @@ class Editor:
231
233
  center_y = (self.height - 400) // 2
232
234
  self.map_setup_widget = MapSetup(self, Rect(center_x, center_y, 400, 400))
233
235
  self.map_setup_widget.visible = False
236
+ self.map_properties_dialog = MapPropertiesDialog(self, Rect(center_x, center_y, 400, 260))
234
237
 
235
238
  def open_file_manager(
236
239
  self,
@@ -542,6 +545,8 @@ class Editor:
542
545
  center_x = (width - 400) // 2
543
546
  center_y = (height - 400) // 2
544
547
  self.map_setup_widget.resize(Rect(center_x, center_y, 400, 400))
548
+ if self.map_properties_dialog:
549
+ self.map_properties_dialog.resize(Rect(center_x, center_y, 400, 260))
545
550
 
546
551
  def toggle_auto_autotile(self):
547
552
  self.autotile_mode = not self.autotile_mode
@@ -555,6 +560,12 @@ class Editor:
555
560
  return
556
561
  self.map_setup_widget.visible = True
557
562
 
563
+ def open_map_properties(self):
564
+ if self.map_properties_dialog is None:
565
+ logger.warning({"msg": "map_properties_dialog is not initialized"})
566
+ return
567
+ self.map_properties_dialog.open()
568
+
558
569
  def toggle_autotiler(self):
559
570
  if self.autotiler.visible:
560
571
  self.autotiler.hide()
@@ -919,6 +930,10 @@ class Editor:
919
930
  if self.map_setup_widget.handle_event(event):
920
931
  continue
921
932
 
933
+ if self.map_properties_dialog and self.map_properties_dialog.visible:
934
+ if self.map_properties_dialog.handle_event(event):
935
+ continue
936
+
922
937
  if self.property_editor and self.property_editor.active:
923
938
  if self.property_editor.handle_event(event):
924
939
  continue
@@ -1089,6 +1104,9 @@ class Editor:
1089
1104
  self.screen.blit(overlay, (0, 0))
1090
1105
  self.map_setup_widget.draw(self.screen)
1091
1106
 
1107
+ if self.map_properties_dialog and self.map_properties_dialog.visible:
1108
+ self.map_properties_dialog.draw(self.screen)
1109
+
1092
1110
  if self.save_input.active:
1093
1111
  self.save_input.draw(self.screen)
1094
1112
  if self.tileset_type_dialog.active:
@@ -40,6 +40,7 @@ class Tilemap:
40
40
  self.map_size = (50, 50)
41
41
  self.initial_map_size = (50, 50)
42
42
  self.initialized = False
43
+ self.render_scale = 1.0
43
44
 
44
45
  self.active_project_path: Optional[Path] = None
45
46
  self.history = HistoryManager()
@@ -59,11 +60,12 @@ class Tilemap:
59
60
  if active_layer:
60
61
  active_layer.tiles = value
61
62
 
62
- def init_size(self, tile_size: "TCoor", map_size: "TCoor"):
63
+ def init_size(self, tile_size: "TCoor", map_size: "TCoor", render_scale: float = 1.0):
63
64
  self.tile_size = tile_size
64
65
  self.map_size = map_size
65
66
  self.initial_map_size = map_size # Store what user initially setup
66
67
  self.initialized = True
68
+ self.render_scale = render_scale
67
69
  self.active_project_path = None
68
70
 
69
71
  # Clear and create default layer
@@ -85,6 +87,7 @@ class Tilemap:
85
87
  "active_layer_idx": self.layer_manager.active_layer_idx,
86
88
  "tile_size": self.tile_size,
87
89
  "map_size": self.map_size,
90
+ "render_scale": self.render_scale,
88
91
  }
89
92
  self.history.save_state(state, description)
90
93
 
@@ -101,6 +104,7 @@ class Tilemap:
101
104
  "active_layer_idx": self.layer_manager.active_layer_idx,
102
105
  "tile_size": self.tile_size,
103
106
  "map_size": self.map_size,
107
+ "render_scale": self.render_scale,
104
108
  }
105
109
  prev_state = self.history.undo(current_state)
106
110
  if prev_state:
@@ -119,6 +123,7 @@ class Tilemap:
119
123
  "active_layer_idx": self.layer_manager.active_layer_idx,
120
124
  "tile_size": self.tile_size,
121
125
  "map_size": self.map_size,
126
+ "render_scale": self.render_scale,
122
127
  }
123
128
  next_state = self.history.redo(current_state)
124
129
  if next_state:
@@ -181,6 +186,7 @@ class Tilemap:
181
186
  self.layer_manager.active_layer_idx = state["active_layer_idx"]
182
187
  self.tile_size = state["tile_size"]
183
188
  self.map_size = state["map_size"]
189
+ self.render_scale = state.get("render_scale", 1.0)
184
190
 
185
191
  if hasattr(self.editor, "autotiler"):
186
192
  designer = self.editor.autotiler
@@ -269,6 +275,7 @@ class Tilemap:
269
275
  )
270
276
  ),
271
277
  "initial_map_size": serialize_point(self.initial_map_size),
278
+ "render_scale": self.render_scale,
272
279
  "version": "1.1",
273
280
  },
274
281
  "resources": {"tilesets": []},
@@ -470,6 +477,7 @@ class Tilemap:
470
477
  self.initial_map_size = deserialize_point(self.initial_map_size)
471
478
  else:
472
479
  self.initial_map_size = self.map_size
480
+ self.render_scale = float(payload["meta"].get("render_scale", 1.0))
473
481
  except (KeyError, ValueError) as e:
474
482
  raise ValueError(f"Error loading map metadata: {e}") from e
475
483
 
@@ -42,6 +42,10 @@ def init_settings(generate_main: bool = False) -> None:
42
42
 
43
43
  print(f"Created settings.json at {settings_file}")
44
44
 
45
+ data_dir = base_path / settings["data_path"]
46
+ data_dir.mkdir(parents=True, exist_ok=True)
47
+ print(f"Created data directory: {data_dir}")
48
+
45
49
  if generate_main:
46
50
  generate_main_file()
47
51
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-editor
3
- Version: 3.1.2
3
+ Version: 3.1.4
4
4
  Summary: Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools
5
5
  Author: tilemap editor contributors
6
6
  License: Proprietary
@@ -153,6 +153,7 @@ src/widgets/autotiler.py
153
153
  src/widgets/filemanager.py
154
154
  src/widgets/input.py
155
155
  src/widgets/layer_selector.py
156
+ src/widgets/map_properties.py
156
157
  src/widgets/mapsetup.py
157
158
  src/widgets/regex_automap_designer.py
158
159
  src/widgets/tile_grid.py
@@ -174,4 +175,5 @@ src/widgets/ui/toolbar.py
174
175
  src/widgets/ui/tooltip.py
175
176
  tests/test_collision_layer_mask.py
176
177
  tests/test_collision_layer_sidebar.py
177
- tests/test_project_paths.py
178
+ tests/test_project_paths.py
179
+ tests/test_render_scale.py
@@ -0,0 +1,133 @@
1
+ import pygame
2
+ from typing import TYPE_CHECKING
3
+ from pygame import Rect
4
+
5
+ from .input import BaseTextInput
6
+
7
+ if TYPE_CHECKING:
8
+ from editor import Editor
9
+
10
+
11
+ COLOR_BG = (45, 45, 50)
12
+ COLOR_BORDER = (80, 80, 80)
13
+ COLOR_ACCENT = (60, 100, 160)
14
+ COLOR_TEXT = (220, 220, 220)
15
+ COLOR_ERROR = (200, 60, 60)
16
+
17
+
18
+ class MapPropertiesDialog:
19
+ def __init__(self, editor: "Editor", center_rect: Rect):
20
+ self.editor = editor
21
+ self.rect = center_rect
22
+ self.visible = False
23
+ self.error_message = ""
24
+
25
+ self.render_scale_input = BaseTextInput(
26
+ Rect(self.rect.x + 20, self.rect.y + 60, self.rect.width - 40, 60),
27
+ "Render Scale",
28
+ "render_scale",
29
+ str(editor.tilemap.render_scale),
30
+ allowed_chars="0123456789.",
31
+ )
32
+
33
+ self.btn_save = Rect(self.rect.centerx - 130, self.rect.bottom - 50, 120, 35)
34
+ self.btn_cancel = Rect(self.rect.centerx + 10, self.rect.bottom - 50, 120, 35)
35
+ self.font = pygame.font.SysFont("Arial", 20, bold=True)
36
+ self.font_info = pygame.font.SysFont("Arial", 14)
37
+
38
+ def open(self):
39
+ self.render_scale_input.text = str(self.editor.tilemap.render_scale)
40
+ self.render_scale_input.cursor_pos = len(self.render_scale_input.text)
41
+ self.render_scale_input.is_focused = False
42
+ self.error_message = ""
43
+ self.visible = True
44
+
45
+ def resize(self, center_rect: Rect):
46
+ self.rect = center_rect
47
+ self.render_scale_input.rect_area = Rect(
48
+ self.rect.x + 20, self.rect.y + 60, self.rect.width - 40, 60
49
+ )
50
+ self.render_scale_input.rect_input = Rect(
51
+ self.render_scale_input.rect_area.x,
52
+ self.render_scale_input.rect_area.y + 20,
53
+ self.render_scale_input.rect_area.width,
54
+ 30,
55
+ )
56
+ self.btn_save = Rect(self.rect.centerx - 130, self.rect.bottom - 50, 120, 35)
57
+ self.btn_cancel = Rect(self.rect.centerx + 10, self.rect.bottom - 50, 120, 35)
58
+
59
+ def handle_event(self, event: pygame.event.Event) -> bool:
60
+ if not self.visible:
61
+ return False
62
+
63
+ if event.type == pygame.MOUSEBUTTONDOWN:
64
+ if event.button == 1:
65
+ if self.btn_save.collidepoint(event.pos):
66
+ self.submit()
67
+ return True
68
+ if self.btn_cancel.collidepoint(event.pos):
69
+ self.visible = False
70
+ return True
71
+
72
+ if event.type == pygame.KEYDOWN:
73
+ if event.key == pygame.K_ESCAPE:
74
+ self.visible = False
75
+ return True
76
+ if event.key == pygame.K_RETURN:
77
+ self.submit()
78
+ return True
79
+
80
+ self.render_scale_input.handle_event(event)
81
+ return True
82
+
83
+ def submit(self):
84
+ try:
85
+ raw = self.render_scale_input.text.strip()
86
+ if not raw:
87
+ raise ValueError("Render Scale is required")
88
+ value = float(raw)
89
+ if value <= 0:
90
+ raise ValueError("Render Scale must be greater than 0")
91
+ self.editor.tilemap.render_scale = value
92
+ self.editor.notifications.notify(f"Render Scale set to {value}")
93
+ self.visible = False
94
+ except ValueError as e:
95
+ self.error_message = str(e)
96
+
97
+ def draw(self, screen: pygame.Surface):
98
+ if not self.visible:
99
+ return
100
+
101
+ overlay = pygame.Surface(
102
+ (self.editor.width, self.editor.height), pygame.SRCALPHA
103
+ )
104
+ overlay.fill((0, 0, 0, 180))
105
+ screen.blit(overlay, (0, 0))
106
+
107
+ pygame.draw.rect(screen, COLOR_BG, self.rect, border_radius=8)
108
+ pygame.draw.rect(screen, COLOR_BORDER, self.rect, 2, border_radius=8)
109
+
110
+ title = self.font.render("Map Properties", True, COLOR_TEXT)
111
+ screen.blit(title, (self.rect.x + 20, self.rect.y + 15))
112
+
113
+ # Show read-only info about tile and map size
114
+ tm = self.editor.tilemap
115
+ info = f"Tile Size: {tm.tile_size[0]}x{tm.tile_size[1]} | Map Size: {tm.map_size[0]}x{tm.map_size[1]}"
116
+ info_surf = self.font_info.render(info, True, (150, 150, 150))
117
+ screen.blit(info_surf, (self.rect.x + 20, self.rect.y + 42))
118
+
119
+ self.render_scale_input.draw(screen)
120
+
121
+ for btn, text, col in [
122
+ (self.btn_save, "Apply", (40, 150, 80)),
123
+ (self.btn_cancel, "Cancel", (150, 60, 60)),
124
+ ]:
125
+ pygame.draw.rect(screen, col, btn, border_radius=4)
126
+ txt_surf = self.font.render(text, True, COLOR_TEXT)
127
+ screen.blit(txt_surf, txt_surf.get_rect(center=btn.center))
128
+
129
+ if self.error_message:
130
+ err = pygame.font.SysFont("Arial", 12).render(
131
+ self.error_message, True, COLOR_ERROR
132
+ )
133
+ screen.blit(err, (self.rect.x + 20, self.btn_save.y - 20))
@@ -44,6 +44,12 @@ class TileGrid:
44
44
  def tile_size(self):
45
45
  return self.editor.tilemap.tile_size
46
46
 
47
+ @property
48
+ def effective_tile_size(self):
49
+ tw, th = self.editor.tilemap.tile_size
50
+ rs = self.editor.tilemap.render_scale
51
+ return (tw * rs, th * rs)
52
+
47
53
  def screen_to_world(self, pos: Tuple[int, int]) -> Tuple[int, int]:
48
54
  wx = (pos[0] - self.rect.x) / self.zoom_level + self.scroll_x
49
55
  wy = (pos[1] - self.rect.y) / self.zoom_level + self.scroll_y
@@ -51,8 +57,8 @@ class TileGrid:
51
57
 
52
58
  def get_grid_pos(self, pos: Tuple[int, int]) -> Tuple[int, int]:
53
59
  wx, wy = self.screen_to_world(pos)
54
- tile_w, tile_h = self.tile_size
55
- return int(wx // tile_w), int(wy // tile_h)
60
+ eff_w, eff_h = self.effective_tile_size
61
+ return int(wx // eff_w), int(wy // eff_h)
56
62
 
57
63
  def update(self):
58
64
  event_blocked = not self.editor.save_input.active
@@ -117,8 +123,9 @@ class TileGrid:
117
123
  self.scroll_y = 0
118
124
 
119
125
  def fit_to_map(self):
120
- world_w = self.editor.tilemap.map_size[0] * self.tile_size[0]
121
- world_h = self.editor.tilemap.map_size[1] * self.tile_size[1]
126
+ eff_w, eff_h = self.effective_tile_size
127
+ world_w = self.editor.tilemap.map_size[0] * eff_w
128
+ world_h = self.editor.tilemap.map_size[1] * eff_h
122
129
  if world_w <= 0 or world_h <= 0:
123
130
  return
124
131
  zoom_x = self.rect.width / world_w
@@ -129,8 +136,9 @@ class TileGrid:
129
136
 
130
137
  def clamp_view(self):
131
138
  self.zoom_level = max(self.min_zoom, min(self.max_zoom, self.zoom_level))
132
- world_w = self.editor.tilemap.map_size[0] * self.tile_size[0]
133
- world_h = self.editor.tilemap.map_size[1] * self.tile_size[1]
139
+ eff_w, eff_h = self.effective_tile_size
140
+ world_w = self.editor.tilemap.map_size[0] * eff_w
141
+ world_h = self.editor.tilemap.map_size[1] * eff_h
134
142
  view_w = self.rect.width / self.zoom_level
135
143
  view_h = self.rect.height / self.zoom_level
136
144
 
@@ -631,16 +639,18 @@ class TileGrid:
631
639
  if not self.hover_cell:
632
640
  return
633
641
 
642
+ eff_w, eff_h = self.effective_tile_size
643
+
634
644
  if is_erasing:
635
645
  # Eraser preview for tiles: show a red box based on eraser_size
636
646
  screen_x = (
637
- self.hover_cell[0] * tile_w - self.scroll_x
647
+ self.hover_cell[0] * eff_w - self.scroll_x
638
648
  ) * self.zoom_level + self.rect.x
639
649
  screen_y = (
640
- self.hover_cell[1] * tile_h - self.scroll_y
650
+ self.hover_cell[1] * eff_h - self.scroll_y
641
651
  ) * self.zoom_level + self.rect.y
642
- size_w = int(tile_w * self.eraser_size * self.zoom_level)
643
- size_h = int(tile_h * self.eraser_size * self.zoom_level)
652
+ size_w = int(eff_w * self.eraser_size * self.zoom_level)
653
+ size_h = int(eff_h * self.eraser_size * self.zoom_level)
644
654
  dest_rect = Rect(screen_x, screen_y, size_w, size_h)
645
655
  pygame.draw.rect(screen, (255, 50, 50), dest_rect, 2)
646
656
  return
@@ -654,14 +664,14 @@ class TileGrid:
654
664
  row = self.hover_cell[1] + y_off
655
665
 
656
666
  screen_x = (
657
- col * tile_w - self.scroll_x
667
+ col * eff_w - self.scroll_x
658
668
  ) * self.zoom_level + self.rect.x
659
669
  screen_y = (
660
- row * tile_h - self.scroll_y
670
+ row * eff_h - self.scroll_y
661
671
  ) * self.zoom_level + self.rect.y
662
672
 
663
- dest_w = int(tile_w * self.zoom_level)
664
- dest_h = int(tile_h * self.zoom_level)
673
+ dest_w = int(eff_w * self.zoom_level)
674
+ dest_h = int(eff_h * self.zoom_level)
665
675
  dest_rect = Rect(screen_x, screen_y, dest_w, dest_h)
666
676
 
667
677
  pygame.draw.rect(screen, (255, 255, 255), dest_rect, 1)
@@ -683,12 +693,12 @@ class TileGrid:
683
693
  pass
684
694
 
685
695
  def _draw_grid(self, screen):
686
- tile_w, tile_h = self.tile_size
696
+ eff_w, eff_h = self.effective_tile_size
687
697
  map_w, map_h = self.editor.tilemap.map_size
688
698
 
689
699
  # World coordinates of map boundaries
690
- map_world_w = map_w * tile_w
691
- map_world_h = map_h * tile_h
700
+ map_world_w = map_w * eff_w
701
+ map_world_h = map_h * eff_h
692
702
 
693
703
  # Screen coordinates of map top-left
694
704
  map_screen_x = (0 - self.scroll_x) * self.zoom_level + self.rect.x
@@ -703,15 +713,15 @@ class TileGrid:
703
713
  visible_world_w = self.rect.width / self.zoom_level
704
714
  visible_world_h = self.rect.height / self.zoom_level
705
715
 
706
- start_col = max(0, int(self.scroll_x // tile_w))
707
- end_col = min(map_w, int((self.scroll_x + visible_world_w) // tile_w) + 1)
716
+ start_col = max(0, int(self.scroll_x // eff_w))
717
+ end_col = min(map_w, int((self.scroll_x + visible_world_w) // eff_w) + 1)
708
718
 
709
- start_row = max(0, int(self.scroll_y // tile_h))
710
- end_row = min(map_h, int((self.scroll_y + visible_world_h) // tile_h) + 1)
719
+ start_row = max(0, int(self.scroll_y // eff_h))
720
+ end_row = min(map_h, int((self.scroll_y + visible_world_h) // eff_h) + 1)
711
721
 
712
722
  # Draw vertical lines (at column positions)
713
723
  for col in range(start_col, end_col + 1):
714
- x = (col * tile_w - self.scroll_x) * self.zoom_level + self.rect.x
724
+ x = (col * eff_w - self.scroll_x) * self.zoom_level + self.rect.x
715
725
  # Line goes from top of map to bottom of map (clipping handled by surface clip)
716
726
  pygame.draw.line(
717
727
  screen,
@@ -722,7 +732,7 @@ class TileGrid:
722
732
 
723
733
  # Draw horizontal lines (at row positions)
724
734
  for row in range(start_row, end_row + 1):
725
- y = (row * tile_h - self.scroll_y) * self.zoom_level + self.rect.y
735
+ y = (row * eff_h - self.scroll_y) * self.zoom_level + self.rect.y
726
736
  # Line goes from left of map to right of map
727
737
  pygame.draw.line(
728
738
  screen,
@@ -782,20 +792,21 @@ class TileGrid:
782
792
  return
783
793
 
784
794
  tile_w, tile_h = self.tile_size
795
+ rs = tilemap.render_scale
796
+ eff_w = tile_w * rs
797
+ eff_h = tile_h * rs
798
+
785
799
  map_w, map_h = tilemap.map_size
786
800
 
787
- # visible world bounds
801
+ # visible world bounds (in effective world space)
788
802
  visible_world_w = self.rect.width / self.zoom_level
789
803
  visible_world_h = self.rect.height / self.zoom_level
790
804
 
791
- start_col = max(0, int(self.scroll_x // tile_w))
792
- end_col = min(map_w, int((self.scroll_x + visible_world_w) // tile_w) + 1)
793
-
794
- start_row = max(0, int(self.scroll_y // tile_h))
795
- end_row = min(map_h, int((self.scroll_y + visible_world_h) // tile_h) + 1)
805
+ start_col = max(0, int(self.scroll_x // eff_w))
806
+ end_col = min(map_w, int((self.scroll_x + visible_world_w) // eff_w) + 1)
796
807
 
797
- # Debug boundaries
798
- # print(f"DEBUG: Rendering rows {start_row}-{end_row}, cols {start_col}-{end_col} | Scroll: ({self.scroll_x}, {self.scroll_y}) | Zoom: {self.zoom_level}")
808
+ start_row = max(0, int(self.scroll_y // eff_h))
809
+ end_row = min(map_h, int((self.scroll_y + visible_world_h) // eff_h) + 1)
799
810
 
800
811
  assert self.editor.tileset_widget is not None
801
812
  tileset_map = self.editor.tileset_widget.tileset_map
@@ -836,29 +847,28 @@ class TileGrid:
836
847
  variant_id = tile["variant"]
837
848
  sheet_w = base_surf.get_width()
838
849
 
850
+ # Source rect always uses logical tile size
839
851
  sheet_cols = sheet_w // tile_w
840
-
841
852
  src_x = (variant_id % sheet_cols) * tile_w
842
853
  src_y = (variant_id // sheet_cols) * tile_h
843
854
  src_rect = Rect(src_x, src_y, tile_w, tile_h)
844
855
 
856
+ # Dest position uses effective (scaled) tile size
845
857
  dest_x = (
846
- (x * tile_w - self.scroll_x) * self.zoom_level
858
+ (x * eff_w - self.scroll_x) * self.zoom_level
847
859
  + self.rect.x
848
860
  + draw_offset_x
849
861
  )
850
862
  dest_y = (
851
- (y * tile_h - self.scroll_y) * self.zoom_level
863
+ (y * eff_h - self.scroll_y) * self.zoom_level
852
864
  + self.rect.y
853
865
  + draw_offset_y
854
866
  )
855
867
 
856
- # Scale if zooming
857
- if self.zoom_level != 1.0:
858
- scaled_w = int(tile_w * self.zoom_level)
859
- scaled_h = int(tile_h * self.zoom_level)
860
-
861
- # Bounds check
868
+ # Scale if zoomed or render_scaled
869
+ if self.zoom_level != 1.0 or rs != 1.0:
870
+ scaled_w = int(eff_w * self.zoom_level)
871
+ scaled_h = int(eff_h * self.zoom_level)
862
872
  if base_surf.get_rect().contains(src_rect):
863
873
  sub = base_surf.subsurface(src_rect)
864
874
  scaled_sub = pygame.transform.scale(
@@ -895,19 +905,19 @@ class TileGrid:
895
905
  src_rect = Rect(src_x, src_y, obj_w, obj_h)
896
906
 
897
907
  dest_x = (
898
- (obj_x - self.scroll_x) * self.zoom_level
908
+ (obj_x * rs - self.scroll_x) * self.zoom_level
899
909
  + self.rect.x
900
910
  + draw_offset_x
901
911
  )
902
912
  dest_y = (
903
- (obj_y - self.scroll_y) * self.zoom_level
913
+ (obj_y * rs - self.scroll_y) * self.zoom_level
904
914
  + self.rect.y
905
915
  + draw_offset_y
906
916
  )
907
917
 
908
- if self.zoom_level != 1.0:
909
- scaled_w = int(obj_w * self.zoom_level)
910
- scaled_h = int(obj_h * self.zoom_level)
918
+ if self.zoom_level != 1.0 or rs != 1.0:
919
+ scaled_w = int(obj_w * rs * self.zoom_level)
920
+ scaled_h = int(obj_h * rs * self.zoom_level)
911
921
  if base_surf.get_rect().contains(src_rect):
912
922
  sub = base_surf.subsurface(src_rect)
913
923
  scaled_sub = pygame.transform.scale(
@@ -44,6 +44,7 @@ class MenuBar:
44
44
  MenuAction(
45
45
  "Save As...", self.editor.open_save_as_dialog, "Ctrl+Shift+S"
46
46
  ),
47
+ MenuAction("Map Properties", self.editor.open_map_properties),
47
48
  MenuAction("Exit", self.editor.exit_editor),
48
49
  ],
49
50
  ),