tilemap-editor 4.2.0__tar.gz → 4.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tilemap_editor-4.2.0/src/tilemap_editor.egg-info → tilemap_editor-4.3.0}/PKG-INFO +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/pyproject.toml +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/editor.py +23 -23
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/layers.py +17 -28
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/ToolMove.svg +1 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/checked.svg +1 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/duplicate.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/error.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/file.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/filedead.svg +1 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/fit.svg +1 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/folder.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/grid.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/image.svg +1 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/info.svg +1 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/load.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/loop.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/pan.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/pause.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/pencil.svg +2 -2
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/play.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/plus.svg +1 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/radio.svg +1 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/reset.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/save.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/stop.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/tilemap.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/tileset.svg +1 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/unchecked.svg +1 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/warning.svg +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/zoomin.svg +5 -5
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/zoomout.svg +5 -5
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/cli.py +6 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0/src/tilemap_editor.egg-info}/PKG-INFO +1 -1
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor.egg-info/SOURCES.txt +3 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/icon_manager.py +51 -4
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/autotiler.py +13 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/tile_grid.py +274 -228
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/button.py +27 -3
- tilemap_editor-4.3.0/src/widgets/ui/drag_tracker.py +62 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/theme.py +57 -8
- tilemap_editor-4.3.0/src/widgets/ui/tool_manager.py +50 -0
- tilemap_editor-4.3.0/src/widgets/ui/toolbar.py +146 -0
- tilemap_editor-4.3.0/tests/test_drag_tracker.py +77 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_layers_autotile.py +200 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_toolbar_tools.py +50 -46
- tilemap_editor-4.2.0/src/tilemap_editor/assets/icons/checked.svg +0 -1
- tilemap_editor-4.2.0/src/tilemap_editor/assets/icons/fit.svg +0 -1
- tilemap_editor-4.2.0/src/tilemap_editor/assets/icons/info.svg +0 -1
- tilemap_editor-4.2.0/src/tilemap_editor/assets/icons/radio.svg +0 -1
- tilemap_editor-4.2.0/src/tilemap_editor/assets/icons/unchecked.svg +0 -1
- tilemap_editor-4.2.0/src/widgets/ui/toolbar.py +0 -164
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/LICENSE +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/MANIFEST.in +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/README.md +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/check.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/checked.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/close.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/error.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/file.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/filedead.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/fit.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/folder.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/grid.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/image.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/info.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/load.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/loop.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/pan.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/pause.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/pencil.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/play.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/plus.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/radio.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/reset.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/save.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/stop.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/tileset.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/warning.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/setup.cfg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/configs/themes.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/constants.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/event_map.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/main.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/node_manager.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/nodes.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/models.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/protocols.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/shape_editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/character_collision/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/object_tileset_collision/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/object_tileset_collision/editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/object_tileset_collision/models.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/object_tileset_collision/protocols.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/object_tileset_collision/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/__main__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/clipboard_util.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/frame_picker.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/models.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/preview.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/protocols.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/runtime_load.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/timeline.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_animation/validation.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_editor/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_editor/editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/sprite_editor/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/collision_painter.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/models.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/protocols.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/plugins/tileset_collision/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/standalone_automap.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/standalone_error_console.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/standalone_filemanager.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/standalone_image_viewer.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/__main__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/check.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/close.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/main.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor/settings.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor.egg-info/requires.txt +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/tilemap_editor.egg-info/top_level.txt +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/ttypes/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/ttypes/tilemap.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/editor_preference.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/error_handler.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/font_manager.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/history.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/icons_cache.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/log_capture.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/project_paths.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/serialization.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/standalone.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/utils/validation.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/__init__.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/automap_models.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/autotile_template.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/filemanager.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/input.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/layer_selector.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/map_properties.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/mapsetup.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/particle_presets.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/particle_system.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/regex_automap_designer.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/spritesheet_grid.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/tile_selector.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/checkbox.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/collision_layer_mask.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/collision_layer_sidebar.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/confirm_dialog.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/dialog_base.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/draw_utils.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/fileinput.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/label.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/layer_type_dialog.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/menubar.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/mode_indicator.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/node_editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/node_selector.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/notification.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/particle_config_dialog.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/property_editor.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/region_selector.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/scrollbar.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/sidebar_container.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/status_bar.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/tileset_type_dialog.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/ui/tooltip.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/src/widgets/widget_base.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_animation_library_grid_offset.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_collision_layer_mask.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_collision_layer_sidebar.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_editor_pan_mode.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_gid_collision.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_project_paths.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_render_scale.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_serialization_regression.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_sprite_animation_editor_grid.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_tile_grid_selection.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_tile_selector_pick.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_tilemap_save.py +0 -0
- {tilemap_editor-4.2.0 → tilemap_editor-4.3.0}/tests/test_timeline_invalidate_cache.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tilemap-editor"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.3.0"
|
|
8
8
|
description = "Pygame tilemap editor with SVG icons, professional UI, and sprite animation tools"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -40,6 +40,7 @@ from widgets.ui.particle_config_dialog import ParticleConfigDialog
|
|
|
40
40
|
from widgets.ui.property_editor import PropertyEditor
|
|
41
41
|
from widgets.ui.sidebar_container import SidebarContainer, ToolbarAction
|
|
42
42
|
from widgets.ui.theme import COLORS, THEMES, get_theme_manager, set_theme
|
|
43
|
+
from widgets.ui.tool_manager import ToolKind, ToolManager
|
|
43
44
|
from widgets.ui.tileset_type_dialog import TilesetTypeDialog
|
|
44
45
|
from widgets.ui.toolbar import Toolbar
|
|
45
46
|
from widgets.ui.tooltip import TooltipManager
|
|
@@ -138,27 +139,31 @@ _launch_standalone_module = launch_standalone
|
|
|
138
139
|
|
|
139
140
|
|
|
140
141
|
class Editor:
|
|
141
|
-
def __init__(
|
|
142
|
+
def __init__(
|
|
143
|
+
self,
|
|
144
|
+
size: Optional[Tuple[int, int]] = None,
|
|
145
|
+
fps=60,
|
|
146
|
+
theme: Optional[str] = None,
|
|
147
|
+
):
|
|
142
148
|
self.base_path, self.data_root, self.config = _load_project_config()
|
|
143
149
|
logger.info(f"Project base_path: {self.base_path}")
|
|
144
150
|
logger.info(f"Data root: {self.data_root}")
|
|
145
151
|
|
|
146
|
-
theme_name = self.config.get("theme", "dark")
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
logger.
|
|
152
|
+
theme_name = theme or self.config.get("theme", "dark")
|
|
153
|
+
tm = get_theme_manager()
|
|
154
|
+
if not tm.set_theme(theme_name):
|
|
155
|
+
logger.warning(f"Theme '{theme_name}' not found, falling back to dark")
|
|
156
|
+
tm.set_theme("dark")
|
|
150
157
|
|
|
151
158
|
pygame.init()
|
|
152
159
|
pygame.display.set_caption("Pure Pygame Editor")
|
|
153
160
|
|
|
154
161
|
self.fps = fps
|
|
155
162
|
self.running = False
|
|
156
|
-
self.pan_mode = False
|
|
157
163
|
self.autotile_mode = False
|
|
158
|
-
self.eraser_mode = False
|
|
159
|
-
self.select_mode = False
|
|
160
164
|
self.node_editing_mode = False
|
|
161
165
|
self.show_nodes = False
|
|
166
|
+
self.tool_manager = ToolManager()
|
|
162
167
|
self._prev_tool = None
|
|
163
168
|
|
|
164
169
|
if isinstance(size, tuple) and len(size) == 2:
|
|
@@ -712,6 +717,8 @@ class Editor:
|
|
|
712
717
|
next_idx = (current_idx + 1) % len(theme_names)
|
|
713
718
|
new_theme = theme_names[next_idx]
|
|
714
719
|
set_theme(new_theme)
|
|
720
|
+
from utils.icon_manager import icon_manager
|
|
721
|
+
icon_manager.clear_cache()
|
|
715
722
|
self.notifications.notify(f"Theme: {new_theme}")
|
|
716
723
|
|
|
717
724
|
settings_file = Path.cwd() / "settings.json"
|
|
@@ -1199,9 +1206,7 @@ class Editor:
|
|
|
1199
1206
|
self.node_editing_mode = not self.node_editing_mode
|
|
1200
1207
|
if self.node_editing_mode:
|
|
1201
1208
|
self.show_nodes = False
|
|
1202
|
-
self.
|
|
1203
|
-
self.select_mode = False
|
|
1204
|
-
self.eraser_mode = False
|
|
1209
|
+
self.tool_manager.deactivate()
|
|
1205
1210
|
continue
|
|
1206
1211
|
elif event.key == pygame.K_n and (ctrl_held or meta_held):
|
|
1207
1212
|
self.open_map_setup()
|
|
@@ -1210,27 +1215,22 @@ class Editor:
|
|
|
1210
1215
|
self.perform_load()
|
|
1211
1216
|
continue
|
|
1212
1217
|
elif event.key == pygame.K_SPACE and (ctrl_held or meta_held):
|
|
1213
|
-
if self.
|
|
1214
|
-
|
|
1215
|
-
if
|
|
1216
|
-
self.select_mode = True
|
|
1217
|
-
elif getattr(self, "_prev_tool", None) == "eraser":
|
|
1218
|
-
self.eraser_mode = True
|
|
1219
|
-
elif getattr(self, "_prev_tool", None) == "nodes":
|
|
1218
|
+
if self.tool_manager.is_active(ToolKind.PAN):
|
|
1219
|
+
restored = self.tool_manager.restore_previous()
|
|
1220
|
+
if restored is None and self._prev_tool == "nodes":
|
|
1220
1221
|
self.node_editing_mode = True
|
|
1222
|
+
self._prev_tool = None
|
|
1221
1223
|
else:
|
|
1222
|
-
if self.
|
|
1224
|
+
if self.tool_manager.is_active(ToolKind.SELECT):
|
|
1223
1225
|
self._prev_tool = "select"
|
|
1224
|
-
elif self.
|
|
1226
|
+
elif self.tool_manager.is_active(ToolKind.ERASER):
|
|
1225
1227
|
self._prev_tool = "eraser"
|
|
1226
1228
|
elif self.node_editing_mode:
|
|
1227
1229
|
self._prev_tool = "nodes"
|
|
1228
1230
|
else:
|
|
1229
1231
|
self._prev_tool = None
|
|
1230
|
-
self.pan_mode = True
|
|
1231
|
-
self.select_mode = False
|
|
1232
|
-
self.eraser_mode = False
|
|
1233
1232
|
self.node_editing_mode = False
|
|
1233
|
+
self.tool_manager.activate(ToolKind.PAN)
|
|
1234
1234
|
continue
|
|
1235
1235
|
elif event.key == pygame.K_g and (ctrl_held or meta_held):
|
|
1236
1236
|
self.toggle_grid()
|
|
@@ -4,8 +4,9 @@ Supports multiple layers with independent tile and object data.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import random
|
|
7
|
-
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
|
8
|
-
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple
|
|
8
|
+
|
|
9
|
+
from ttypes.tilemap import TypeObject, TypeTile
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from widgets.autotiler import AutotileRule
|
|
@@ -78,9 +79,7 @@ class Layer:
|
|
|
78
79
|
existing_positions = [p for p in positions if p in self.tiles]
|
|
79
80
|
return self._autotile_tiles(rules, existing_positions)
|
|
80
81
|
|
|
81
|
-
def _autotile_tiles(
|
|
82
|
-
self, rules: List["AutotileRule"], positions: List[Tuple[int, int]]
|
|
83
|
-
) -> int:
|
|
82
|
+
def _autotile_tiles(self, rules: List["AutotileRule"], positions: List[Tuple[int, int]]) -> int:
|
|
84
83
|
"""
|
|
85
84
|
Internal helper to update specific tiles according to autotile rules.
|
|
86
85
|
|
|
@@ -97,12 +96,7 @@ class Layer:
|
|
|
97
96
|
if not rules or not positions:
|
|
98
97
|
return 0
|
|
99
98
|
|
|
100
|
-
rules_hash = hash(
|
|
101
|
-
tuple(
|
|
102
|
-
(r.group_id, r.tileset_index, tuple(sorted(r.variant_ids)))
|
|
103
|
-
for r in rules
|
|
104
|
-
)
|
|
105
|
-
)
|
|
99
|
+
rules_hash = hash(tuple((r.group_id, r.tileset_index, tuple(sorted(r.variant_ids))) for r in rules))
|
|
106
100
|
|
|
107
101
|
if self._autotile_cache["rules_hash"] != rules_hash:
|
|
108
102
|
variant_to_group: Dict[Tuple[int, int], str] = {}
|
|
@@ -180,21 +174,23 @@ class Layer:
|
|
|
180
174
|
if n_group == target_group_id:
|
|
181
175
|
actual_neighbors.append((dx, dy))
|
|
182
176
|
|
|
183
|
-
neighbor_offsets_set = {
|
|
184
|
-
n for n in actual_neighbors if n in significant_offsets
|
|
185
|
-
}
|
|
177
|
+
neighbor_offsets_set = {n for n in actual_neighbors if n in significant_offsets}
|
|
186
178
|
|
|
187
179
|
matched_rule: Optional["AutotileRule"] = None
|
|
180
|
+
new_variant: Optional[int] = None
|
|
188
181
|
for rule in group_rules:
|
|
189
|
-
if
|
|
190
|
-
rule.neighbors == neighbor_offsets_set
|
|
191
|
-
and rule.tileset_index == ttype
|
|
192
|
-
):
|
|
182
|
+
if rule.neighbors == neighbor_offsets_set and rule.tileset_index == ttype:
|
|
193
183
|
matched_rule = rule
|
|
194
184
|
break
|
|
195
185
|
|
|
196
186
|
if matched_rule and matched_rule.variant_ids:
|
|
197
|
-
|
|
187
|
+
# only reroll if current variant isnt already
|
|
188
|
+
# in the matched rule's set to prevents re-randomization
|
|
189
|
+
# of neighbors whose pattern hasnt actually changed.
|
|
190
|
+
if current_variant not in matched_rule.variant_ids:
|
|
191
|
+
new_variant = random.choice(matched_rule.variant_ids)
|
|
192
|
+
else:
|
|
193
|
+
new_variant = current_variant
|
|
198
194
|
|
|
199
195
|
if new_variant != current_variant:
|
|
200
196
|
tile["variant"] = new_variant
|
|
@@ -238,12 +234,7 @@ class Layer:
|
|
|
238
234
|
while queue:
|
|
239
235
|
curr = queue.pop(0)
|
|
240
236
|
|
|
241
|
-
if
|
|
242
|
-
curr[0] < 0
|
|
243
|
-
or curr[0] >= map_size[0]
|
|
244
|
-
or curr[1] < 0
|
|
245
|
-
or curr[1] >= map_size[1]
|
|
246
|
-
):
|
|
237
|
+
if curr[0] < 0 or curr[0] >= map_size[0] or curr[1] < 0 or curr[1] >= map_size[1]:
|
|
247
238
|
continue
|
|
248
239
|
|
|
249
240
|
curr_tile = self.tiles.get(curr)
|
|
@@ -476,9 +467,7 @@ class LayerManager:
|
|
|
476
467
|
if not manager.layers:
|
|
477
468
|
manager.create_layer("Default")
|
|
478
469
|
|
|
479
|
-
if manager.active_layer_idx < 0 or manager.active_layer_idx >= len(
|
|
480
|
-
manager.layers
|
|
481
|
-
):
|
|
470
|
+
if manager.active_layer_idx < 0 or manager.active_layer_idx >= len(manager.layers):
|
|
482
471
|
manager.active_layer_idx = 0
|
|
483
472
|
|
|
484
473
|
return manager
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#ffffff"><circle cx="8" cy="8" r="2"/><path d="M8 1a1 1 0 0 0-.691.291l-2 2 1.414 1.414 1.293-1.293 1.293 1.293 1.414-1.414-2-2A1 1 0 0 0 8 1zM3.309 5.291l-2 2a1 1 0 0 0 0 1.414l2 2 1.414-1.414L3.43 7.998l1.293-1.293-1.414-1.414zm9.414 0-1.414 1.414 1.293 1.293-1.293 1.293 1.414 1.414 2-2a1 1 0 0 0 0-1.414l-2-2zm-6 6-1.414 1.414 2 2a1 1 0 0 0 1.414 0l2-2-1.414-1.414-1.293 1.293-1.293-1.293z"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect width="14" height="14" x="1" y="1" fill="#ffffff" rx="2.33"/><path fill="#ffffff" d="M11.5 3.734 5.89 9.346 4.185 7.665l-1.5 1.499 3.204 3.18L13 5.235z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="m5 1v11h9v-6h-5v-5zm5 0v4h4zm-8 3v11h2 8v-2h-8v-9z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><circle cx="8" cy="8" r="4" fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><circle cx="8" cy="8" r="4" fill="#ffffff"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="m2 1v14h12v-9h-5v-5zm8 0v4h4z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M2 1v14h12V6H9V1zm8 0v4h4zM5 7.793l.646-.646a.353.353 0 0 1 .707.707l-.646.646.646.646a.353.353 0 0 1-.707.707L5 9.207l-.646.646a.353.353 0 0 1-.707-.706l.646-.647-.646-.646a.353.353 0 0 1 .707-.707zm6 0 .646-.646a.353.353 0 0 1 .707.707l-.646.646.646.646a.353.353 0 0 1-.706.707L11 9.207l-.646.646a.353.353 0 0 1-.707-.706l.646-.647-.646-.646a.353.353 0 0 1 .706-.707zM3.5 11h9a.5.5 0 0 1 0 1H8a2 2 0 0 1-4 0h-.5a.5.5 0 0 1 0-1zM5 12a1 1 0 0 0 2 0z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><circle cx="8" cy="8" r="8" fill-opacity=".4"/><path fill="#ffffff" d="M8 1a7 7 0 0 0 0 14A7 7 0 0 0 8 1zm0 3.166A1 1 0 0 1 9.526 5v7h-2V6.87l-1.445.962-1-1.6z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M2 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-4a1 1 0 0 1-1-1V3a1 1 0 0 0-1-1z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M3 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2zm0 2h2v2H3zm4 0h2v2H7zm4 0h2v2h-2zM3 7h2v2H3zm4 0h2v2H7zm4 0h2v2h-2zm-8 4h2v2H3zm4 0h2v2H7zm4 0h2v2h-2z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="m2 1a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-12a1 1 0 0 0 -1-1zm1 2h10v8h-10zm6 2-1.5 2.5-.70117 1.168-.099609-.16797-.89844-1.5-.90039 1.5-.90039 1.5h1.8008.19922 1.5996 1.4004 3l-1.5-2.5-1.5-2.5z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M8 1a7 7 0 0 0 0 14A7 7 0 0 0 8 1zM7 4h2v2H7zm0 3h2v5H7z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M3 2a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9c1.105 0 1.818-.91 2-2l1-6a1 1 0 0 0-1-1H6c-.552 0-.909.455-1 1l-1 6c-.091.545-.448 1-1 1a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1 1 1 0 0 0 1 1h5a1 1 0 0 0-1-1H7a2 2 0 0 0-2-2H3z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M8 1v2H6a5 5 0 0 0-4 8l1.414-1.414A3 3 0 0 1 6 5h2v2l4-3-4-3zm6 4-1.414 1.414A3 3 0 0 1 10 11H8V9l-4 3 4 3v-2h2a5 5 0 0 0 4-8z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M11 2a1 1 0 0 0-2 0v6H8V3a1 1 0 0 0-2 0v8.05l-2.5-1.8A1 1 0 0 0 1.875 11L6 15h6a2 2 0 0 0 2-2V4a1 1 0 0 0-2 0v4h-1z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M4 3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm6 0a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/></svg>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
-
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="m3.99 16.854-1.314 3.504a.75.75 0 0 0 .966.965l3.503-1.314a3 3 0 0 0 1.068-.687L18.36 9.175s-.354-1.061-1.414-2.122c-1.06-1.06-2.122-1.414-2.122-1.414L4.677 15.786a3 3 0 0 0-.687 1.068zm12.249-12.63 1.383-1.383c.248-.248.579-.406.925-.348.487.08 1.232.322 1.934 1.025.703.703.945 1.447 1.025 1.934.058.346-.1.677-.348.925L19.774 7.76s-.353-1.06-1.414-2.12c-1.06-1.062-2.121-1.415-2.121-1.415z" fill="#
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
+
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="m3.99 16.854-1.314 3.504a.75.75 0 0 0 .966.965l3.503-1.314a3 3 0 0 0 1.068-.687L18.36 9.175s-.354-1.061-1.414-2.122c-1.06-1.06-2.122-1.414-2.122-1.414L4.677 15.786a3 3 0 0 0-.687 1.068zm12.249-12.63 1.383-1.383c.248-.248.579-.406.925-.348.487.08 1.232.322 1.934 1.025.703.703.945 1.447 1.025 1.934.058.346-.1.677-.348.925L19.774 7.76s-.353-1.06-1.414-2.12c-1.06-1.062-2.121-1.415-2.121-1.415z" fill="#ffffff"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M4 12a1 1 0 0 0 1.555.832l6-4a1 1 0 0 0 0-1.664l-6-4A1 1 0 0 0 4 4z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><circle cx="8" cy="8" r="7" fill="#ffffff"/><circle cx="8" cy="8" r="4" fill="#ffffff"/></svg>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
<?xml version="1.0" ?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
-
<svg fill="#
|
|
2
|
+
<svg fill="#ffffff" width="800px" height="800px" viewBox="0 0 512 512" data-name="Layer 1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"><path d="M64,256H34A222,222,0,0,1,430,118.15V85h30V190H355V160h67.27A192.21,192.21,0,0,0,256,64C150.13,64,64,150.13,64,256Zm384,0c0,105.87-86.13,192-192,192A192.21,192.21,0,0,1,89.73,352H157V322H52V427H82V393.85A222,222,0,0,0,478,256Z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M3 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4l-3-3h-1v6H3zm1 0v5h3V1zm4 8a1 1 0 0 1 0 4 1 1 0 0 1 0-4z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect width="10" height="10" x="3" y="3" fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect width="10" height="10" x="3" y="3" fill="#ffffff" rx="1"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M1 1v2h2V1zm3 0v2h2V1zm3 0v2h2V1zm3 0v2h2V1zm3 0v2h2V1zM1 4v2h2V4zm3 0v2h2V4zm3 0v2h2V4zm3 0v2h2V4zm3 0v2h2V4zM1 7v2h2V7zm3 0v2h2V7zm3 0v2h2V7zm3 0v2h2V7zm3 0v2h2V7zM1 10v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zM1 13v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M1 1v2h2V1zm3 0v2h2V1zm3 0v2h2V1zm3 0v2h2V1zm3 0v2h2V1zM1 4v2h2V4zm3 0v2h2V4zm3 0v2h2V4zm3 0v2h2V4zm3 0v2h2V4zM1 7v2h2V7zm3 0v2h2V7zm5 1v7h5a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v4l-1-1-1 1V8zm-8 2v2h2v-2zm3 0v2h2v-2zm-3 3v2h2v-2zm3 0v2h2v-2z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect width="14" height="14" x="1" y="1" fill="#ffffff" rx="2.33"/><path fill="#ffffff" d="M11.5 3.734 5.89 9.346 4.185 7.665l-1.5 1.499 3.204 3.18L13 5.235z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M8 1a7 7 0 0 0 0 14A7 7 0 0 0 8 1zM7 3h2v7H7zm0 8h2v2H7z"/></svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#
|
|
4
|
-
<title>zoomin</title>
|
|
5
|
-
<path d="M16.906 20.188l5.5 5.5-2.25 2.281-5.75-5.781c-1.406 0.781-3.031 1.219-4.719 1.219-5.344 0-9.688-4.344-9.688-9.688s4.344-9.688 9.688-9.688 9.719 4.344 9.719 9.688c0 2.5-0.969 4.781-2.5 6.469zM2.688 13.719c0 3.875 3.125 6.969 7 6.969 3.844 0 7-3.094 7-6.969s-3.156-6.969-7-6.969c-3.875 0-7 3.094-7 6.969zM10.813 12.625h3.875v2.219h-3.875v3.844h-2.219v-3.844h-3.844v-2.219h3.844v-3.875h2.219v3.875z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#ffffff" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>zoomin</title>
|
|
5
|
+
<path d="M16.906 20.188l5.5 5.5-2.25 2.281-5.75-5.781c-1.406 0.781-3.031 1.219-4.719 1.219-5.344 0-9.688-4.344-9.688-9.688s4.344-9.688 9.688-9.688 9.719 4.344 9.719 9.688c0 2.5-0.969 4.781-2.5 6.469zM2.688 13.719c0 3.875 3.125 6.969 7 6.969 3.844 0 7-3.094 7-6.969s-3.156-6.969-7-6.969c-3.875 0-7 3.094-7 6.969zM10.813 12.625h3.875v2.219h-3.875v3.844h-2.219v-3.844h-3.844v-2.219h3.844v-3.875h2.219v3.875z"></path>
|
|
6
6
|
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#
|
|
4
|
-
<title>zoomout</title>
|
|
5
|
-
<path d="M16.906 20.188l5.5 5.5-2.25 2.281-5.75-5.781c-1.406 0.781-3.031 1.219-4.719 1.219-5.344 0-9.688-4.344-9.688-9.688s4.344-9.688 9.688-9.688 9.719 4.344 9.719 9.688c0 2.5-0.969 4.781-2.5 6.469zM2.688 13.719c0 3.875 3.125 6.969 7 6.969 3.844 0 7-3.094 7-6.969s-3.156-6.969-7-6.969c-3.875 0-7 3.094-7 6.969zM4.438 12.625h10.531v2.219h-10.531v-2.219z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#ffffff" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>zoomout</title>
|
|
5
|
+
<path d="M16.906 20.188l5.5 5.5-2.25 2.281-5.75-5.781c-1.406 0.781-3.031 1.219-4.719 1.219-5.344 0-9.688-4.344-9.688-9.688s4.344-9.688 9.688-9.688 9.719 4.344 9.719 9.688c0 2.5-0.969 4.781-2.5 6.469zM2.688 13.719c0 3.875 3.125 6.969 7 6.969 3.844 0 7-3.094 7-6.969s-3.156-6.969-7-6.969c-3.875 0-7 3.094-7 6.969zM4.438 12.625h10.531v2.219h-10.531v-2.219z"></path>
|
|
6
6
|
</svg>
|
|
@@ -43,6 +43,11 @@ def main() -> None:
|
|
|
43
43
|
"--size", default="1500x900", help="Window size as WIDTHxHEIGHT"
|
|
44
44
|
)
|
|
45
45
|
run_parser.add_argument("--fps", type=int, default=60, help="Editor FPS")
|
|
46
|
+
run_parser.add_argument(
|
|
47
|
+
"--theme",
|
|
48
|
+
default=None,
|
|
49
|
+
help='Theme name or path to .json theme file (e.g. "molokai", "path/to/custom.json")',
|
|
50
|
+
)
|
|
46
51
|
|
|
47
52
|
args = parser.parse_args()
|
|
48
53
|
|
|
@@ -74,7 +79,7 @@ def _run_editor(args) -> None:
|
|
|
74
79
|
try:
|
|
75
80
|
with error_context("cli_main"):
|
|
76
81
|
size = _parse_size(args.size)
|
|
77
|
-
editor = Editor(size=size, fps=max(1, args.fps))
|
|
82
|
+
editor = Editor(size=size, fps=max(1, args.fps), theme=args.theme)
|
|
78
83
|
editor.run()
|
|
79
84
|
except KeyboardInterrupt:
|
|
80
85
|
print("\nEditor interrupted by user")
|
|
@@ -179,6 +179,7 @@ src/widgets/ui/collision_layer_mask.py
|
|
|
179
179
|
src/widgets/ui/collision_layer_sidebar.py
|
|
180
180
|
src/widgets/ui/confirm_dialog.py
|
|
181
181
|
src/widgets/ui/dialog_base.py
|
|
182
|
+
src/widgets/ui/drag_tracker.py
|
|
182
183
|
src/widgets/ui/draw_utils.py
|
|
183
184
|
src/widgets/ui/fileinput.py
|
|
184
185
|
src/widgets/ui/label.py
|
|
@@ -196,11 +197,13 @@ src/widgets/ui/sidebar_container.py
|
|
|
196
197
|
src/widgets/ui/status_bar.py
|
|
197
198
|
src/widgets/ui/theme.py
|
|
198
199
|
src/widgets/ui/tileset_type_dialog.py
|
|
200
|
+
src/widgets/ui/tool_manager.py
|
|
199
201
|
src/widgets/ui/toolbar.py
|
|
200
202
|
src/widgets/ui/tooltip.py
|
|
201
203
|
tests/test_animation_library_grid_offset.py
|
|
202
204
|
tests/test_collision_layer_mask.py
|
|
203
205
|
tests/test_collision_layer_sidebar.py
|
|
206
|
+
tests/test_drag_tracker.py
|
|
204
207
|
tests/test_editor_pan_mode.py
|
|
205
208
|
tests/test_gid_collision.py
|
|
206
209
|
tests/test_layers_autotile.py
|
|
@@ -386,6 +386,41 @@ class IconManager:
|
|
|
386
386
|
thickness,
|
|
387
387
|
)
|
|
388
388
|
|
|
389
|
+
elif name == "select":
|
|
390
|
+
thickness = max(2, size // 8)
|
|
391
|
+
p = padding
|
|
392
|
+
r = size - padding
|
|
393
|
+
pygame.draw.rect(surface, color, (p + 2, p + 2, r - p - 6, r - p - 6), thickness)
|
|
394
|
+
pygame.draw.line(surface, color, (r - 6, r - 6), (r, r), thickness + 1)
|
|
395
|
+
|
|
396
|
+
elif name == "eraser":
|
|
397
|
+
thickness = max(2, size // 8)
|
|
398
|
+
p = padding
|
|
399
|
+
r = size - padding
|
|
400
|
+
pygame.draw.rect(surface, color, (p, r // 2, r - p, r // 2 - p + 2))
|
|
401
|
+
pygame.draw.polygon(
|
|
402
|
+
surface, color,
|
|
403
|
+
[(r - p - 4, p + 2), (r - p, p + 2), (p + 4, r // 2), (p, r // 2)],
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
elif name == "auto":
|
|
407
|
+
thickness = max(2, size // 10)
|
|
408
|
+
cx, cy = size // 2, size // 2
|
|
409
|
+
pygame.draw.circle(surface, color, (cx, cy), size // 4, thickness)
|
|
410
|
+
pygame.draw.line(surface, color, (cx, cy), (cx, padding), thickness)
|
|
411
|
+
pygame.draw.line(surface, color, (cx, cy), (size - padding, cy), thickness)
|
|
412
|
+
pygame.draw.line(surface, color, (cx, cy), (cx, size - padding), thickness)
|
|
413
|
+
|
|
414
|
+
elif name == "nodes":
|
|
415
|
+
thickness = max(2, size // 10)
|
|
416
|
+
r = size // 8
|
|
417
|
+
positions = [(size // 2, size // 4), (size // 4, size * 3 // 4), (size * 3 // 4, size * 3 // 4)]
|
|
418
|
+
for px, py in positions:
|
|
419
|
+
pygame.draw.circle(surface, color, (px, py), r)
|
|
420
|
+
for i in range(len(positions)):
|
|
421
|
+
for j in range(i + 1, len(positions)):
|
|
422
|
+
pygame.draw.line(surface, color, positions[i], positions[j], 1)
|
|
423
|
+
|
|
389
424
|
elif name == "pan":
|
|
390
425
|
thickness = max(2, size // 8)
|
|
391
426
|
cx, cy = size // 2, size // 2
|
|
@@ -476,14 +511,15 @@ class IconManager:
|
|
|
476
511
|
Returns:
|
|
477
512
|
pygame.Surface with the rendered icon
|
|
478
513
|
"""
|
|
514
|
+
svg_name = _ICON_ALIASES.get(name, name)
|
|
479
515
|
cache_key = (name, size, color or (0, 0, 0))
|
|
480
516
|
if cache_key in self._surface_cache:
|
|
481
517
|
return self._surface_cache[cache_key]
|
|
482
518
|
|
|
483
519
|
surface = None
|
|
484
520
|
|
|
485
|
-
if self.has_icon(
|
|
486
|
-
svg_path = self._icons_path / f"{
|
|
521
|
+
if self.has_icon(svg_name):
|
|
522
|
+
svg_path = self._icons_path / f"{svg_name}.svg"
|
|
487
523
|
try:
|
|
488
524
|
if hasattr(pygame.image, "load_sized_svg"):
|
|
489
525
|
surface = pygame.image.load_sized_svg(str(svg_path), (size, size))
|
|
@@ -496,7 +532,7 @@ class IconManager:
|
|
|
496
532
|
|
|
497
533
|
if surface is None:
|
|
498
534
|
fallback_color = color or (200, 200, 200)
|
|
499
|
-
surface = self._draw_fallback_icon(
|
|
535
|
+
surface = self._draw_fallback_icon(svg_name, size, fallback_color)
|
|
500
536
|
|
|
501
537
|
if color and surface:
|
|
502
538
|
tinted = surface.copy()
|
|
@@ -523,9 +559,16 @@ def get_icon(
|
|
|
523
559
|
return icon_manager.get_icon(name, size, color)
|
|
524
560
|
|
|
525
561
|
|
|
562
|
+
_ICON_ALIASES = {
|
|
563
|
+
"zoom_in": "zoomin",
|
|
564
|
+
"zoom_out": "zoomout",
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
|
|
526
568
|
def has_icon(name: str) -> bool:
|
|
527
569
|
"""Check if an icon exists (either as SVG or fallback)."""
|
|
528
|
-
|
|
570
|
+
resolved = _ICON_ALIASES.get(name, name)
|
|
571
|
+
return icon_manager.has_icon(resolved) or resolved in [
|
|
529
572
|
"plus",
|
|
530
573
|
"close",
|
|
531
574
|
"x",
|
|
@@ -547,4 +590,8 @@ def has_icon(name: str) -> bool:
|
|
|
547
590
|
"fit",
|
|
548
591
|
"pan",
|
|
549
592
|
"radio",
|
|
593
|
+
"select",
|
|
594
|
+
"eraser",
|
|
595
|
+
"auto",
|
|
596
|
+
"nodes",
|
|
550
597
|
]
|
|
@@ -246,6 +246,19 @@ class AutotileRuleDesigner:
|
|
|
246
246
|
all_rules.extend(g.rules)
|
|
247
247
|
return all_rules
|
|
248
248
|
|
|
249
|
+
@property
|
|
250
|
+
def variant_to_group(self):
|
|
251
|
+
"""Map (tileset_index, variant_id) -> group_id from all rules."""
|
|
252
|
+
mapping = {}
|
|
253
|
+
for g in self.groups:
|
|
254
|
+
for rule in g.rules:
|
|
255
|
+
ts_idx = rule.tileset_index
|
|
256
|
+
for vid in rule.variant_ids:
|
|
257
|
+
key = (ts_idx, vid)
|
|
258
|
+
if key not in mapping:
|
|
259
|
+
mapping[key] = g.name
|
|
260
|
+
return mapping
|
|
261
|
+
|
|
249
262
|
def handle_event(self, event) -> bool:
|
|
250
263
|
if not self.visible:
|
|
251
264
|
return False
|