tilemap-editor 4.3.0__tar.gz → 4.3.2__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.0 → tilemap_editor-4.3.2}/PKG-INFO +10 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/README.md +7 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/pyproject.toml +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/editor.py +72 -74
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/event_map.py +4 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/layers.py +28 -28
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/node_manager.py +13 -13
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/nodes.py +7 -7
- tilemap_editor-4.3.2/src/plugins/character_collision/editor.py +602 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/character_collision/models.py +29 -28
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/character_collision/protocols.py +16 -16
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/character_collision/shape_editor.py +50 -39
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/character_collision/standalone.py +12 -5
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/object_tileset_collision/__init__.py +1 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/object_tileset_collision/editor.py +102 -94
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/object_tileset_collision/models.py +10 -10
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/object_tileset_collision/protocols.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/object_tileset_collision/standalone.py +4 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/__init__.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/clipboard_util.py +0 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/editor.py +205 -373
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/frame_picker.py +58 -83
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/models.py +15 -15
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/preview.py +47 -76
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/protocols.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/runtime_load.py +16 -16
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/standalone.py +3 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/timeline.py +55 -98
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/validation.py +4 -5
- tilemap_editor-4.3.2/src/plugins/sprite_editor/dialogs.py +197 -0
- tilemap_editor-4.3.2/src/plugins/sprite_editor/editor.py +631 -0
- tilemap_editor-4.3.2/src/plugins/sprite_editor/region_export.py +46 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_editor/standalone.py +12 -21
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/__init__.py +1 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/collision_painter.py +57 -58
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/editor.py +94 -136
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/models.py +13 -13
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/protocols.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/tileset_collision/standalone.py +4 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/standalone_automap.py +5 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/standalone_error_console.py +37 -108
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/standalone_filemanager.py +13 -10
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/standalone_image_viewer.py +5 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap.py +14 -14
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/check.svg +1 -0
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/error.svg +1 -0
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/fold_down_arrow.svg +1 -0
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/gear.svg +1 -0
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/info.svg +1 -0
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/miniobj.svg +1 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/tileset.svg +1 -1
- tilemap_editor-4.3.2/src/tilemap_editor/assets/icons/unfold_right_arrow.svg +1 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/cli.py +2 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/settings.py +2 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/PKG-INFO +10 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/SOURCES.txt +9 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/top_level.txt +0 -1
- tilemap_editor-4.3.2/src/ttypes/__init__.py +8 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/ttypes/tilemap.py +15 -15
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/__init__.py +1 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/editor_preference.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/error_handler.py +10 -10
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/font_manager.py +14 -16
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/history.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/icon_manager.py +8 -8
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/icons_cache.py +31 -24
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/log_capture.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/project_paths.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/serialization.py +4 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/standalone.py +19 -7
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/utils/validation.py +1 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/automap_models.py +14 -15
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/autotile_template.py +8 -8
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/autotiler.py +47 -52
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/filemanager.py +122 -217
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/input.py +46 -29
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/layer_selector.py +17 -16
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/map_properties.py +3 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/mapsetup.py +5 -5
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/particle_presets.py +6 -8
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/particle_system.py +12 -14
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/regex_automap_designer.py +20 -22
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/spritesheet_grid.py +45 -57
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/tile_grid.py +185 -286
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/tile_selector.py +193 -280
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/button.py +5 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/checkbox.py +3 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/collision_layer_mask.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/collision_layer_sidebar.py +9 -12
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/confirm_dialog.py +4 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/dialog_base.py +5 -4
- tilemap_editor-4.3.2/src/widgets/ui/drag_tracker.py +145 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/draw_utils.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/fileinput.py +15 -21
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/label.py +0 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/layer_type_dialog.py +5 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/menubar.py +24 -27
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/mode_indicator.py +17 -19
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/node_editor.py +30 -31
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/node_selector.py +28 -28
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/notification.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/particle_config_dialog.py +31 -32
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/property_editor.py +13 -15
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/region_selector.py +102 -121
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/scrollbar.py +16 -17
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/sidebar_container.py +7 -7
- tilemap_editor-4.3.2/src/widgets/ui/splitter.py +79 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/status_bar.py +10 -10
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/theme.py +37 -16
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/tileset_type_dialog.py +23 -24
- tilemap_editor-4.3.2/src/widgets/ui/toast.py +245 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/tool_manager.py +4 -5
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/toolbar.py +7 -9
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/ui/tooltip.py +6 -5
- tilemap_editor-4.3.2/src/widgets/ui/tree_widget.py +452 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_animation_library_grid_offset.py +1 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_collision_layer_sidebar.py +13 -25
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_editor_pan_mode.py +1 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_layers_autotile.py +9 -10
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_project_paths.py +2 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_render_scale.py +1 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_serialization_regression.py +3 -1
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_sprite_animation_editor_grid.py +23 -6
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_tile_selector_pick.py +1 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_tilemap_save.py +1 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_toolbar_tools.py +1 -2
- tilemap_editor-4.3.0/src/configs/themes.py +0 -81
- tilemap_editor-4.3.0/src/plugins/character_collision/editor.py +0 -425
- tilemap_editor-4.3.0/src/plugins/sprite_editor/editor.py +0 -521
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/check.svg +0 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/error.svg +0 -1
- tilemap_editor-4.3.0/src/tilemap_editor/assets/icons/info.svg +0 -1
- tilemap_editor-4.3.0/src/ttypes/__init__.py +0 -6
- tilemap_editor-4.3.0/src/widgets/ui/drag_tracker.py +0 -62
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/LICENSE +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/MANIFEST.in +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/check.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/checked.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/close.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/error.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/file.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/filedead.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/fit.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/folder.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/grid.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/image.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/info.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/load.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/loop.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/pan.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/pause.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/pencil.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/play.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/plus.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/radio.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/reset.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/save.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/stop.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/tileset.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/warning.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/setup.cfg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/constants.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/main.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/__init__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/character_collision/__init__.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_animation/__main__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/plugins/sprite_editor/__init__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/__init__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/__main__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/__init__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Bold.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Italic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/jetbrain-fonts/JetBrainsMono-Regular.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/noto/NotoSans-Bold.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/noto/NotoSans-BoldItalic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/noto/NotoSans-Italic.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/ToolMove.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/arrow-down.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/checked.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/close.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/duplicate.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/file.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/filedead.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/fit.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/folder.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/grid.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/image.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/load.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/loop.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/onion.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/pan.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/pause.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/pencil.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/play.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/plus.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/radio.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/reset.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/save.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/skip-back.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/skip-forward.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/stop.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/tilemap.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/unchecked.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/warning.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/zoomin.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/assets/icons/zoomout.svg +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor/main.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/dependency_links.txt +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/entry_points.txt +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/tilemap_editor.egg-info/requires.txt +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/__init__.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/src/widgets/widget_base.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_collision_layer_mask.py +4 -4
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_drag_tracker.py +0 -0
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_gid_collision.py +2 -2
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_tile_grid_selection.py +3 -3
- {tilemap_editor-4.3.0 → tilemap_editor-4.3.2}/tests/test_timeline_invalidate_cache.py +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-editor
|
|
3
|
-
Version: 4.3.
|
|
4
|
-
Summary: Pygame tilemap editor with
|
|
3
|
+
Version: 4.3.2
|
|
4
|
+
Summary: Pygame tilemap editor with collision, animation, sprite & particle tools
|
|
5
5
|
Author: tilemap editor contributors
|
|
6
6
|
License: Proprietary
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
9
|
Classifier: Topic :: Games/Entertainment
|
|
10
10
|
Classifier: Topic :: Software Development
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: pygame-ce>=2.5
|
|
@@ -21,12 +21,18 @@ Dynamic: license-file
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
[tilemap-editor on PyPI](https://pypi.org/project/tilemap-editor/)
|
|
24
|
+
[tilemap-parser on deepwiki](https://deepwiki.com/FluffyBrudy/tilemap)
|
|
24
25
|
|
|
25
26
|
## Parser
|
|
26
27
|
|
|
27
28
|
`tilemap-parser` is a utility to parse and display maps created by this editor. You can use it to load and visualize tilemaps in your game or application.
|
|
28
29
|
|
|
29
|
-
[tilemap-parser on
|
|
30
|
+
[tilemap-parser on deepwiki](https://deepwiki.com/FluffyBrudy/tilemap-parser)
|
|
31
|
+
[tilemap-parser on PyPI](https://pypi.org/project/tilemap-parser/)
|
|
32
|
+
|
|
33
|
+
## Kit
|
|
34
|
+
|
|
35
|
+
`pygkit` is general-purpose Pygame CE runtime kit: UI widgets, audio management, timers, interpolation, signals and utilities.
|
|
30
36
|
|
|
31
37
|
### Quick Start
|
|
32
38
|
|
|
@@ -42,7 +48,6 @@ tilemap-editor init
|
|
|
42
48
|
tilemap-editor run
|
|
43
49
|
```
|
|
44
50
|
|
|
45
|
-
|
|
46
51
|
```python
|
|
47
52
|
from editor import Editor
|
|
48
53
|
|
|
@@ -50,4 +55,3 @@ if __name__ == "__main__":
|
|
|
50
55
|
editor = Editor()
|
|
51
56
|
editor.run()
|
|
52
57
|
```
|
|
53
|
-
|
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
[tilemap-editor on PyPI](https://pypi.org/project/tilemap-editor/)
|
|
8
|
+
[tilemap-parser on deepwiki](https://deepwiki.com/FluffyBrudy/tilemap)
|
|
8
9
|
|
|
9
10
|
## Parser
|
|
10
11
|
|
|
11
12
|
`tilemap-parser` is a utility to parse and display maps created by this editor. You can use it to load and visualize tilemaps in your game or application.
|
|
12
13
|
|
|
13
|
-
[tilemap-parser on
|
|
14
|
+
[tilemap-parser on deepwiki](https://deepwiki.com/FluffyBrudy/tilemap-parser)
|
|
15
|
+
[tilemap-parser on PyPI](https://pypi.org/project/tilemap-parser/)
|
|
16
|
+
|
|
17
|
+
## Kit
|
|
18
|
+
|
|
19
|
+
`pygkit` is general-purpose Pygame CE runtime kit: UI widgets, audio management, timers, interpolation, signals and utilities.
|
|
14
20
|
|
|
15
21
|
### Quick Start
|
|
16
22
|
|
|
@@ -26,7 +32,6 @@ tilemap-editor init
|
|
|
26
32
|
tilemap-editor run
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
|
|
30
35
|
```python
|
|
31
36
|
from editor import Editor
|
|
32
37
|
|
|
@@ -34,4 +39,3 @@ if __name__ == "__main__":
|
|
|
34
39
|
editor = Editor()
|
|
35
40
|
editor.run()
|
|
36
41
|
```
|
|
37
|
-
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tilemap-editor"
|
|
7
|
-
version = "4.3.
|
|
8
|
-
description = "Pygame tilemap editor with
|
|
7
|
+
version = "4.3.2"
|
|
8
|
+
description = "Pygame tilemap editor with collision, animation, sprite & particle tools"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
11
|
license = { text = "Proprietary" }
|
|
12
12
|
authors = [{ name = "tilemap editor contributors" }]
|
|
13
13
|
dependencies = [
|
|
@@ -5,13 +5,14 @@ import queue
|
|
|
5
5
|
import subprocess
|
|
6
6
|
import sys
|
|
7
7
|
import threading
|
|
8
|
+
from collections.abc import Callable
|
|
8
9
|
from pathlib import Path
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
10
11
|
|
|
11
12
|
import pygame
|
|
12
13
|
from pygame import Rect
|
|
13
14
|
|
|
14
|
-
from utils.font_manager import
|
|
15
|
+
from utils.font_manager import FontWeight, font_manager
|
|
15
16
|
|
|
16
17
|
if sys.platform == "darwin":
|
|
17
18
|
os.environ.setdefault("SDL_VIDEO_MAC_SCREEN_SCALE", "1")
|
|
@@ -20,7 +21,6 @@ from constants import BASE_PATH
|
|
|
20
21
|
from node_manager import NodeManager
|
|
21
22
|
from tilemap import Tilemap
|
|
22
23
|
from utils import error_context, error_handler
|
|
23
|
-
from utils.log_capture import setup_console_log
|
|
24
24
|
from utils.standalone import launch_standalone
|
|
25
25
|
from widgets.autotiler import AutotileRuleDesigner
|
|
26
26
|
from widgets.layer_selector import LayerSelector
|
|
@@ -40,14 +40,13 @@ 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
|
|
44
43
|
from widgets.ui.tileset_type_dialog import TilesetTypeDialog
|
|
44
|
+
from widgets.ui.tool_manager import ToolKind, ToolManager
|
|
45
45
|
from widgets.ui.toolbar import Toolbar
|
|
46
46
|
from widgets.ui.tooltip import TooltipManager
|
|
47
47
|
|
|
48
48
|
if TYPE_CHECKING:
|
|
49
49
|
from plugins.sprite_animation import SpriteAnimationEditor
|
|
50
|
-
from plugins.sprite_editor import SpriteEditor
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
def setup_error_logging():
|
|
@@ -92,7 +91,7 @@ def _load_project_config() -> tuple[Path, Path, dict]:
|
|
|
92
91
|
raise RuntimeError("settings.json not found. Run 'tilemap-editor init' first.")
|
|
93
92
|
|
|
94
93
|
try:
|
|
95
|
-
with open(settings_file,
|
|
94
|
+
with open(settings_file, encoding="utf-8") as f:
|
|
96
95
|
config = json.load(f)
|
|
97
96
|
except json.JSONDecodeError as e:
|
|
98
97
|
raise RuntimeError(f"Invalid settings.json: {e}")
|
|
@@ -102,6 +101,24 @@ def _load_project_config() -> tuple[Path, Path, dict]:
|
|
|
102
101
|
if field not in config:
|
|
103
102
|
raise RuntimeError(f"Invalid settings.json: missing '{field}'")
|
|
104
103
|
|
|
104
|
+
defaults = {
|
|
105
|
+
"theme": "dark",
|
|
106
|
+
"themes_list": ["dark", "molokai", "light", "semi_light"],
|
|
107
|
+
"nodes_path": "nodes",
|
|
108
|
+
"collision_paths": {"tileset": "collision", "character": "character_collision"},
|
|
109
|
+
}
|
|
110
|
+
changed = False
|
|
111
|
+
for key, val in defaults.items():
|
|
112
|
+
if key not in config:
|
|
113
|
+
config[key] = val
|
|
114
|
+
changed = True
|
|
115
|
+
if changed:
|
|
116
|
+
try:
|
|
117
|
+
with open(settings_file, "w", encoding="utf-8") as f:
|
|
118
|
+
json.dump(config, f, indent=4)
|
|
119
|
+
except Exception:
|
|
120
|
+
pass
|
|
121
|
+
|
|
105
122
|
base_path = Path(config["base_path"]).expanduser()
|
|
106
123
|
|
|
107
124
|
if not base_path.is_absolute():
|
|
@@ -141,9 +158,9 @@ _launch_standalone_module = launch_standalone
|
|
|
141
158
|
class Editor:
|
|
142
159
|
def __init__(
|
|
143
160
|
self,
|
|
144
|
-
size:
|
|
161
|
+
size: tuple[int, int] | None = None,
|
|
145
162
|
fps=60,
|
|
146
|
-
theme:
|
|
163
|
+
theme: str | None = None,
|
|
147
164
|
):
|
|
148
165
|
self.base_path, self.data_root, self.config = _load_project_config()
|
|
149
166
|
logger.info(f"Project base_path: {self.base_path}")
|
|
@@ -181,27 +198,27 @@ class Editor:
|
|
|
181
198
|
self.selector_w = 300
|
|
182
199
|
self._tileset_dragging = False
|
|
183
200
|
self.left_panel_w = 380
|
|
184
|
-
self.map_setup_widget:
|
|
185
|
-
self.map_properties_dialog:
|
|
186
|
-
self.tileset_widget:
|
|
187
|
-
self.layer_widget:
|
|
188
|
-
self.tile_grid_widget:
|
|
201
|
+
self.map_setup_widget: MapSetup | None = None
|
|
202
|
+
self.map_properties_dialog: MapPropertiesDialog | None = None
|
|
203
|
+
self.tileset_widget: TileSelector | None = None
|
|
204
|
+
self.layer_widget: LayerSelector | None = None
|
|
205
|
+
self.tile_grid_widget: TileGrid | None = None
|
|
189
206
|
|
|
190
207
|
self.left_panel_visible = False
|
|
191
|
-
self.animation_panel:
|
|
192
|
-
self._animation_panel_surface:
|
|
208
|
+
self.animation_panel: SpriteAnimationEditor | None = None
|
|
209
|
+
self._animation_panel_surface: pygame.Surface | None = None
|
|
193
210
|
|
|
194
211
|
self.autotiler = AutotileRuleDesigner(self, 100, 100)
|
|
195
212
|
self.regex_automap_designer = RegexAutomapDesigner(self, 150, 100)
|
|
196
213
|
self.notifications = NotificationManager(self)
|
|
197
214
|
self.tooltip = TooltipManager()
|
|
198
|
-
self.error_console_process:
|
|
199
|
-
self.property_editor:
|
|
200
|
-
self.particle_config_dialog:
|
|
215
|
+
self.error_console_process: subprocess.Popen | None = None
|
|
216
|
+
self.property_editor: PropertyEditor | None = None
|
|
217
|
+
self.particle_config_dialog: ParticleConfigDialog | None = None
|
|
201
218
|
|
|
202
|
-
self.child_processes:
|
|
203
|
-
self.file_manager_process:
|
|
204
|
-
self._file_manager_callbacks:
|
|
219
|
+
self.child_processes: list[subprocess.Popen] = []
|
|
220
|
+
self.file_manager_process: subprocess.Popen | None = None
|
|
221
|
+
self._file_manager_callbacks: dict[str, Any] = {}
|
|
205
222
|
|
|
206
223
|
self.loading_state = {
|
|
207
224
|
"active": False,
|
|
@@ -209,7 +226,7 @@ class Editor:
|
|
|
209
226
|
"error": None,
|
|
210
227
|
"path": None,
|
|
211
228
|
}
|
|
212
|
-
self._load_queue:
|
|
229
|
+
self._load_queue: queue.Queue = queue.Queue()
|
|
213
230
|
|
|
214
231
|
editor_rect = self.screen.get_rect()
|
|
215
232
|
editor_rect.center = ((width - 300) // 2, height // 2)
|
|
@@ -265,14 +282,16 @@ class Editor:
|
|
|
265
282
|
def open_file_manager(
|
|
266
283
|
self,
|
|
267
284
|
on_select: Callable[[Path], None] = lambda p: None,
|
|
268
|
-
initial_dir:
|
|
269
|
-
allowed_exts:
|
|
285
|
+
initial_dir: Path | None = None,
|
|
286
|
+
allowed_exts: list[str] = None,
|
|
270
287
|
mode: str = "open",
|
|
271
|
-
on_save:
|
|
288
|
+
on_save: Callable[[Path], None] | None = None,
|
|
272
289
|
default_name: str = "",
|
|
273
290
|
multi_select: bool = False,
|
|
274
291
|
):
|
|
275
292
|
"""Launch file manager as a subprocess."""
|
|
293
|
+
if allowed_exts is None:
|
|
294
|
+
allowed_exts = [".png", ".jpg", ".json"]
|
|
276
295
|
if self.file_manager_process and self.file_manager_process.poll() is None:
|
|
277
296
|
return
|
|
278
297
|
|
|
@@ -718,13 +737,14 @@ class Editor:
|
|
|
718
737
|
new_theme = theme_names[next_idx]
|
|
719
738
|
set_theme(new_theme)
|
|
720
739
|
from utils.icon_manager import icon_manager
|
|
740
|
+
|
|
721
741
|
icon_manager.clear_cache()
|
|
722
742
|
self.notifications.notify(f"Theme: {new_theme}")
|
|
723
743
|
|
|
724
744
|
settings_file = Path.cwd() / "settings.json"
|
|
725
745
|
if settings_file.exists():
|
|
726
746
|
try:
|
|
727
|
-
with open(settings_file,
|
|
747
|
+
with open(settings_file, encoding="utf-8") as f:
|
|
728
748
|
config = json.load(f)
|
|
729
749
|
config["theme"] = new_theme
|
|
730
750
|
with open(settings_file, "w", encoding="utf-8") as f:
|
|
@@ -736,13 +756,13 @@ class Editor:
|
|
|
736
756
|
if hasattr(self.autotiler, "_launch_external_viewer"):
|
|
737
757
|
self.autotiler._launch_external_viewer()
|
|
738
758
|
|
|
739
|
-
def _active_tileset_image_path(self) ->
|
|
759
|
+
def _active_tileset_image_path(self) -> Path | None:
|
|
740
760
|
"""Filesystem path of the tileset image to use for the animation editor."""
|
|
741
761
|
tw = self.tileset_widget
|
|
742
762
|
if not tw or not tw.tilesets:
|
|
743
763
|
return None
|
|
744
764
|
|
|
745
|
-
candidates:
|
|
765
|
+
candidates: list[Path] = []
|
|
746
766
|
if 0 <= tw.active_idx < len(tw.tilesets):
|
|
747
767
|
candidates.append(tw.tilesets[tw.active_idx].path)
|
|
748
768
|
candidates.append(tw.tilesets[0].path)
|
|
@@ -925,7 +945,7 @@ class Editor:
|
|
|
925
945
|
if logger:
|
|
926
946
|
logger.info(msg)
|
|
927
947
|
|
|
928
|
-
def _write_propagation_groups(self, tileset_path: Path) ->
|
|
948
|
+
def _write_propagation_groups(self, tileset_path: Path) -> Path | None:
|
|
929
949
|
"""Collect auto-tile variant groups for a tileset and write to temp JSON.
|
|
930
950
|
|
|
931
951
|
Returns the path to the temp file, or None if no autotiler data is available.
|
|
@@ -950,7 +970,7 @@ class Editor:
|
|
|
950
970
|
if tileset_index is None:
|
|
951
971
|
return None
|
|
952
972
|
|
|
953
|
-
groups:
|
|
973
|
+
groups: dict[str, list[int]] = {}
|
|
954
974
|
for group in self.autotiler.groups:
|
|
955
975
|
for rule in group.rules:
|
|
956
976
|
if rule.tileset_index == tileset_index and rule.variant_ids:
|
|
@@ -1003,37 +1023,15 @@ class Editor:
|
|
|
1003
1023
|
logger.info(msg)
|
|
1004
1024
|
|
|
1005
1025
|
def launch_character_collision_editor(self):
|
|
1006
|
-
"""Launch the character collision editor in a new window.
|
|
1007
|
-
|
|
1008
|
-
Opens a file picker to select a character sprite image.
|
|
1009
|
-
"""
|
|
1010
|
-
self.open_file_manager(
|
|
1011
|
-
on_select=self._launch_character_collision_editor_with_image,
|
|
1012
|
-
initial_dir=self.data_root,
|
|
1013
|
-
allowed_exts=[".png", ".jpg", ".jpeg"],
|
|
1014
|
-
mode="open",
|
|
1015
|
-
)
|
|
1016
|
-
|
|
1017
|
-
def _launch_character_collision_editor_with_image(self, path: Path):
|
|
1018
|
-
"""Launch character collision editor subprocess with selected image."""
|
|
1026
|
+
"""Launch the character collision editor in a new window."""
|
|
1019
1027
|
try:
|
|
1020
|
-
character_name = path.stem
|
|
1021
|
-
|
|
1022
1028
|
args = [
|
|
1023
|
-
str(path),
|
|
1024
1029
|
"--name",
|
|
1025
|
-
|
|
1030
|
+
"Character",
|
|
1026
1031
|
"--data-root",
|
|
1027
1032
|
str(self.data_root),
|
|
1028
1033
|
]
|
|
1029
1034
|
|
|
1030
|
-
collision_dir = self.data_root / self.config.get("collision_paths", {}).get(
|
|
1031
|
-
"character", "character_collision"
|
|
1032
|
-
)
|
|
1033
|
-
collision_path = collision_dir / f"{character_name}.collision.json"
|
|
1034
|
-
if collision_path.exists():
|
|
1035
|
-
args.extend(["--load", str(collision_path)])
|
|
1036
|
-
|
|
1037
1035
|
process = launch_standalone(
|
|
1038
1036
|
"plugins.character_collision.standalone",
|
|
1039
1037
|
args,
|
|
@@ -1042,7 +1040,7 @@ class Editor:
|
|
|
1042
1040
|
)
|
|
1043
1041
|
self.child_processes.append(process)
|
|
1044
1042
|
|
|
1045
|
-
print(
|
|
1043
|
+
print("Launched character collision editor")
|
|
1046
1044
|
except Exception as e:
|
|
1047
1045
|
error_handler.capture(e, context="launch_character_collision_editor")
|
|
1048
1046
|
|
|
@@ -1181,40 +1179,40 @@ class Editor:
|
|
|
1181
1179
|
if event.key == pygame.K_r and (ctrl_held or meta_held):
|
|
1182
1180
|
self.toggle_autotiler()
|
|
1183
1181
|
continue
|
|
1184
|
-
|
|
1182
|
+
if event.key == pygame.K_m and (ctrl_held or meta_held):
|
|
1185
1183
|
self.toggle_regex_automap()
|
|
1186
1184
|
continue
|
|
1187
|
-
|
|
1185
|
+
if event.key == pygame.K_s and (ctrl_held or meta_held):
|
|
1188
1186
|
if shift_held:
|
|
1189
1187
|
self.open_save_as_dialog()
|
|
1190
1188
|
else:
|
|
1191
1189
|
self.perform_quick_save()
|
|
1192
1190
|
continue
|
|
1193
|
-
|
|
1191
|
+
if event.key == pygame.K_BACKQUOTE and (ctrl_held or meta_held):
|
|
1194
1192
|
self.launch_error_console()
|
|
1195
1193
|
continue
|
|
1196
|
-
|
|
1194
|
+
if event.key == pygame.K_z and (ctrl_held or meta_held):
|
|
1197
1195
|
if shift_held:
|
|
1198
1196
|
self.tilemap.redo()
|
|
1199
1197
|
else:
|
|
1200
1198
|
self.tilemap.undo()
|
|
1201
1199
|
continue
|
|
1202
|
-
|
|
1200
|
+
if event.key == pygame.K_y and (ctrl_held or meta_held):
|
|
1203
1201
|
self.tilemap.redo()
|
|
1204
1202
|
continue
|
|
1205
|
-
|
|
1203
|
+
if event.key == pygame.K_n and (ctrl_held or meta_held) and shift_held:
|
|
1206
1204
|
self.node_editing_mode = not self.node_editing_mode
|
|
1207
1205
|
if self.node_editing_mode:
|
|
1208
1206
|
self.show_nodes = False
|
|
1209
1207
|
self.tool_manager.deactivate()
|
|
1210
1208
|
continue
|
|
1211
|
-
|
|
1209
|
+
if event.key == pygame.K_n and (ctrl_held or meta_held):
|
|
1212
1210
|
self.open_map_setup()
|
|
1213
1211
|
continue
|
|
1214
|
-
|
|
1212
|
+
if event.key == pygame.K_o and (ctrl_held or meta_held):
|
|
1215
1213
|
self.perform_load()
|
|
1216
1214
|
continue
|
|
1217
|
-
|
|
1215
|
+
if event.key == pygame.K_SPACE and (ctrl_held or meta_held):
|
|
1218
1216
|
if self.tool_manager.is_active(ToolKind.PAN):
|
|
1219
1217
|
restored = self.tool_manager.restore_previous()
|
|
1220
1218
|
if restored is None and self._prev_tool == "nodes":
|
|
@@ -1232,19 +1230,19 @@ class Editor:
|
|
|
1232
1230
|
self.node_editing_mode = False
|
|
1233
1231
|
self.tool_manager.activate(ToolKind.PAN)
|
|
1234
1232
|
continue
|
|
1235
|
-
|
|
1233
|
+
if event.key == pygame.K_g and (ctrl_held or meta_held):
|
|
1236
1234
|
self.toggle_grid()
|
|
1237
1235
|
continue
|
|
1238
|
-
|
|
1236
|
+
if event.key == pygame.K_e and (ctrl_held or meta_held) and shift_held:
|
|
1239
1237
|
self.export_selection_as_png()
|
|
1240
1238
|
continue
|
|
1241
|
-
|
|
1239
|
+
if event.key == pygame.K_t and (ctrl_held or meta_held):
|
|
1242
1240
|
self.cycle_theme()
|
|
1243
1241
|
continue
|
|
1244
|
-
|
|
1242
|
+
if event.key == pygame.K_b and (ctrl_held or meta_held):
|
|
1245
1243
|
self.toggle_animation_panel()
|
|
1246
1244
|
continue
|
|
1247
|
-
|
|
1245
|
+
if pygame.K_1 <= event.key <= pygame.K_9:
|
|
1248
1246
|
if not (self.node_editor and self.node_editor.visible and self.node_editor.editing_field):
|
|
1249
1247
|
idx = event.key - pygame.K_1
|
|
1250
1248
|
if idx < self.tilemap.layer_manager.get_layer_count():
|
|
@@ -1314,7 +1312,7 @@ class Editor:
|
|
|
1314
1312
|
if hasattr(self.animation_panel, "update"):
|
|
1315
1313
|
self.animation_panel.update()
|
|
1316
1314
|
|
|
1317
|
-
self.screen.fill(
|
|
1315
|
+
self.screen.fill(COLORS.bg)
|
|
1318
1316
|
self.tooltip.hide()
|
|
1319
1317
|
|
|
1320
1318
|
if self.tile_grid_widget:
|
|
@@ -1343,12 +1341,12 @@ class Editor:
|
|
|
1343
1341
|
|
|
1344
1342
|
if self.left_panel_visible and self.animation_panel:
|
|
1345
1343
|
panel_surf = pygame.Surface((self.left_panel_w, self.height), pygame.SRCALPHA)
|
|
1346
|
-
panel_surf.fill((
|
|
1344
|
+
panel_surf.fill((*COLORS.panel_alt, 255))
|
|
1347
1345
|
self.screen.blit(panel_surf, (0, 65))
|
|
1348
1346
|
|
|
1349
1347
|
pygame.draw.rect(
|
|
1350
1348
|
self.screen,
|
|
1351
|
-
|
|
1349
|
+
COLORS.border,
|
|
1352
1350
|
Rect(0, 65, self.left_panel_w, self.height - 65),
|
|
1353
1351
|
1,
|
|
1354
1352
|
)
|
|
@@ -1391,13 +1389,13 @@ class Editor:
|
|
|
1391
1389
|
|
|
1392
1390
|
msg = self.loading_state.get("message", "Loading...")
|
|
1393
1391
|
font = font_manager.get_font("noto", 18, FontWeight.BOLD)
|
|
1394
|
-
text = font.render(msg, True,
|
|
1392
|
+
text = font.render(msg, True, COLORS.text)
|
|
1395
1393
|
text_rect = text.get_rect(center=(self.width // 2, self.height // 2))
|
|
1396
1394
|
self.screen.blit(text, text_rect)
|
|
1397
1395
|
|
|
1398
1396
|
dot_font = font_manager.get_font("noto", 16, FontWeight.REGULAR)
|
|
1399
1397
|
dots = "." * ((pygame.time.get_ticks() // 400) % 4)
|
|
1400
|
-
dot_surf = dot_font.render(dots, True,
|
|
1398
|
+
dot_surf = dot_font.render(dots, True, COLORS.text_muted)
|
|
1401
1399
|
dot_rect = dot_surf.get_rect(center=(self.width // 2, self.height // 2 + 30))
|
|
1402
1400
|
self.screen.blit(dot_surf, dot_rect)
|
|
1403
1401
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
2
3
|
|
|
3
4
|
from pygame import QUIT, Event
|
|
4
5
|
|
|
@@ -10,11 +11,11 @@ class EventMap:
|
|
|
10
11
|
def __init__(self, editor: "Editor") -> None:
|
|
11
12
|
self.editor = editor
|
|
12
13
|
|
|
13
|
-
self.event_map:
|
|
14
|
+
self.event_map: dict[tuple[int, int | None], Callable[[Event], None]] = {
|
|
14
15
|
(QUIT, None): lambda _: self.quit()
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
def get_event(self, event_key:
|
|
18
|
+
def get_event(self, event_key: tuple[int, int | None]):
|
|
18
19
|
return self.event_map.get(event_key, None)
|
|
19
20
|
|
|
20
21
|
def quit(self):
|
|
@@ -4,7 +4,7 @@ Supports multiple layers with independent tile and object data.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import random
|
|
7
|
-
from typing import TYPE_CHECKING, Any
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
9
|
from ttypes.tilemap import TypeObject, TypeTile
|
|
10
10
|
|
|
@@ -34,11 +34,11 @@ class Layer:
|
|
|
34
34
|
self.visible = visible
|
|
35
35
|
self.locked = locked
|
|
36
36
|
self.opacity = max(0.0, min(1.0, opacity))
|
|
37
|
-
self.properties:
|
|
37
|
+
self.properties: dict[str, Any] = {}
|
|
38
38
|
|
|
39
|
-
self.tiles:
|
|
39
|
+
self.tiles: dict[tuple[int, int], TypeTile] = {}
|
|
40
40
|
|
|
41
|
-
self.objects:
|
|
41
|
+
self.objects: dict[int, TypeObject] = {}
|
|
42
42
|
self.next_object_id: int = 1
|
|
43
43
|
|
|
44
44
|
self._autotile_cache = {
|
|
@@ -48,20 +48,20 @@ class Layer:
|
|
|
48
48
|
"significant_offsets": set(),
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
def set_tile(self, pos:
|
|
51
|
+
def set_tile(self, pos: tuple[int, int], tile: TypeTile) -> None:
|
|
52
52
|
"""Set a tile at the given grid position."""
|
|
53
53
|
if not self.locked:
|
|
54
54
|
self.tiles[pos] = tile
|
|
55
55
|
|
|
56
|
-
def get_tile(self, pos:
|
|
56
|
+
def get_tile(self, pos: tuple[int, int]) -> TypeTile | None:
|
|
57
57
|
"""Get a tile at the given grid position."""
|
|
58
58
|
return self.tiles.get(pos)
|
|
59
59
|
|
|
60
|
-
def autotile_layer(self, rules:
|
|
60
|
+
def autotile_layer(self, rules: list["AutotileRule"]) -> int:
|
|
61
61
|
"""Update all tiles in this layer according to autotile rules."""
|
|
62
62
|
return self._autotile_tiles(rules, list(self.tiles.keys()))
|
|
63
63
|
|
|
64
|
-
def autotile_at_pos(self, pos:
|
|
64
|
+
def autotile_at_pos(self, pos: tuple[int, int], rules: list["AutotileRule"]) -> int:
|
|
65
65
|
"""Update the tile at pos and its 8 neighbors according to autotile rules."""
|
|
66
66
|
positions = [pos]
|
|
67
67
|
for dx, dy in [
|
|
@@ -79,7 +79,7 @@ class Layer:
|
|
|
79
79
|
existing_positions = [p for p in positions if p in self.tiles]
|
|
80
80
|
return self._autotile_tiles(rules, existing_positions)
|
|
81
81
|
|
|
82
|
-
def _autotile_tiles(self, rules:
|
|
82
|
+
def _autotile_tiles(self, rules: list["AutotileRule"], positions: list[tuple[int, int]]) -> int:
|
|
83
83
|
"""
|
|
84
84
|
Internal helper to update specific tiles according to autotile rules.
|
|
85
85
|
|
|
@@ -99,9 +99,9 @@ class Layer:
|
|
|
99
99
|
rules_hash = hash(tuple((r.group_id, r.tileset_index, tuple(sorted(r.variant_ids))) for r in rules))
|
|
100
100
|
|
|
101
101
|
if self._autotile_cache["rules_hash"] != rules_hash:
|
|
102
|
-
variant_to_group:
|
|
103
|
-
rules_by_group:
|
|
104
|
-
significant_offsets:
|
|
102
|
+
variant_to_group: dict[tuple[int, int], str] = {}
|
|
103
|
+
rules_by_group: dict[str, list[AutotileRule]] = {}
|
|
104
|
+
significant_offsets: set[tuple[int, int]] = set()
|
|
105
105
|
|
|
106
106
|
for rule in rules:
|
|
107
107
|
gid = rule.group_id
|
|
@@ -133,7 +133,7 @@ class Layer:
|
|
|
133
133
|
|
|
134
134
|
changes_count = 0
|
|
135
135
|
|
|
136
|
-
def _get_group(t: dict) ->
|
|
136
|
+
def _get_group(t: dict) -> str | None:
|
|
137
137
|
"""Get group_id for a tile: autotile_group field > legacy variant lookup."""
|
|
138
138
|
ag = t.get("autotile_group")
|
|
139
139
|
if ag is not None:
|
|
@@ -176,8 +176,8 @@ class Layer:
|
|
|
176
176
|
|
|
177
177
|
neighbor_offsets_set = {n for n in actual_neighbors if n in significant_offsets}
|
|
178
178
|
|
|
179
|
-
matched_rule:
|
|
180
|
-
new_variant:
|
|
179
|
+
matched_rule: AutotileRule | None = None
|
|
180
|
+
new_variant: int | None = None
|
|
181
181
|
for rule in group_rules:
|
|
182
182
|
if rule.neighbors == neighbor_offsets_set and rule.tileset_index == ttype:
|
|
183
183
|
matched_rule = rule
|
|
@@ -201,7 +201,7 @@ class Layer:
|
|
|
201
201
|
|
|
202
202
|
return changes_count
|
|
203
203
|
|
|
204
|
-
def remove_tile(self, pos:
|
|
204
|
+
def remove_tile(self, pos: tuple[int, int]) -> bool:
|
|
205
205
|
"""Remove a tile at the given grid position. Returns True if tile existed."""
|
|
206
206
|
if not self.locked and pos in self.tiles:
|
|
207
207
|
del self.tiles[pos]
|
|
@@ -210,9 +210,9 @@ class Layer:
|
|
|
210
210
|
|
|
211
211
|
def flood_fill(
|
|
212
212
|
self,
|
|
213
|
-
start_pos:
|
|
213
|
+
start_pos: tuple[int, int],
|
|
214
214
|
new_tile_data: TypeTile,
|
|
215
|
-
map_size:
|
|
215
|
+
map_size: tuple[int, int],
|
|
216
216
|
) -> None:
|
|
217
217
|
"""Replace contiguous tiles of the same type starting from start_pos."""
|
|
218
218
|
if self.locked or self.layer_type != "tile":
|
|
@@ -252,11 +252,11 @@ class Layer:
|
|
|
252
252
|
seen.add(next_pos)
|
|
253
253
|
queue.append(next_pos)
|
|
254
254
|
|
|
255
|
-
def get_all_tiles(self) ->
|
|
255
|
+
def get_all_tiles(self) -> dict[tuple[int, int], TypeTile]:
|
|
256
256
|
"""Return a copy of all tiles in this layer."""
|
|
257
257
|
return dict(self.tiles)
|
|
258
258
|
|
|
259
|
-
def add_object(self, pos:
|
|
259
|
+
def add_object(self, pos: tuple[int, int], obj: TypeObject) -> int:
|
|
260
260
|
"""Add an object at the given pixel position. Returns the object ID."""
|
|
261
261
|
if not self.locked:
|
|
262
262
|
obj_id = self.next_object_id
|
|
@@ -265,7 +265,7 @@ class Layer:
|
|
|
265
265
|
return obj_id
|
|
266
266
|
return -1
|
|
267
267
|
|
|
268
|
-
def get_object(self, obj_id: int) ->
|
|
268
|
+
def get_object(self, obj_id: int) -> TypeObject | None:
|
|
269
269
|
"""Get an object by ID."""
|
|
270
270
|
return self.objects.get(obj_id)
|
|
271
271
|
|
|
@@ -276,11 +276,11 @@ class Layer:
|
|
|
276
276
|
return True
|
|
277
277
|
return False
|
|
278
278
|
|
|
279
|
-
def get_all_objects(self) ->
|
|
279
|
+
def get_all_objects(self) -> dict[int, TypeObject]:
|
|
280
280
|
"""Return a copy of all objects in this layer."""
|
|
281
281
|
return dict(self.objects)
|
|
282
282
|
|
|
283
|
-
def move_object(self, obj_id: int, new_pos:
|
|
283
|
+
def move_object(self, obj_id: int, new_pos: tuple[int, int]) -> bool:
|
|
284
284
|
"""Move an object to a new position. Returns True if successful."""
|
|
285
285
|
if not self.locked and obj_id in self.objects:
|
|
286
286
|
self.objects[obj_id]["area"]["x"] = new_pos[0]
|
|
@@ -364,14 +364,14 @@ class LayerManager:
|
|
|
364
364
|
"""Manages multiple layers for a tilemap."""
|
|
365
365
|
|
|
366
366
|
def __init__(self):
|
|
367
|
-
self.layers:
|
|
367
|
+
self.layers: list[Layer] = []
|
|
368
368
|
self.active_layer_idx: int = -1
|
|
369
369
|
|
|
370
370
|
def create_layer(
|
|
371
371
|
self,
|
|
372
372
|
name: str,
|
|
373
373
|
layer_type: str = "tile",
|
|
374
|
-
insert_index:
|
|
374
|
+
insert_index: int | None = None,
|
|
375
375
|
) -> Layer:
|
|
376
376
|
"""Create a new layer and add it to the manager."""
|
|
377
377
|
z_index = len(self.layers)
|
|
@@ -402,13 +402,13 @@ class LayerManager:
|
|
|
402
402
|
|
|
403
403
|
return True
|
|
404
404
|
|
|
405
|
-
def get_layer(self, index: int) ->
|
|
405
|
+
def get_layer(self, index: int) -> Layer | None:
|
|
406
406
|
"""Get a layer by index."""
|
|
407
407
|
if 0 <= index < len(self.layers):
|
|
408
408
|
return self.layers[index]
|
|
409
409
|
return None
|
|
410
410
|
|
|
411
|
-
def get_active_layer(self) ->
|
|
411
|
+
def get_active_layer(self) -> Layer | None:
|
|
412
412
|
"""Get the currently active layer."""
|
|
413
413
|
return self.get_layer(self.active_layer_idx)
|
|
414
414
|
|
|
@@ -432,7 +432,7 @@ class LayerManager:
|
|
|
432
432
|
return True
|
|
433
433
|
return False
|
|
434
434
|
|
|
435
|
-
def get_rendered_layers(self) ->
|
|
435
|
+
def get_rendered_layers(self) -> list[Layer]:
|
|
436
436
|
"""Get all visible layers sorted by z_index for rendering."""
|
|
437
437
|
visible = [layer for layer in self.layers if layer.visible]
|
|
438
438
|
return sorted(visible, key=lambda l: l.z_index)
|