tilemap-editor 4.3.7__tar.gz → 4.3.9__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.
- tilemap_editor-4.3.9/CHANGELOG.md +239 -0
- {tilemap_editor-4.3.7/src/tilemap_editor.egg-info → tilemap_editor-4.3.9}/PKG-INFO +3 -1
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/pyproject.toml +36 -7
- tilemap_editor-4.3.9/src/plugins/sprite_editor/camera.py +97 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/clipboard.py +74 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/commands.py +248 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/document.py +352 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/editor.py +658 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/overlays.py +155 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_editor/region_export.py +3 -3
- tilemap_editor-4.3.9/src/plugins/sprite_editor/selection.py +99 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/tools.py +745 -0
- tilemap_editor-4.3.9/src/plugins/sprite_editor/viewport.py +179 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/editor.py +12 -5
- tilemap_editor-4.3.9/src/run.py +3 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9/src/tilemap_editor.egg-info}/PKG-INFO +3 -1
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor.egg-info/SOURCES.txt +15 -1
- tilemap_editor-4.3.9/src/tilemap_editor.egg-info/requires.txt +4 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/font_manager.py +15 -1
- tilemap_editor-4.3.9/src/utils/natural_sort.py +29 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/filemanager.py +4 -3
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/region_selector.py +20 -6
- tilemap_editor-4.3.9/tests/test_natural_sort.py +80 -0
- tilemap_editor-4.3.9/tests/test_sprite_editor_commands.py +271 -0
- tilemap_editor-4.3.9/tests/test_sprite_editor_interaction.py +610 -0
- tilemap_editor-4.3.9/tests/test_sprite_editor_models.py +380 -0
- tilemap_editor-4.3.7/src/plugins/sprite_editor/editor.py +0 -631
- tilemap_editor-4.3.7/src/tilemap_editor.egg-info/requires.txt +0 -1
- tilemap_editor-4.3.7/src/widgets/spritesheet_grid.py +0 -707
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/LICENSE +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/MANIFEST.in +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/README.md +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/check.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/checked.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/close.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/error.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/file.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/filedead.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/fit.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/folder.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/grid.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/image.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/info.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/load.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/loop.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/pan.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/pause.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/pencil.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/play.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/plus.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/radio.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/reset.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/save.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/stop.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/tileset.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/warning.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/setup.cfg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/constants.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/event_map.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/layers.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/main.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/node_manager.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/nodes.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/models.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/protocols.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/shape_editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/character_collision/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/object_tileset_collision/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/object_tileset_collision/editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/object_tileset_collision/models.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/object_tileset_collision/protocols.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/object_tileset_collision/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/__main__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/clipboard_util.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/frame_picker.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/models.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/preview.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/protocols.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/runtime_load.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/timeline.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_animation/validation.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_editor/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_editor/dialogs.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/sprite_editor/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/collision_painter.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/models.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/protocols.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/plugins/tileset_collision/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/standalone_automap.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/standalone_error_console.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/standalone_filemanager.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/standalone_image_viewer.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/__main__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/check.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/checked.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/close.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/error.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/file.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/fit.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/fold_down_arrow.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/folder.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/gear.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/grid.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/image.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/info.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/load.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/loop.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/miniobj.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/pan.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/pause.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/play.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/plus.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/radio.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/reset.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/save.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/stop.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/tileset.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/unfold_right_arrow.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/warning.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/cli.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/main.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor/settings.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/tilemap_editor.egg-info/top_level.txt +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/ttypes/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/ttypes/tilemap.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/editor_preference.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/error_handler.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/history.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/icon_manager.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/icons_cache.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/log_capture.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/project_paths.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/property_suggestions.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/serialization.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/standalone.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/utils/validation.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/__init__.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/automap_models.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/autotile_template.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/autotiler.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/input.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/layer_selector.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/map_properties.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/mapsetup.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/particle_presets.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/particle_system.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/regex_automap_designer.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/tile_grid.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/tile_selector.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/button.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/checkbox.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/collision_layer_mask.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/collision_layer_sidebar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/confirm_dialog.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/dialog_base.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/drag_tracker.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/draw_utils.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/fileinput.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/label.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/layer_type_dialog.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/menubar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/mode_indicator.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/node_editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/node_selector.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/notification.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/particle_config_dialog.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/property_editor.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/resize_map_dialog.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/scrollbar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/sidebar_container.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/splitter.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/status_bar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/theme.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/tileset_type_dialog.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/toast.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/tool_manager.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/toolbar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/tooltip.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/ui/tree_widget.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/src/widgets/widget_base.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_animation_library_grid_offset.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_collision_layer_mask.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_collision_layer_sidebar.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_drag_tracker.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_editor_pan_mode.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_gid_collision.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_layers_autotile.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_map_resize_model.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_project_paths.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_render_scale.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_serialization_regression.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_sprite_animation_editor_grid.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_tile_grid_selection.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_tile_selector_pick.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_tilemap_save.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_timeline_invalidate_cache.py +0 -0
- {tilemap_editor-4.3.7 → tilemap_editor-4.3.9}/tests/test_toolbar_tools.py +0 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
<!-- towncrier release notes start -->
|
|
4
|
+
# tilemap_editor 4.3.9 (2026-08-04)
|
|
5
|
+
|
|
6
|
+
## Bug Fixes
|
|
7
|
+
|
|
8
|
+
- Fixed tileset collision editor tile picking when the tileset is centered in the selector: mouse clicks now map to the correct tile after the centering offset is applied.
|
|
9
|
+
- Fixed region selector coordinate conversion (screen↔image) to account for the centered image when it is smaller than the viewport, so drawing, selection, and drag operations stay aligned.
|
|
10
|
+
|
|
11
|
+
# tilemap_editor 4.3.8 (2026-08-04)
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Sprite editor: two-row grouped toolbar, natural filename sorting on multi-sheet loads, and a Stack V/H toggle for vertical or horizontal sheet stacking.
|
|
16
|
+
- Rewrote the sprite editor around a command stack with single-canvas undo memory: shared clipboard with relative-tile pasting that survives scale/grid changes, drag-move and rubber-band selection that can expand the canvas, object-selection undo restore, and a pure camera with cursor-anchored zoom. (sprite-editor-v2)
|
|
17
|
+
|
|
18
|
+
## Bug Fixes
|
|
19
|
+
|
|
20
|
+
- Fixed sprite editor undo history corruption from shared region references, viewport cache staleness after region edits, coordinate errors after loading new sheets, index lookup failures with negative-origin canvases, and canvas expansion failures for negative cell coordinates
|
|
21
|
+
- Fixed sprite editor paste landing in wrong cells after a scale or grid-size change (clipboard now stores relative tile offsets), paste/cut double-clipboard split-brain, paste preview lacking pixel ghost, and moves/pastes past the canvas edge now expanding the canvas. (sprite-editor-paste-fixes)
|
|
22
|
+
- Fixed sprite editor theming and camera gestures: the canvas, header bar, grid lines, and overlays now use theme colors/fonts instead of hardcoded dark values (canvas no longer stays black on light themes), the canvas header no longer covers the sheet's top rows, and mouse wheel zoom/pan work again with the same 30px/1.12x behavior as the old editor. (sprite-editor-theme-wheel)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## [4.3.7] - 2026-07-30
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
- Replaced buggy auto-resize system with explicit offset + size model for widget positioning
|
|
30
|
+
|
|
31
|
+
## [4.3.6] - 2026-07-26
|
|
32
|
+
|
|
33
|
+
### Features
|
|
34
|
+
|
|
35
|
+
- Added tileset properties completion
|
|
36
|
+
- Updated README with credits and Python version info
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
- Fixed UX bugs and node prescale problem
|
|
41
|
+
|
|
42
|
+
## [4.3.4] - 2026-07-24
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
- Added y-sort option for tile rendering order
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- Restructured codebase with enhanced UI components and preference persistence
|
|
51
|
+
- Improved shape editor UX with theme integration and viewport centering
|
|
52
|
+
|
|
53
|
+
## [4.3.1] - 2026-07-17
|
|
54
|
+
|
|
55
|
+
### Bug Fixes
|
|
56
|
+
|
|
57
|
+
- Fixed create folder blocker in file manager
|
|
58
|
+
- Adjusted input field inner size
|
|
59
|
+
|
|
60
|
+
## [4.3.0] - 2026-07-16
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- Refactored toolbar and tool system with ToolManager/ToolKind central state
|
|
65
|
+
- Replaced editor boolean flags with centralized ToolManager mutual exclusion
|
|
66
|
+
- CLI `--theme` support
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- Icon-only compact toolbar (28px) with separator bars and tooltips
|
|
71
|
+
|
|
72
|
+
### Bug Fixes
|
|
73
|
+
|
|
74
|
+
- Fixed node and object render_scale bugs (selection rect, move offset, hit-test)
|
|
75
|
+
|
|
76
|
+
## [4.2.0] - 2026-07-15
|
|
77
|
+
|
|
78
|
+
### Features
|
|
79
|
+
|
|
80
|
+
- Separated autotile group from layer tile data
|
|
81
|
+
- Added global ID system for tiles
|
|
82
|
+
- Re-added autotile early-out optimization
|
|
83
|
+
- Added auto-detect group from variant
|
|
84
|
+
|
|
85
|
+
## [4.1.0] - 2026-07-13
|
|
86
|
+
|
|
87
|
+
### Features
|
|
88
|
+
|
|
89
|
+
- Added .tmx file open/save support with TMX-to-dict converter
|
|
90
|
+
|
|
91
|
+
### Bug Fixes
|
|
92
|
+
|
|
93
|
+
- Fixed alignment of tmx converter with parser fixes (mask, props, gid count)
|
|
94
|
+
|
|
95
|
+
### Misc
|
|
96
|
+
|
|
97
|
+
- Formatted code and applied unsafe fixes with ruff
|
|
98
|
+
|
|
99
|
+
## [4.0.0] - 2026-07-11
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- Refactored widget theme system with dynamic COLORS proxy, SHAPE, FONTS, SPACING
|
|
104
|
+
- Applied theme from settings.json with custom theme loading support
|
|
105
|
+
- Added theme-aware WidgetBase with box model (padding, border, content_rect)
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
|
|
109
|
+
- CLI `--theme` argument accepting name or path to .json file
|
|
110
|
+
|
|
111
|
+
### Bug Fixes
|
|
112
|
+
|
|
113
|
+
- Fixed tile grid issues and serialization
|
|
114
|
+
- Improved node ui/ux with ctrl/cmd+shift+n toggle for node manager
|
|
115
|
+
- Improved particle rendering
|
|
116
|
+
- Temporarily disabled autotile propagation on collision paint
|
|
117
|
+
|
|
118
|
+
## [3.3.8] - 2026-07-01
|
|
119
|
+
|
|
120
|
+
### Bug Fixes
|
|
121
|
+
|
|
122
|
+
- Replaced smoothscale with scale for broader compatibility
|
|
123
|
+
- Fixed fallback to scale when smoothscale fails on non-32bit surfaces
|
|
124
|
+
- Replaced unicode characters with SVG icons for frame nav and onion skin
|
|
125
|
+
|
|
126
|
+
## [3.3.4] - 2026-06-17
|
|
127
|
+
|
|
128
|
+
### Features
|
|
129
|
+
|
|
130
|
+
- Enhanced sprite editor with cut/copy/paste functionality
|
|
131
|
+
- Added checkbox widget for UI controls
|
|
132
|
+
|
|
133
|
+
### Documentation
|
|
134
|
+
|
|
135
|
+
- Added documentation for tilemap-editor (setup, project structure, architecture, usage)
|
|
136
|
+
|
|
137
|
+
## [3.3.3] - 2026-06-10
|
|
138
|
+
|
|
139
|
+
### Features
|
|
140
|
+
|
|
141
|
+
- Added particle system with 66 presets across 11 categories
|
|
142
|
+
- Added particle system editor integration with config dialog
|
|
143
|
+
- Added particle preview in TileGrid
|
|
144
|
+
|
|
145
|
+
### Bug Fixes
|
|
146
|
+
|
|
147
|
+
- Fixed propagation of negative grid offsets
|
|
148
|
+
- Fixed zero animation frame_stride guard
|
|
149
|
+
- Fixed preset dropdown refresh on node switch
|
|
150
|
+
- Fixed particle preview reset on config save
|
|
151
|
+
|
|
152
|
+
### Misc
|
|
153
|
+
|
|
154
|
+
- Added 'synchronize' type to PR agent workflow triggers
|
|
155
|
+
|
|
156
|
+
## [3.2.10] - 2026-06-07
|
|
157
|
+
|
|
158
|
+
### Bug Fixes
|
|
159
|
+
|
|
160
|
+
- Fixed tab click offset ignoring scroll_x
|
|
161
|
+
|
|
162
|
+
### Added
|
|
163
|
+
|
|
164
|
+
- Hover-only arrow buttons for tab navigation
|
|
165
|
+
|
|
166
|
+
## [3.2.9] - 2026-06-07
|
|
167
|
+
|
|
168
|
+
### Bug Fixes
|
|
169
|
+
|
|
170
|
+
- Fixed stride normalization — removed % stride normalization, auto-compute stride
|
|
171
|
+
- Fixed dialog UI overlap
|
|
172
|
+
|
|
173
|
+
## [3.2.8] - 2026-06-07
|
|
174
|
+
|
|
175
|
+
### Features
|
|
176
|
+
|
|
177
|
+
- Added node system with NodeManager, NodeSelector, NodeEditor, and TileGrid overlay
|
|
178
|
+
- Added lenient tileset loading with warn dialog instead of reject on size mismatch
|
|
179
|
+
|
|
180
|
+
### Bug Fixes
|
|
181
|
+
|
|
182
|
+
- Fixed layer rename text not visible during editing
|
|
183
|
+
- Fixed object layer position offset from render_scale
|
|
184
|
+
- Fixed capsule move icon and animation preview grid_offset
|
|
185
|
+
- Fixed layer rename Cmd+Backspace interaction
|
|
186
|
+
|
|
187
|
+
## [3.2.4] - 2026-06-04
|
|
188
|
+
|
|
189
|
+
### Features
|
|
190
|
+
|
|
191
|
+
- Added copy/paste collision shapes with toast feedback and painted tiles focus mode
|
|
192
|
+
- Added sprite editor integration with flip ghosting fix, tileset zoom, autotiler import fix
|
|
193
|
+
- Added auto-expand spritesheet canvas on paste overflow
|
|
194
|
+
- Added editable name field in character collision editor
|
|
195
|
+
- Added renaming support in character collision
|
|
196
|
+
- Added animation library loading and tool state management
|
|
197
|
+
- Added auto-propagation of collision shapes to auto-tile variant groups on save
|
|
198
|
+
|
|
199
|
+
### Bug Fixes
|
|
200
|
+
|
|
201
|
+
- Fixed animation rename shortcuts, path resolution, file input overflow, and dual-focus metadata fields
|
|
202
|
+
- Fixed sprite editor multi-row paste flattening and missing tile-size arg
|
|
203
|
+
- Fixed dynamic grid span
|
|
204
|
+
- Fixed L shortcut conflict with name input
|
|
205
|
+
|
|
206
|
+
### Misc
|
|
207
|
+
|
|
208
|
+
- Added unit tests
|
|
209
|
+
|
|
210
|
+
## [3.1.6] - 2026-05-21
|
|
211
|
+
|
|
212
|
+
### Bug Fixes
|
|
213
|
+
|
|
214
|
+
- Fixed NameError in save_map
|
|
215
|
+
- Fixed asymmetry in load path resolution
|
|
216
|
+
- Fixed path resolution in init
|
|
217
|
+
|
|
218
|
+
### Added
|
|
219
|
+
|
|
220
|
+
- Added render_scale to map properties with dialog UI and TileGrid support
|
|
221
|
+
- Added auto-creation of data directory on init
|
|
222
|
+
|
|
223
|
+
## [3.1.0] - 2026-05-18
|
|
224
|
+
|
|
225
|
+
### Features
|
|
226
|
+
|
|
227
|
+
- Added Godot-inspired physics layer (radio) + mask (checkbox) bit selector (16 layers)
|
|
228
|
+
- Added collision layer sidebar overlay with toggle/close/dim
|
|
229
|
+
- Added object tileset collision editor with region support
|
|
230
|
+
- Added reusable text input system with cursor, selection, and shortcuts
|
|
231
|
+
- Added project initialization, asset management, and data structure improvements
|
|
232
|
+
- Added theme support
|
|
233
|
+
- Added collision mask support
|
|
234
|
+
- Implemented event priority system and modal overlays in autotiler
|
|
235
|
+
|
|
236
|
+
### Changed
|
|
237
|
+
|
|
238
|
+
- Improved file manager path handling and directory initialization
|
|
239
|
+
- Improved tileset collision help panel and macOS HiDPI support
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-editor
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.9
|
|
4
4
|
Summary: Pygame tilemap editor with collision, animation, sprite & particle tools
|
|
5
5
|
Author: tilemap editor contributors
|
|
6
6
|
License: Proprietary
|
|
@@ -12,6 +12,8 @@ Requires-Python: >=3.11
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: pygame-ce>=2.5
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: towncrier; extra == "dev"
|
|
15
17
|
Dynamic: license-file
|
|
16
18
|
|
|
17
19
|
# tilemap-editor
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tilemap-editor"
|
|
7
|
-
version = "4.3.
|
|
7
|
+
version = "4.3.9"
|
|
8
8
|
description = "Pygame tilemap editor with collision, animation, sprite & particle tools"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -24,6 +24,41 @@ classifiers = [
|
|
|
24
24
|
tilemap-editor = "tilemap_editor.cli:main"
|
|
25
25
|
tilemap-anim-editor = "plugins.sprite_animation.standalone:main"
|
|
26
26
|
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
dev = ["towncrier"]
|
|
29
|
+
|
|
30
|
+
[tool.towncrier]
|
|
31
|
+
package = "tilemap_editor"
|
|
32
|
+
directory = "changes"
|
|
33
|
+
filename = "CHANGELOG.md"
|
|
34
|
+
start_string = "<!-- towncrier release notes start -->"
|
|
35
|
+
underlines = ["-", "~", "^"]
|
|
36
|
+
|
|
37
|
+
[[tool.towncrier.type]]
|
|
38
|
+
directory = "feature"
|
|
39
|
+
name = "Features"
|
|
40
|
+
showcontent = true
|
|
41
|
+
|
|
42
|
+
[[tool.towncrier.type]]
|
|
43
|
+
directory = "bugfix"
|
|
44
|
+
name = "Bug Fixes"
|
|
45
|
+
showcontent = true
|
|
46
|
+
|
|
47
|
+
[[tool.towncrier.type]]
|
|
48
|
+
directory = "doc"
|
|
49
|
+
name = "Documentation"
|
|
50
|
+
showcontent = true
|
|
51
|
+
|
|
52
|
+
[[tool.towncrier.type]]
|
|
53
|
+
directory = "removal"
|
|
54
|
+
name = "Deprecations and Removals"
|
|
55
|
+
showcontent = true
|
|
56
|
+
|
|
57
|
+
[[tool.towncrier.type]]
|
|
58
|
+
directory = "misc"
|
|
59
|
+
name = "Misc"
|
|
60
|
+
showcontent = true
|
|
61
|
+
|
|
27
62
|
[tool.setuptools]
|
|
28
63
|
package-dir = {"" = "src"}
|
|
29
64
|
include-package-data = true
|
|
@@ -62,9 +97,3 @@ namespaces = true
|
|
|
62
97
|
|
|
63
98
|
[tool.setuptools.exclude-package-data]
|
|
64
99
|
"*" = ["*.spec", "*.sh"]
|
|
65
|
-
|
|
66
|
-
# Keep data-files for backward compatibility (one release cycle)
|
|
67
|
-
[tool.setuptools.data-files]
|
|
68
|
-
"share/tilemap_editor/assets/icons" = ["assets/icons/*.svg"]
|
|
69
|
-
"share/tilemap_editor/assets/fonts/noto" = ["assets/fonts/noto/*.ttf"]
|
|
70
|
-
"share/tilemap_editor/assets/fonts/jetbrain-fonts" = ["assets/fonts/jetbrain-fonts/*.ttf"]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Pure camera math — world (document) <-> screen transforms.
|
|
2
|
+
|
|
3
|
+
No pygame imports: this module is fully usable and testable headlessly.
|
|
4
|
+
Holds viewport origin and scroll as plain floats; the viewport provides
|
|
5
|
+
the pygame-side rect/bilt machinery.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
MIN_ZOOM = 0.1
|
|
11
|
+
MAX_ZOOM = 16.0
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _clamp_zoom(value: float) -> float:
|
|
15
|
+
return max(MIN_ZOOM, min(MAX_ZOOM, value))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Camera:
|
|
19
|
+
"""One monotonic linear transform between document and screen space.
|
|
20
|
+
|
|
21
|
+
screen = (local - origin) * zoom + viewport_topleft + scroll
|
|
22
|
+
local = (screen - viewport_topleft - scroll) / zoom + origin
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
viewport_x: float = 0.0,
|
|
28
|
+
viewport_y: float = 0.0,
|
|
29
|
+
zoom: float = 1.0,
|
|
30
|
+
scroll_x: float = 0.0,
|
|
31
|
+
scroll_y: float = 0.0,
|
|
32
|
+
):
|
|
33
|
+
self.viewport_x = float(viewport_x)
|
|
34
|
+
self.viewport_y = float(viewport_y)
|
|
35
|
+
self._zoom = _clamp_zoom(float(zoom))
|
|
36
|
+
self.scroll_x = float(scroll_x)
|
|
37
|
+
self.scroll_y = float(scroll_y)
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def zoom(self) -> float:
|
|
41
|
+
return self._zoom
|
|
42
|
+
|
|
43
|
+
@zoom.setter
|
|
44
|
+
def zoom(self, value: float) -> None:
|
|
45
|
+
self._zoom = _clamp_zoom(float(value))
|
|
46
|
+
|
|
47
|
+
def world_to_screen(self, x: float, y: float) -> tuple[float, float]:
|
|
48
|
+
return (
|
|
49
|
+
self.viewport_x + self.scroll_x + x * self._zoom,
|
|
50
|
+
self.viewport_y + self.scroll_y + y * self._zoom,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def screen_to_world(self, sx: float, sy: float) -> tuple[float, float]:
|
|
54
|
+
if self._zoom <= 0:
|
|
55
|
+
return (0.0, 0.0)
|
|
56
|
+
return (
|
|
57
|
+
(sx - self.viewport_x - self.scroll_x) / self._zoom,
|
|
58
|
+
(sy - self.viewport_y - self.scroll_y) / self._zoom,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def fit(self, world_size: tuple[float, float], viewport_size: tuple[float, float]) -> None:
|
|
62
|
+
"""Zoom so the whole document fits the viewport, centered."""
|
|
63
|
+
ww, wh = world_size
|
|
64
|
+
vw, vh = viewport_size
|
|
65
|
+
if ww <= 0 or wh <= 0 or vw <= 0 or vh <= 0:
|
|
66
|
+
self.reset()
|
|
67
|
+
return
|
|
68
|
+
self._zoom = _clamp_zoom(min(vw / ww, vh / wh))
|
|
69
|
+
self.scroll_x = (vw - ww * self._zoom) / 2.0
|
|
70
|
+
self.scroll_y = (vh - wh * self._zoom) / 2.0
|
|
71
|
+
|
|
72
|
+
def reset(self) -> None:
|
|
73
|
+
"""100% zoom, document origin at the viewport top-left."""
|
|
74
|
+
self._zoom = 1.0
|
|
75
|
+
self.scroll_x = 0.0
|
|
76
|
+
self.scroll_y = 0.0
|
|
77
|
+
|
|
78
|
+
def zoom_at(self, screen_point: tuple[float, float], factor: float) -> None:
|
|
79
|
+
"""Zoom by factor while keeping the world point under the cursor fixed."""
|
|
80
|
+
sx, sy = screen_point
|
|
81
|
+
wx, wy = self.screen_to_world(sx, sy)
|
|
82
|
+
new_zoom = _clamp_zoom(self._zoom * factor)
|
|
83
|
+
if abs(new_zoom - self._zoom) < 1e-9:
|
|
84
|
+
return
|
|
85
|
+
self._zoom = new_zoom
|
|
86
|
+
self.scroll_x = sx - self.viewport_x - wx * self._zoom
|
|
87
|
+
self.scroll_y = sy - self.viewport_y - wy * self._zoom
|
|
88
|
+
|
|
89
|
+
def pan(self, dx: float, dy: float) -> None:
|
|
90
|
+
"""Scroll by a screen-space delta (content follows the cursor)."""
|
|
91
|
+
self.scroll_x += float(dx)
|
|
92
|
+
self.scroll_y += float(dy)
|
|
93
|
+
|
|
94
|
+
def world_to_screen_rect(self, x: float, y: float, w: float, h: float) -> tuple[float, float, float, float]:
|
|
95
|
+
"""Screen-space rect for a world-space rect (floats)."""
|
|
96
|
+
sx, sy = self.world_to_screen(x, y)
|
|
97
|
+
return (sx, sy, w * self._zoom, h * self._zoom)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Clipboard — layout-relative tile data, independent of the UI.
|
|
2
|
+
|
|
3
|
+
Fixes the old absolute-index clipboard (P5/P6): tiles are stored as
|
|
4
|
+
(dx, dy) offsets relative to the clipboard origin, plus a source
|
|
5
|
+
tile-size snapshot, so pasting recomputes destination cells in the
|
|
6
|
+
*current* grid and never lands in surprising places after Scale/Grid.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pygame import Surface
|
|
12
|
+
|
|
13
|
+
from .document import Document
|
|
14
|
+
from .selection import Selection
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Clipboard:
|
|
18
|
+
__slots__ = ("tiles", "tile_size", "origin_local")
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
self.tiles: list[tuple[int, int, Surface]] = []
|
|
22
|
+
self.tile_size: tuple[int, int] = (0, 0)
|
|
23
|
+
self.origin_local: tuple[int, int] = (0, 0)
|
|
24
|
+
|
|
25
|
+
def __len__(self) -> int:
|
|
26
|
+
return len(self.tiles)
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def is_empty(self) -> bool:
|
|
30
|
+
return not self.tiles
|
|
31
|
+
|
|
32
|
+
def clear(self) -> None:
|
|
33
|
+
self.tiles = []
|
|
34
|
+
self.tile_size = (0, 0)
|
|
35
|
+
self.origin_local = (0, 0)
|
|
36
|
+
|
|
37
|
+
def copy_from_selection(self, doc: Document, selection: Selection) -> bool:
|
|
38
|
+
"""Snapshot the selected cells as (dx, dy, surface) tiles.
|
|
39
|
+
|
|
40
|
+
Returns True if anything was copied.
|
|
41
|
+
"""
|
|
42
|
+
cells = selection.sorted_cells()
|
|
43
|
+
if not cells or not doc.surface:
|
|
44
|
+
self.clear()
|
|
45
|
+
return False
|
|
46
|
+
min_col = min(c for c, _ in cells)
|
|
47
|
+
min_row = min(r for _, r in cells)
|
|
48
|
+
self.tiles = [
|
|
49
|
+
(col - min_col, row - min_row, doc.extract_tile(col, row))
|
|
50
|
+
for col, row in cells
|
|
51
|
+
]
|
|
52
|
+
self.tile_size = doc.tile_size
|
|
53
|
+
self.origin_local = (min_col * doc.tw, min_row * doc.th)
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
def covered_cells(self, target_col: int, target_row: int) -> list[tuple[int, int]]:
|
|
57
|
+
"""Cell list the clipboard would occupy anchored at a target cell."""
|
|
58
|
+
return [
|
|
59
|
+
(target_col + dx, target_row + dy)
|
|
60
|
+
for dx, dy, _ in self.tiles
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
def paste_surfaces(self, target_col: int, target_row: int) -> list[tuple[int, int, Surface]]:
|
|
64
|
+
"""(col, row, surface) placements anchored at a target cell."""
|
|
65
|
+
return [
|
|
66
|
+
(target_col + dx, target_row + dy, surf)
|
|
67
|
+
for dx, dy, surf in self.tiles
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
def bounds_cells(self) -> tuple[int, int]:
|
|
71
|
+
"""Bounding box (ncols, nrows) of the clipboard tiles."""
|
|
72
|
+
if not self.tiles:
|
|
73
|
+
return (0, 0)
|
|
74
|
+
return (max(dx for dx, _, _ in self.tiles) + 1, max(dy for _, dy, _ in self.tiles) + 1)
|