├── .gitignore ├── .pylintrc ├── COPYING ├── Makefile ├── NEWS.md ├── README.md ├── data ├── gui │ ├── checkbox │ │ ├── checked.tga │ │ ├── checked_disabled.tga │ │ ├── unchecked.tga │ │ └── unchecked_disabled.tga │ ├── fonts │ │ ├── font_black.tga │ │ └── font_gray.tga │ ├── menu │ │ ├── arrow.png │ │ ├── checked.png │ │ └── unchecked.png │ └── radiobutton │ │ ├── checked.tga │ │ ├── checked_disabled.tga │ │ ├── unchecked.tga │ │ └── unchecked_disabled.tga ├── images │ ├── brush │ │ ├── brush.png │ │ ├── brush2.png │ │ ├── brush3.png │ │ ├── brush4.png │ │ ├── brush5.png │ │ ├── brush6.png │ │ ├── brush7.png │ │ └── brush8.png │ ├── files │ │ ├── directory.png │ │ └── file.png │ ├── fonts │ │ ├── verdana11_black.png │ │ └── verdana11_yellow.png │ ├── icons16 │ │ ├── addon_package-16.png │ │ ├── resize1.png │ │ ├── resize2.png │ │ ├── resize_horz.png │ │ ├── resize_vert.png │ │ ├── stock_about-16.png │ │ ├── stock_attach-16.png │ │ ├── stock_book-16.png │ │ ├── stock_bottom-16.png │ │ ├── stock_broken_image-16.png │ │ ├── stock_cdrom-16.png │ │ ├── stock_convert-16.png │ │ ├── stock_copy-16.png │ │ ├── stock_cut-16.png │ │ ├── stock_delete-16.png │ │ ├── stock_down-16.png │ │ ├── stock_edit-16.png │ │ ├── stock_exec-16.png │ │ ├── stock_exit-16.png │ │ ├── stock_export-16.png │ │ ├── stock_first-16.png │ │ ├── stock_font-16.png │ │ ├── stock_help-16.png │ │ ├── stock_home-16.png │ │ ├── stock_import-16.png │ │ ├── stock_insert-image-16.png │ │ ├── stock_insert-object-16.png │ │ ├── stock_insert-table-16.png │ │ ├── stock_jump-to-16.png │ │ ├── stock_last-16.png │ │ ├── stock_left-16.png │ │ ├── stock_line_in-16.png │ │ ├── stock_mike-16.png │ │ ├── stock_new-16.png │ │ ├── stock_open-16.png │ │ ├── stock_paste-16.png │ │ ├── stock_preferences-16.png │ │ ├── stock_print-16.png │ │ ├── stock_print-preview-16.png │ │ ├── stock_properties-16.png │ │ ├── stock_redo-16.png │ │ ├── stock_refresh-16.png │ │ ├── stock_revert-16.png │ │ ├── stock_right-16.png │ │ ├── stock_save-16.png │ │ ├── stock_save_as-16.png │ │ ├── stock_search-16.png │ │ ├── stock_search_and_replace-16.png │ │ ├── stock_spellcheck-16.png │ │ ├── stock_stop-16.png │ │ ├── stock_text_align_center-16.png │ │ ├── stock_text_align_justify-16.png │ │ ├── stock_text_align_left-16.png │ │ ├── stock_text_align_right-16.png │ │ ├── stock_text_bold-16.png │ │ ├── stock_text_italic-16.png │ │ ├── stock_text_strikethrough-16.png │ │ ├── stock_text_underlined-16.png │ │ ├── stock_top-16.png │ │ ├── stock_undelete-16.png │ │ ├── stock_undo-16.png │ │ ├── stock_up-16.png │ │ └── stock_volume-16.png │ ├── icons24 │ │ ├── anim_fastbackward.png │ │ ├── anim_fastforward.png │ │ ├── anim_next.png │ │ ├── anim_play.png │ │ ├── anim_playbackward.png │ │ ├── anim_previous.png │ │ ├── anim_skipbackward.png │ │ ├── anim_skipforward.png │ │ ├── anim_slowmotion.png │ │ ├── anim_slowmotionbackward.png │ │ ├── background.png │ │ ├── downarrow.png │ │ ├── eye.png │ │ ├── foreground.png │ │ ├── grid.png │ │ ├── index.html │ │ ├── interactive.png │ │ ├── minimap.png │ │ ├── object_flip_horizontal.png │ │ ├── object_flip_vertical.png │ │ ├── object_hflip.png │ │ ├── object_lower.png │ │ ├── object_lower_to_bottom.png │ │ ├── object_raise.png │ │ ├── object_raise_to_top.png │ │ ├── object_rotate270.png │ │ ├── object_rotate90.png │ │ ├── object_tobottom.png │ │ ├── object_totop.png │ │ ├── object_vflip.png │ │ ├── run.png │ │ ├── secretarea.png │ │ ├── sector.png │ │ ├── stock_about.png │ │ ├── stock_attach.png │ │ ├── stock_book-open.png │ │ ├── stock_book.png │ │ ├── stock_bottom.png │ │ ├── stock_broken_image.png │ │ ├── stock_cancel.png │ │ ├── stock_cdrom.png │ │ ├── stock_convert.png │ │ ├── stock_copy.png │ │ ├── stock_cut.png │ │ ├── stock_delete.png │ │ ├── stock_down.png │ │ ├── stock_edit.png │ │ ├── stock_exec.png │ │ ├── stock_exit.png │ │ ├── stock_export.png │ │ ├── stock_first.png │ │ ├── stock_font.png │ │ ├── stock_help.png │ │ ├── stock_home.png │ │ ├── stock_import.png │ │ ├── stock_insert-image.png │ │ ├── stock_insert-object.png │ │ ├── stock_insert-table.png │ │ ├── stock_jump-to.png │ │ ├── stock_last.png │ │ ├── stock_left.png │ │ ├── stock_line_in.png │ │ ├── stock_media-fwd.png │ │ ├── stock_media-next.png │ │ ├── stock_media-pause.png │ │ ├── stock_media-play.png │ │ ├── stock_media-prev.png │ │ ├── stock_media-rec.png │ │ ├── stock_media-rew.png │ │ ├── stock_media-stop.png │ │ ├── stock_mike.png │ │ ├── stock_new.png │ │ ├── stock_ok.png │ │ ├── stock_open.png │ │ ├── stock_palette.png │ │ ├── stock_paste.png │ │ ├── stock_preferences.png │ │ ├── stock_print-preview.png │ │ ├── stock_print.png │ │ ├── stock_properties.png │ │ ├── stock_redo.png │ │ ├── stock_refresh.png │ │ ├── stock_revert.png │ │ ├── stock_right.png │ │ ├── stock_save.png │ │ ├── stock_save_as.png │ │ ├── stock_search.png │ │ ├── stock_search_and_replace.png │ │ ├── stock_spellcheck.png │ │ ├── stock_stop.png │ │ ├── stock_text_align_center.png │ │ ├── stock_text_align_justify.png │ │ ├── stock_text_align_left.png │ │ ├── stock_text_align_right.png │ │ ├── stock_text_bold.png │ │ ├── stock_text_italic.png │ │ ├── stock_text_strikethrough.png │ │ ├── stock_text_underline.png │ │ ├── stock_top.png │ │ ├── stock_undelete.png │ │ ├── stock_undo.png │ │ ├── stock_up.png │ │ ├── stock_volume.png │ │ ├── stock_zoom_1.png │ │ ├── stock_zoom_fit.png │ │ ├── stock_zoom_in.png │ │ └── stock_zoom_out.png │ ├── supertux │ │ ├── minus.png │ │ ├── plus.png │ │ ├── stock-eye-12.png │ │ ├── stock-eye-half-12.png │ │ └── supertux-editor.png │ ├── tools │ │ ├── select.png │ │ ├── stock-tool-clone-22.png │ │ ├── stock-tool-color-picker-22.png │ │ ├── stock-tool-crop-22.png │ │ ├── stock-tool-eraser-16.png │ │ ├── stock-tool-eraser-22.png │ │ ├── stock-tool-fill-24.png │ │ ├── stock-tool-move-22.png │ │ ├── stock-tool-pencil-22.png │ │ ├── stock-tool-rect-select-22.png │ │ ├── stock-tool-replace-24.png │ │ ├── stock-tool-tiles-24.png │ │ └── stock-tool-zoom-22.png │ └── window │ │ ├── close.png │ │ ├── maximize.png │ │ ├── minimize.png │ │ └── rollup.png └── supertux │ ├── demos │ └── karkus476_plays_level_1 │ ├── smarttiles.csv │ └── smarttiles_mapping.csv ├── flake.lock ├── flake.nix ├── flexlay ├── __init__.py ├── blend_func.py ├── blitter.py ├── color.py ├── commands │ ├── __init__.py │ ├── command.py │ ├── command_group.py │ ├── layer_delete_command.py │ ├── object_add_command.py │ ├── object_delete_command.py │ ├── object_move_command.py │ ├── object_transform_command.py │ └── paint_command.py ├── drawer_properties.py ├── editor_map.py ├── field.py ├── flexlay.py ├── graphic_context.py ├── graphic_context_state.py ├── gui │ ├── __init__.py │ ├── button_panel.py │ ├── colorpicker.py │ ├── editor_map_component.py │ ├── editor_map_widget.py │ ├── file_dialog.py │ ├── generic_dialog.py │ ├── generic_wizard.py │ ├── icon.py │ ├── layer_selector.py │ ├── menubar.py │ ├── minimap.py │ ├── minimap_widget.py │ ├── object_selector.py │ ├── object_selector_widget.py │ ├── project_widget.py │ ├── properties_widget.py │ ├── smart_tile_selector_widget.py │ ├── statusbar.py │ ├── tile_brush_selector.py │ ├── tile_selection.py │ ├── tile_selector.py │ └── tile_selector_widget.py ├── gui_manager.py ├── input_event.py ├── layer.py ├── math │ ├── __init__.py │ ├── origin.py │ ├── point.py │ ├── rect.py │ └── size.py ├── object_brush.py ├── object_layer.py ├── objmap_control_point.py ├── objmap_object.py ├── objmap_path_node.py ├── objmap_rect_object.py ├── objmap_sprite_object.py ├── objmap_tilemap_object.py ├── pixel_buffer.py ├── property.py ├── sprite.py ├── sprite_brush.py ├── tile.py ├── tile_brush.py ├── tilemap_layer.py ├── tileset.py ├── tool_context.py ├── tools │ ├── __init__.py │ ├── layer_move_tool.py │ ├── objmap_select_tool.py │ ├── tile_brush_create_tool.py │ ├── tile_fill_tool.py │ ├── tile_paint_tool.py │ ├── tile_replace_tool.py │ ├── tilemap_select_tool.py │ ├── tool.py │ ├── workspace_move_tool.py │ ├── zoom2_tool.py │ ├── zoom_out_tool.py │ └── zoom_tool.py ├── util │ ├── __init__.py │ ├── config.py │ ├── sexpr.py │ ├── sexpr_reader.py │ ├── sexpr_writer.py │ ├── signal.py │ └── version.py ├── wip │ ├── __init__.py │ ├── bitmap_layer.py │ ├── brush.py │ ├── brushmask.py │ ├── canvas.py │ ├── display.py │ ├── onion_skin_layer.py │ ├── sketch_layer.py │ ├── sketch_stroke_tool.py │ ├── sprite_stroke_drawer.py │ ├── stroke.py │ ├── stroke_drawer.py │ ├── surface.py │ └── tile_provider.py └── workspace.py ├── logo.png ├── logo.svg ├── pyproject.toml ├── setup.cfg ├── setup.py ├── simpleed.py ├── supertux-editor ├── supertux-level ├── supertux ├── TODO ├── __init__.py ├── __main__.py ├── addon.py ├── addon_dialog.py ├── badguys.py ├── button_panel.py ├── config.py ├── constraint.py ├── data.py ├── gameobj.py ├── gameobj_factor.py ├── gameobj_props_change_command.py ├── gameobjs.py ├── gui.py ├── level.py ├── level_file_dialog.py ├── menubar.py ├── new_addon.py ├── new_level.py ├── property.py ├── sector.py ├── sprite.py ├── supertux.py ├── supertux_arguments.py ├── text_editor │ ├── __init__.py │ ├── cmd_supertux_textedit.py │ ├── example.stl │ ├── highlighters │ │ ├── __init__.py │ │ ├── highlighter.py │ │ ├── lisp_highlighter.py │ │ ├── patterns.json │ │ ├── patterns2.json │ │ └── squirrel_highlighter.py │ └── supertux_text_edit.py ├── tilemap.py ├── tileset.py ├── toolbox.py ├── util.py └── worldmap_object.py └── tests ├── test.stl ├── test_flexlay.py ├── test_generic_dialog.py ├── test_generic_wizard.py ├── test_math.py ├── test_sexpr.py ├── test_signal.py ├── test_supertux.py └── test_supertux_properties.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | *.os 4 | *.pyc 5 | *.so 6 | *.so.* 7 | *~ 8 | .idea/ 9 | .sconsign.dblite 10 | /.mypy_cache/ 11 | /.pylint/ 12 | /TODO 13 | /build/ 14 | /flexlay.egg-info/ 15 | /libflexlay/flexlay_wrap_wrap.cc 16 | /libflexlay/libflexlay.so 17 | /netpanzer/netpanzer_wrap.cc 18 | /netpanzer/netpanzer_wrap.so 19 | /old 20 | /ruby/flexlay_wrap.so 21 | /simple/simple 22 | /result 23 | moc_*.cpp 24 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | disable= 3 | invalid-name 4 | # missing-docstring, 5 | # too-many-instance-attributes, 6 | # too-few-public-methods, 7 | # no-self-use, 8 | # fixme, 9 | # unused-argument, 10 | # locally-disabled, 11 | # no-else-return, 12 | # too-many-locals, 13 | # protected-access, 14 | # broad-except, 15 | # wrong-import-position, 16 | # too-many-arguments, 17 | # unused-variable, 18 | # too-many-branches, 19 | # len-as-condition, 20 | # wrong-import-order, 21 | # too-many-nested-blocks, 22 | # too-many-return-statements 23 | # generated-members=sys.stdout.buffer,sys.stderr.buffer 24 | 25 | 26 | # W0108: unneccesary lambda 27 | # W0511: FIXME 28 | # W0613: unused arguments 29 | # disable=W0511,W0613,W0108 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2018 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | SOURCES := $(wildcard flexlay/*.py flexlay/*/*.py supertux/*.py tests/*.py) 18 | 19 | default: flake mypy # test 20 | 21 | all: autopep flake test pylint 22 | 23 | autopep: 24 | autopep8 --max-line=120 --in-place --aggressive $(SOURCES) 25 | 26 | test: 27 | python3 -m unittest discover -v -s tests/ 28 | 29 | mypy: 30 | mypy \ 31 | --incremental \ 32 | --ignore-missing-imports \ 33 | --follow-imports skip \ 34 | --warn-return-any \ 35 | --warn-unused-ignores \ 36 | --warn-incomplete-stub \ 37 | --warn-redundant-casts \ 38 | $(SOURCES) 39 | 40 | mypyverbose: 41 | export MYPYPATH=/usr/lib/python3/dist-packages/; \ 42 | mypy \ 43 | --incremental \ 44 | --ignore-missing-imports \ 45 | --follow-imports silent \ 46 | --check-untyped-defs \ 47 | --warn-return-any \ 48 | --warn-unused-ignores \ 49 | --warn-incomplete-stub \ 50 | --warn-redundant-casts \ 51 | $(SOURCES) | \ 52 | grep -v ^/usr | \ 53 | fgrep -v '"pyqtSignal" has no attribute' | \ 54 | grep -v 'Callable.*has no attribute "connect' | \ 55 | fgrep -v 'No overload variant of "QAction" matches argument types' 56 | 57 | # --disallow-any unimported,unannotated,decorated,explicit,generics \ 58 | # --disallow-any unimported,expr,unannotated,decorated,explicit,generics \ 59 | 60 | flake: 61 | flake8 --max-line-length=120 --ignore=N802,W504 $(SOURCES) 62 | 63 | PYLINT_TARGETS := $(addprefix .pylint/, $(SOURCES)) 64 | 65 | $(PYLINT_TARGETS): .pylint/%.py: %.py 66 | mkdir -p $(dir $@) 67 | PYTHONPATH=. epylint3 $< --rcfile=.pylintrc --max-line-length=120 --extension-pkg-whitelist=PyQt5 68 | touch $@ 69 | 70 | pylint: $(PYLINT_TARGETS) 71 | 72 | clean: 73 | rm -vrf .pylint/ 74 | 75 | install: 76 | sudo -H pip3 install --force-reinstall --upgrade . 77 | 78 | .PHONY: autopep test flake pylint clean all default run 79 | 80 | .NOTPARALLEL: all 81 | 82 | # EOF # 83 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # Flexlay release and development notes 2 | 3 | ## Flexlay 1.0.0 (WIP for SuperTux 0.5.0) 4 | 5 | - Flexlay is now being developed by The SuperTux Team, primarily for SuperTux 6 | level editing 7 | - Flexlay will follow [SemVer](http://semver.org/) (just as SuperTux does) 8 | - Removed C++ and Ruby support altogether, Flexlay now uses only Python 3 with 9 | PyQt 4. Many features from old C++ editor are lost 10 | - Added SuperTux level creation wizard 11 | 12 | ## Flexlay 0.1.0 13 | 14 | - Split Flexlay into a C++ library and a scripting modules, Ruby and (very limited) 15 | Python support is now available 16 | - Restructured the scripting bindings 17 | - C++ object hierachy now completly available in scripting 18 | - Switched build system from autohell to SCons 19 | - Support for resizable rectangular objects 20 | - Better support for sprite objects 21 | - Support for constrained object movement 22 | - Major GUI cleanup 23 | - An icon-toolbar 24 | - Configurable keyboard shortcut support 25 | - SuperTux: support for multiple sublevels and most features of lasted development 26 | version 27 | - NetPanzer: support for object based level building, no more need to mess with 28 | raw tiles 29 | - Pingus: basic support for loading levels and saving them, however only limited 30 | editing capabilties 31 | - Paint: a simple paint application with support for animation 32 | 33 | ## Flexlay 0.0.1 34 | 35 | - First release 36 | - Zoom support 37 | - Multilayer tilemap support 38 | - Tilemap to png converting 39 | - Tile brushes 40 | - Simple copy/paste 41 | - Undo/redo 42 | - Game object support 43 | - SuperTux support 44 | - netPanzer support 45 | - Windstille support 46 | - Pingus support (load only) 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Flexlay 2 | ======= 3 | 4 | Flexlay is a generic 2d editor framework with special focus on games. 5 | It is written in Python3 and uses Qt5. It currently supports multi 6 | layered tile-, object- and bitmaps, full undo/redo, support for 7 | tile-brushes, easy copy/paste, multiple buffers, minimap support, a 8 | metadata editor and some other stuff usefull for creating levels for 9 | 2d games. 10 | 11 | Supported games: 12 | 13 | * [SuperTux](http://www.supertux.org/) 14 | * [netPanzer](https://sourceforge.net/projects/netpanzer.berlios/) (currently defunct in `master`, see `flexlay-clanlib-master` tag) 15 | 16 | Since Flexlay is a framework and not an editor itself, it has to be 17 | started via a game specific script (e.g. supertux-editor, 18 | netpanzer-editor). 19 | 20 | To run the SuperTux version of Flexlay, see [the 21 | wiki](https://github.com/SuperTux/flexlay/wiki/Installing-the-Flexlay-SuperTux-editor). 22 | 23 | Flexlay is covered under the GNU GPL, which means that you can copy 24 | and even modify it pretty much as you like, as long as you keep the 25 | copyright headers in place and distribute the source too if you 26 | distribute binaries, see the file COPYING for details. 27 | -------------------------------------------------------------------------------- /data/gui/checkbox/checked.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/checkbox/checked.tga -------------------------------------------------------------------------------- /data/gui/checkbox/checked_disabled.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/checkbox/checked_disabled.tga -------------------------------------------------------------------------------- /data/gui/checkbox/unchecked.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/checkbox/unchecked.tga -------------------------------------------------------------------------------- /data/gui/checkbox/unchecked_disabled.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/checkbox/unchecked_disabled.tga -------------------------------------------------------------------------------- /data/gui/fonts/font_black.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/fonts/font_black.tga -------------------------------------------------------------------------------- /data/gui/fonts/font_gray.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/fonts/font_gray.tga -------------------------------------------------------------------------------- /data/gui/menu/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/menu/arrow.png -------------------------------------------------------------------------------- /data/gui/menu/checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/menu/checked.png -------------------------------------------------------------------------------- /data/gui/menu/unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/menu/unchecked.png -------------------------------------------------------------------------------- /data/gui/radiobutton/checked.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/radiobutton/checked.tga -------------------------------------------------------------------------------- /data/gui/radiobutton/checked_disabled.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/radiobutton/checked_disabled.tga -------------------------------------------------------------------------------- /data/gui/radiobutton/unchecked.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/radiobutton/unchecked.tga -------------------------------------------------------------------------------- /data/gui/radiobutton/unchecked_disabled.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/gui/radiobutton/unchecked_disabled.tga -------------------------------------------------------------------------------- /data/images/brush/brush.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush.png -------------------------------------------------------------------------------- /data/images/brush/brush2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush2.png -------------------------------------------------------------------------------- /data/images/brush/brush3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush3.png -------------------------------------------------------------------------------- /data/images/brush/brush4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush4.png -------------------------------------------------------------------------------- /data/images/brush/brush5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush5.png -------------------------------------------------------------------------------- /data/images/brush/brush6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush6.png -------------------------------------------------------------------------------- /data/images/brush/brush7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush7.png -------------------------------------------------------------------------------- /data/images/brush/brush8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/brush/brush8.png -------------------------------------------------------------------------------- /data/images/files/directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/files/directory.png -------------------------------------------------------------------------------- /data/images/files/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/files/file.png -------------------------------------------------------------------------------- /data/images/fonts/verdana11_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/fonts/verdana11_black.png -------------------------------------------------------------------------------- /data/images/fonts/verdana11_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/fonts/verdana11_yellow.png -------------------------------------------------------------------------------- /data/images/icons16/addon_package-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/addon_package-16.png -------------------------------------------------------------------------------- /data/images/icons16/resize1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/resize1.png -------------------------------------------------------------------------------- /data/images/icons16/resize2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/resize2.png -------------------------------------------------------------------------------- /data/images/icons16/resize_horz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/resize_horz.png -------------------------------------------------------------------------------- /data/images/icons16/resize_vert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/resize_vert.png -------------------------------------------------------------------------------- /data/images/icons16/stock_about-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_about-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_attach-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_attach-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_book-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_book-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_bottom-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_bottom-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_broken_image-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_broken_image-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_cdrom-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_cdrom-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_convert-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_convert-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_copy-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_copy-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_cut-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_cut-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_delete-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_delete-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_down-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_down-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_edit-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_edit-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_exec-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_exec-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_exit-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_exit-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_export-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_export-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_first-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_first-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_font-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_font-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_help-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_help-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_home-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_home-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_import-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_import-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_insert-image-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_insert-image-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_insert-object-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_insert-object-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_insert-table-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_insert-table-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_jump-to-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_jump-to-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_last-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_last-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_left-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_left-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_line_in-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_line_in-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_mike-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_mike-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_new-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_new-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_open-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_open-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_paste-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_paste-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_preferences-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_preferences-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_print-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_print-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_print-preview-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_print-preview-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_properties-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_properties-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_redo-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_redo-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_refresh-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_refresh-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_revert-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_revert-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_right-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_right-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_save-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_save-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_save_as-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_save_as-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_search-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_search-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_search_and_replace-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_search_and_replace-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_spellcheck-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_spellcheck-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_stop-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_stop-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_align_center-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_align_center-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_align_justify-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_align_justify-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_align_left-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_align_left-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_align_right-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_align_right-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_bold-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_bold-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_italic-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_italic-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_strikethrough-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_strikethrough-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_text_underlined-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_text_underlined-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_top-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_top-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_undelete-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_undelete-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_undo-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_undo-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_up-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_up-16.png -------------------------------------------------------------------------------- /data/images/icons16/stock_volume-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons16/stock_volume-16.png -------------------------------------------------------------------------------- /data/images/icons24/anim_fastbackward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_fastbackward.png -------------------------------------------------------------------------------- /data/images/icons24/anim_fastforward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_fastforward.png -------------------------------------------------------------------------------- /data/images/icons24/anim_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_next.png -------------------------------------------------------------------------------- /data/images/icons24/anim_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_play.png -------------------------------------------------------------------------------- /data/images/icons24/anim_playbackward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_playbackward.png -------------------------------------------------------------------------------- /data/images/icons24/anim_previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_previous.png -------------------------------------------------------------------------------- /data/images/icons24/anim_skipbackward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_skipbackward.png -------------------------------------------------------------------------------- /data/images/icons24/anim_skipforward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_skipforward.png -------------------------------------------------------------------------------- /data/images/icons24/anim_slowmotion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_slowmotion.png -------------------------------------------------------------------------------- /data/images/icons24/anim_slowmotionbackward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/anim_slowmotionbackward.png -------------------------------------------------------------------------------- /data/images/icons24/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/background.png -------------------------------------------------------------------------------- /data/images/icons24/downarrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/downarrow.png -------------------------------------------------------------------------------- /data/images/icons24/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/eye.png -------------------------------------------------------------------------------- /data/images/icons24/foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/foreground.png -------------------------------------------------------------------------------- /data/images/icons24/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/grid.png -------------------------------------------------------------------------------- /data/images/icons24/interactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/interactive.png -------------------------------------------------------------------------------- /data/images/icons24/minimap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/minimap.png -------------------------------------------------------------------------------- /data/images/icons24/object_flip_horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_flip_horizontal.png -------------------------------------------------------------------------------- /data/images/icons24/object_flip_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_flip_vertical.png -------------------------------------------------------------------------------- /data/images/icons24/object_hflip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_hflip.png -------------------------------------------------------------------------------- /data/images/icons24/object_lower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_lower.png -------------------------------------------------------------------------------- /data/images/icons24/object_lower_to_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_lower_to_bottom.png -------------------------------------------------------------------------------- /data/images/icons24/object_raise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_raise.png -------------------------------------------------------------------------------- /data/images/icons24/object_raise_to_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_raise_to_top.png -------------------------------------------------------------------------------- /data/images/icons24/object_rotate270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_rotate270.png -------------------------------------------------------------------------------- /data/images/icons24/object_rotate90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_rotate90.png -------------------------------------------------------------------------------- /data/images/icons24/object_tobottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_tobottom.png -------------------------------------------------------------------------------- /data/images/icons24/object_totop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_totop.png -------------------------------------------------------------------------------- /data/images/icons24/object_vflip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/object_vflip.png -------------------------------------------------------------------------------- /data/images/icons24/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/run.png -------------------------------------------------------------------------------- /data/images/icons24/secretarea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/secretarea.png -------------------------------------------------------------------------------- /data/images/icons24/sector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/sector.png -------------------------------------------------------------------------------- /data/images/icons24/stock_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_about.png -------------------------------------------------------------------------------- /data/images/icons24/stock_attach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_attach.png -------------------------------------------------------------------------------- /data/images/icons24/stock_book-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_book-open.png -------------------------------------------------------------------------------- /data/images/icons24/stock_book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_book.png -------------------------------------------------------------------------------- /data/images/icons24/stock_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_bottom.png -------------------------------------------------------------------------------- /data/images/icons24/stock_broken_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_broken_image.png -------------------------------------------------------------------------------- /data/images/icons24/stock_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_cancel.png -------------------------------------------------------------------------------- /data/images/icons24/stock_cdrom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_cdrom.png -------------------------------------------------------------------------------- /data/images/icons24/stock_convert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_convert.png -------------------------------------------------------------------------------- /data/images/icons24/stock_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_copy.png -------------------------------------------------------------------------------- /data/images/icons24/stock_cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_cut.png -------------------------------------------------------------------------------- /data/images/icons24/stock_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_delete.png -------------------------------------------------------------------------------- /data/images/icons24/stock_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_down.png -------------------------------------------------------------------------------- /data/images/icons24/stock_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_edit.png -------------------------------------------------------------------------------- /data/images/icons24/stock_exec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_exec.png -------------------------------------------------------------------------------- /data/images/icons24/stock_exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_exit.png -------------------------------------------------------------------------------- /data/images/icons24/stock_export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_export.png -------------------------------------------------------------------------------- /data/images/icons24/stock_first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_first.png -------------------------------------------------------------------------------- /data/images/icons24/stock_font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_font.png -------------------------------------------------------------------------------- /data/images/icons24/stock_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_help.png -------------------------------------------------------------------------------- /data/images/icons24/stock_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_home.png -------------------------------------------------------------------------------- /data/images/icons24/stock_import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_import.png -------------------------------------------------------------------------------- /data/images/icons24/stock_insert-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_insert-image.png -------------------------------------------------------------------------------- /data/images/icons24/stock_insert-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_insert-object.png -------------------------------------------------------------------------------- /data/images/icons24/stock_insert-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_insert-table.png -------------------------------------------------------------------------------- /data/images/icons24/stock_jump-to.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_jump-to.png -------------------------------------------------------------------------------- /data/images/icons24/stock_last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_last.png -------------------------------------------------------------------------------- /data/images/icons24/stock_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_left.png -------------------------------------------------------------------------------- /data/images/icons24/stock_line_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_line_in.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-fwd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-fwd.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-next.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-pause.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-play.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-prev.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-rec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-rec.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-rew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-rew.png -------------------------------------------------------------------------------- /data/images/icons24/stock_media-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_media-stop.png -------------------------------------------------------------------------------- /data/images/icons24/stock_mike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_mike.png -------------------------------------------------------------------------------- /data/images/icons24/stock_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_new.png -------------------------------------------------------------------------------- /data/images/icons24/stock_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_ok.png -------------------------------------------------------------------------------- /data/images/icons24/stock_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_open.png -------------------------------------------------------------------------------- /data/images/icons24/stock_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_palette.png -------------------------------------------------------------------------------- /data/images/icons24/stock_paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_paste.png -------------------------------------------------------------------------------- /data/images/icons24/stock_preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_preferences.png -------------------------------------------------------------------------------- /data/images/icons24/stock_print-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_print-preview.png -------------------------------------------------------------------------------- /data/images/icons24/stock_print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_print.png -------------------------------------------------------------------------------- /data/images/icons24/stock_properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_properties.png -------------------------------------------------------------------------------- /data/images/icons24/stock_redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_redo.png -------------------------------------------------------------------------------- /data/images/icons24/stock_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_refresh.png -------------------------------------------------------------------------------- /data/images/icons24/stock_revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_revert.png -------------------------------------------------------------------------------- /data/images/icons24/stock_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_right.png -------------------------------------------------------------------------------- /data/images/icons24/stock_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_save.png -------------------------------------------------------------------------------- /data/images/icons24/stock_save_as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_save_as.png -------------------------------------------------------------------------------- /data/images/icons24/stock_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_search.png -------------------------------------------------------------------------------- /data/images/icons24/stock_search_and_replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_search_and_replace.png -------------------------------------------------------------------------------- /data/images/icons24/stock_spellcheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_spellcheck.png -------------------------------------------------------------------------------- /data/images/icons24/stock_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_stop.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_align_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_align_center.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_align_justify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_align_justify.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_align_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_align_left.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_align_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_align_right.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_bold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_bold.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_italic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_italic.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_strikethrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_strikethrough.png -------------------------------------------------------------------------------- /data/images/icons24/stock_text_underline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_text_underline.png -------------------------------------------------------------------------------- /data/images/icons24/stock_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_top.png -------------------------------------------------------------------------------- /data/images/icons24/stock_undelete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_undelete.png -------------------------------------------------------------------------------- /data/images/icons24/stock_undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_undo.png -------------------------------------------------------------------------------- /data/images/icons24/stock_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_up.png -------------------------------------------------------------------------------- /data/images/icons24/stock_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_volume.png -------------------------------------------------------------------------------- /data/images/icons24/stock_zoom_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_zoom_1.png -------------------------------------------------------------------------------- /data/images/icons24/stock_zoom_fit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_zoom_fit.png -------------------------------------------------------------------------------- /data/images/icons24/stock_zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_zoom_in.png -------------------------------------------------------------------------------- /data/images/icons24/stock_zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/icons24/stock_zoom_out.png -------------------------------------------------------------------------------- /data/images/supertux/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/supertux/minus.png -------------------------------------------------------------------------------- /data/images/supertux/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/supertux/plus.png -------------------------------------------------------------------------------- /data/images/supertux/stock-eye-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/supertux/stock-eye-12.png -------------------------------------------------------------------------------- /data/images/supertux/stock-eye-half-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/supertux/stock-eye-half-12.png -------------------------------------------------------------------------------- /data/images/supertux/supertux-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/supertux/supertux-editor.png -------------------------------------------------------------------------------- /data/images/tools/select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/select.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-clone-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-clone-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-color-picker-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-color-picker-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-crop-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-crop-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-eraser-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-eraser-16.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-eraser-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-eraser-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-fill-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-fill-24.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-move-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-move-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-pencil-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-pencil-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-rect-select-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-rect-select-22.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-replace-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-replace-24.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-tiles-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-tiles-24.png -------------------------------------------------------------------------------- /data/images/tools/stock-tool-zoom-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/tools/stock-tool-zoom-22.png -------------------------------------------------------------------------------- /data/images/window/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/window/close.png -------------------------------------------------------------------------------- /data/images/window/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/window/maximize.png -------------------------------------------------------------------------------- /data/images/window/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/window/minimize.png -------------------------------------------------------------------------------- /data/images/window/rollup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/data/images/window/rollup.png -------------------------------------------------------------------------------- /data/supertux/smarttiles.csv: -------------------------------------------------------------------------------- 1 | ID,label,width,height,start ID,reverse,max width,max height,mappings 2 | 0, Green pipe (horizontal),2,2,57,false,-1,2,53|55|1744|0|1745|56|54|0|55 3 | 1, Green pipe (vertical),2,2,53,true,2,-1,57|55|58|60|1743|55|1742|59|55 4 | 2, Small tree,2,12,1287,false 5 | 3, Medium tree,4,12,1239,false 6 | 4, Big tree,6,12,1167,false 7 | 5, Gigantic tree,8,12,1071,false 8 | 6, Horizontal block,3,1,27,false,-1,2,27|28|29|0|0|0|0|0|0 9 | 7, Vertical block,1,3,211,false,1,-1,211|0|0|0|0|0|213|212|0 10 | 8, Cloud,4,2,85,false 11 | 9, Run sign,2,2,136,false 12 | 10, Right sign,2,2,141,false 13 | 11, Rightup sign,2,2,1600,false 14 | 12, Rightdown sign,2,2,1604,false 15 | 13, Left sign,2,2,1608,false 16 | 14, Leftup sign,2,2,1612,false 17 | 15, Leftdown sign,2,2,1616,false 18 | 16, Up sign,2,2,1620,false 19 | 17, Down sign,2,2,1624,false 20 | 18, Danger sign,2,2,1628,false 21 | 19, Cyan color sign,2,2,1727,false 22 | 20, Yellow color sign,2,2,1731,false 23 | 21, Rock sign,2,2,1822,false 24 | 22, Trampoline sign,2,2,2400,false 25 | 23, Ice cube holding sign,2,2,3163,false 26 | 24, Blue pipe (vertical),2,2,2085,false 27 | -------------------------------------------------------------------------------- /data/supertux/smarttiles_mapping.csv: -------------------------------------------------------------------------------- 1 | tile_id,top,right,bottom,left 2 | 27,0,28,0,0 3 | 28,0,29,0,27 4 | 29,0,0,0,27 5 | 211,0,0,212,0 6 | 212,211,0,213,0 7 | 213,212,0,0,0 8 | 1287,0,1288,1289,0 9 | 1288,0,0,1290,1287 10 | 1289,1287,1290,1291,0 11 | 1290,1288,0,1292,1289 12 | 1291,1289,1292,1293,0 13 | 1292,1290,0,1294,1291 14 | 1293,1291,1294,1295,0 15 | 1294,1292,0,1296,1293 16 | 1295,1293,1296,1297,0 17 | 1296,1294,0,1298,1295 18 | 1297,1295,1298,1299,0 19 | 1298,1296,0,1300,1297 20 | 1299,1297,1300,1301,0 21 | 1300,1298,0,1302,1299 22 | 1301,1299,1302,1303,0 23 | 1302,1300,0,1304,1301 24 | 1303,1301,1304,1305,0 25 | 1304,1302,0,1306,1303 26 | 1305,1303,1306,1307,0 27 | 1306,1304,0,1308,1305 28 | 1307,1305,1308,1309,0 29 | 1308,1306,0,1310,1307 30 | 1309,1307,1310,0,0 31 | 1310,1308,0,0,1309 32 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1656928814, 6 | "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1657296039, 21 | "narHash": "sha256-Ghh39+aS+pw5sTP/ZO8VIKE6sBhMadDaQZtf+3yu4Vc=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "71d7a4c037dc4f3e98d5c4a81b941933cf5bf675", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "NixOS", 29 | "ref": "nixos-22.05", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "flake-utils": "flake-utils", 37 | "nixpkgs": "nixpkgs" 38 | } 39 | } 40 | }, 41 | "root": "root", 42 | "version": 7 43 | } 44 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "SuperTux 0.4.0 level editor"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | }; 8 | 9 | outputs = { self, nixpkgs, flake-utils }: 10 | flake-utils.lib.eachDefaultSystem (system: 11 | let 12 | pkgs = nixpkgs.legacyPackages.${system}; 13 | pythonPackages = pkgs.python310Packages; 14 | in rec { 15 | packages = flake-utils.lib.flattenTree rec { 16 | 17 | PyQt5-stubs = pythonPackages.buildPythonPackage rec { 18 | pname = "PyQt5-stubs"; 19 | version = "5.15.6.0"; 20 | src = pythonPackages.fetchPypi { 21 | inherit pname version; 22 | sha256 = "sha256-kScKwj6/OKHcBM2XqoUs0Ir4Lcg5EA5Tla8UR+Pplwc="; 23 | }; 24 | }; 25 | 26 | flexlay = pythonPackages.buildPythonPackage rec { 27 | pname = "flexlay"; 28 | version = "0.2.0"; 29 | src = ./.; 30 | nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; 31 | makeWrapperArgs = [ 32 | "\${qtWrapperArgs[@]}" 33 | "--set" "LIBGL_DRIVERS_PATH" "${pkgs.mesa.drivers}/lib/dri" 34 | "--prefix" "LD_LIBRARY_PATH" ":" "${pkgs.mesa.drivers}/lib" 35 | ]; 36 | preCheck = '' 37 | export QT_QPA_PLATFORM_PLUGIN_PATH="${pkgs.qt5.qtbase.bin}/lib/qt-${pkgs.qt5.qtbase.version}/plugins"; 38 | # export QT_QPA_PLATFORM=offscreen 39 | ''; 40 | checkPhase = '' 41 | runHook preCheck 42 | flake8 flexlay supertux tests 43 | # pyright flexlay supertux tests 44 | # mypy flexlay supertux tests 45 | # pylint flexlay supertux tests 46 | # HOME=$TMP python3 -m unittest discover -v -s tests/ 47 | runHook postCheck 48 | ''; 49 | propagatedBuildInputs = [ 50 | pkgs.xorg.libxcb 51 | pythonPackages.setuptools 52 | pythonPackages.numpy 53 | pythonPackages.pyqt5 54 | pythonPackages.pyqt5_sip 55 | pythonPackages.pyxdg 56 | ]; 57 | checkInputs = (with pkgs; [ 58 | pyright 59 | ]) ++ (with pythonPackages; [ 60 | flake8 61 | mypy 62 | pylint 63 | types-setuptools 64 | pyannotate 65 | ]) ++ [ 66 | PyQt5-stubs 67 | ]; 68 | }; 69 | 70 | flexlay-nocheck = flexlay.override { 71 | doCheck = false; 72 | }; 73 | 74 | default = flexlay; 75 | }; 76 | 77 | devShells = rec { 78 | flexlay-dev = pkgs.mkShell { 79 | inputsFrom = [ packages.flexlay ]; 80 | shellHook = packages.flexlay.preCheck + '' 81 | # runHook setuptoolsShellHook 82 | ''; 83 | }; 84 | default = flexlay-dev; 85 | }; 86 | } 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /flexlay/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/__init__.py -------------------------------------------------------------------------------- /flexlay/blend_func.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class BlendFunc: 19 | 20 | zero = 0 21 | one = 1 22 | one_minus_src_alpha = 2 23 | 24 | def __init__(self) -> None: 25 | pass 26 | 27 | 28 | # EOF # 29 | -------------------------------------------------------------------------------- /flexlay/blitter.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtCore import QPoint 19 | from PyQt5.QtGui import QPainter 20 | 21 | from flexlay.pixel_buffer import PixelBuffer 22 | 23 | 24 | def blit_opaque(target: PixelBuffer, brush: PixelBuffer, x: int, y: int) -> None: 25 | painter = QPainter(target.get_qimage()) 26 | painter.setCompositionMode(QPainter.CompositionMode_Source) 27 | painter.drawImage(QPoint(x, y), brush.get_qimage()) 28 | 29 | 30 | def blit(target: PixelBuffer, brush: PixelBuffer, x: int, y: int) -> None: 31 | painter = QPainter(target.get_qimage()) 32 | painter.setCompositionMode(QPainter.CompositionMode_SourceOver) 33 | painter.drawImage(QPoint(x, y), brush.get_qimage()) 34 | 35 | 36 | def blit_clear(canvas: PixelBuffer) -> None: 37 | pass 38 | # print("clear(PixelBuffer canvas) not implemented", canvas) 39 | # canvas.lock() 40 | # buffer = static_cast(canvas.get_data()) 41 | # memset(buffer, 0, sizeof(unsigned char) * canvas.get_pitch() * canvas.height) 42 | # canvas.unlock() 43 | 44 | 45 | # EOF # 46 | -------------------------------------------------------------------------------- /flexlay/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/commands/__init__.py -------------------------------------------------------------------------------- /flexlay/commands/command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class Command: 19 | """ 20 | Commands allow undoable actions. This means, 21 | actions which can be undone by pressing the 22 | undo button. Create a new Command for each 23 | undoable action that may happen. They are 24 | then added to the undo stack. When undone, 25 | they are added to the redo stack 26 | """ 27 | 28 | def __init__(self) -> None: 29 | """Here, the values involved in the 30 | Command should be initialised or 31 | passed as parameters""" 32 | pass 33 | 34 | def execute(self) -> None: 35 | """This method is run once - when the 36 | action happens.""" 37 | pass 38 | 39 | def redo(self) -> None: 40 | """This method is run when this command 41 | is top of the undo stack and the undo 42 | button is clicked""" 43 | pass 44 | 45 | def undo(self) -> None: 46 | """This method is run when this command 47 | is top of the redo stack and the redo 48 | button is clicked""" 49 | pass 50 | 51 | 52 | # EOF # 53 | -------------------------------------------------------------------------------- /flexlay/commands/command_group.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.commands.command import Command 19 | 20 | 21 | class CommandGroup(Command): 22 | 23 | def __init__(self) -> None: 24 | super().__init__() 25 | 26 | self.commands: list[Command] = [] 27 | 28 | def add_command(self, command: Command) -> None: 29 | self.commands.append(command) 30 | 31 | def execute(self) -> None: 32 | for command in self.commands: 33 | command.execute() 34 | 35 | def undo(self) -> None: 36 | for command in reversed(self.commands): 37 | command.undo() 38 | 39 | def redo(self) -> None: 40 | for command in self.commands: 41 | command.redo() 42 | 43 | 44 | # EOF # 45 | -------------------------------------------------------------------------------- /flexlay/commands/layer_delete_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional, TYPE_CHECKING 19 | 20 | from flexlay.commands.command import Command 21 | from flexlay.objmap_tilemap_object import ObjMapTilemapObject 22 | 23 | if TYPE_CHECKING: 24 | from flexlay.gui.layer_selector import LayerSelector 25 | 26 | 27 | class LayerDeleteCommand(Command): 28 | def __init__(self, layer_selector: 'LayerSelector', layer: int) -> None: 29 | """Deletes a Layer 30 | 31 | :param layer: Either a TilemapLayer, an ObjMapTilemapObject or an int (the layer to remove) 32 | """ 33 | self.layer: int = layer 34 | self.layer_selector: 'LayerSelector' = layer_selector 35 | self.removed_object: Optional[ObjMapTilemapObject] = None 36 | 37 | def execute(self) -> None: 38 | self.removed_object = self.layer_selector.unsafe_remove_layer(self.layer) 39 | 40 | def undo(self) -> None: 41 | if self.removed_object is not None: 42 | self.layer_selector.add_layer(self.removed_object) 43 | else: 44 | raise RuntimeError("Could not undo layer removal.") 45 | 46 | def redo(self) -> None: 47 | assert self.removed_object is not None 48 | self.layer_selector.unsafe_remove_layer(self.removed_object) 49 | 50 | 51 | # EOF # 52 | -------------------------------------------------------------------------------- /flexlay/commands/object_add_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.commands.command import Command 19 | from flexlay.object_layer import ObjectLayer 20 | from flexlay.objmap_object import ObjMapObject 21 | 22 | 23 | class ObjectAddCommand(Command): 24 | 25 | def __init__(self, objmap: ObjectLayer) -> None: 26 | super().__init__() 27 | 28 | self.objmap: ObjectLayer = objmap 29 | self.objs: list[ObjMapObject] = [] 30 | 31 | def add_object(self, obj: ObjMapObject) -> None: 32 | self.objs.append(obj) 33 | 34 | def execute(self) -> None: 35 | for obj in self.objs: 36 | self.objmap.add_object(obj) 37 | 38 | def undo(self) -> None: 39 | for obj in self.objs: 40 | self.objmap.delete_object(obj) 41 | 42 | def redo(self) -> None: 43 | self.execute() 44 | 45 | 46 | # EOF # 47 | -------------------------------------------------------------------------------- /flexlay/commands/object_delete_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.object_layer import ObjectLayer 19 | from flexlay.objmap_object import ObjMapObject 20 | from flexlay.commands.command import Command 21 | 22 | 23 | class ObjectDeleteCommand(Command): 24 | 25 | def __init__(self, object_layer: ObjectLayer) -> None: 26 | self.object_layer = object_layer 27 | self.objects: list[ObjMapObject] = [] 28 | 29 | def add_object(self, obj: ObjMapObject) -> None: 30 | self.objects.append(obj) 31 | 32 | def execute(self) -> None: 33 | for obj in self.objects: 34 | self.object_layer.delete_object(obj) 35 | 36 | def redo(self) -> None: 37 | self.execute() 38 | 39 | def undo(self) -> None: 40 | for obj in self.objects: 41 | self.object_layer.add_object(obj) 42 | 43 | 44 | # EOF # 45 | -------------------------------------------------------------------------------- /flexlay/commands/object_move_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.object_layer import ObjectLayer 19 | from flexlay.objmap_object import ObjMapObject 20 | from flexlay.math import Pointf 21 | from flexlay.commands.command import Command 22 | 23 | 24 | class Obj: 25 | 26 | def __init__(self, objmap_object: ObjMapObject, old_pos: Pointf, new_pos: Pointf) -> None: 27 | self.obj: ObjMapObject = objmap_object 28 | self.old_pos: Pointf = old_pos 29 | self.new_pos: Pointf = new_pos 30 | 31 | 32 | class ObjectMoveCommand(Command): 33 | 34 | def __init__(self, object_layer: ObjectLayer) -> None: 35 | self.objmap = object_layer 36 | self.objects: list[Obj] = [] 37 | 38 | def execute(self) -> None: 39 | pass 40 | 41 | def add_obj(self, obj: ObjMapObject) -> None: 42 | self.objects.append(Obj(obj, obj.get_pos(), obj.get_pos())) 43 | 44 | def move_by(self, delta: Pointf) -> None: 45 | for obj in self.objects: 46 | obj.new_pos = obj.old_pos + delta 47 | obj.obj.set_pos(obj.new_pos) 48 | obj.obj.sig_move(obj.obj) 49 | 50 | def redo(self) -> None: 51 | for obj in self.objects: 52 | obj.obj.set_pos(obj.new_pos) 53 | 54 | def undo(self) -> None: 55 | for obj in self.objects: 56 | obj.obj.set_pos(obj.old_pos) 57 | 58 | 59 | # EOF # 60 | -------------------------------------------------------------------------------- /flexlay/commands/object_transform_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class ObjectTransformCommand: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | def execute(self) -> None: 24 | pass 25 | 26 | def redo(self) -> None: 27 | pass 28 | 29 | def undo(self) -> None: 30 | pass 31 | 32 | 33 | # EOF # 34 | -------------------------------------------------------------------------------- /flexlay/drawer_properties.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | 21 | class DrawerProperties: 22 | 23 | current: Optional['DrawerProperties'] = None 24 | 25 | def __init__(self) -> None: 26 | DrawerProperties.current = self 27 | 28 | 29 | # EOF # 30 | -------------------------------------------------------------------------------- /flexlay/field.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import List 19 | import numpy.typing as npt 20 | 21 | import numpy as np 22 | 23 | 24 | class Field: 25 | 26 | @staticmethod 27 | def from_size(width: int, height: int) -> 'Field': 28 | return Field(np.zeros((height, width), dtype=np.uint32)) 29 | 30 | @staticmethod 31 | def from_list(width: int, height: int, data: List[int]) -> 'Field': 32 | return Field(np.array(data, dtype=np.uint32).reshape(height, width)) 33 | 34 | def __init__(self, data: npt.NDArray[np.uint32]) -> None: 35 | self._data = data 36 | 37 | def copy_region(self, x: int, y: int, w: int, h: int) -> 'Field': 38 | start_x = max(0, -x) 39 | start_y = max(0, -y) 40 | 41 | end_x = min(self.width, w - x) 42 | end_y = min(self.height, h - y) 43 | 44 | field = Field.from_size(w, h) 45 | for iy in range(start_y, end_y): 46 | for ix in range(start_x, end_x): 47 | field.put(x + ix, y + iy, self.at(ix, iy)) 48 | return field 49 | 50 | def copy(self) -> 'Field': 51 | return Field(np.copy(self._data)) 52 | 53 | def put(self, x: int, y: int, value: int) -> None: 54 | assert 0 <= value < np.iinfo(np.uint32).max, "{}: not in range".format(value) 55 | self._data[y][x] = value 56 | 57 | def at(self, x: int, y: int) -> int: 58 | assert (x >= 0 or x < self.width or y >= 0 or y < self.height) 59 | return int(self._data[y][x]) 60 | 61 | def resize(self, w: int, h: int, x: int = 0, y: int = 0) -> None: 62 | field = self.copy_region(x, y, w, h) 63 | self._data = field._data 64 | 65 | @property 66 | def width(self) -> int: 67 | return int(self._data.shape[1]) 68 | 69 | @property 70 | def height(self) -> int: 71 | return int(self._data.shape[0]) 72 | 73 | def size(self) -> int: 74 | return int(self._data.size) 75 | 76 | def __contains__(self, key: int) -> bool: 77 | return bool(key in self._data) 78 | 79 | def __str__(self) -> str: 80 | result = "\n" 81 | for y in range(self.height): 82 | for x in range(self.width): 83 | result += "%04s " % self.at(x, y) 84 | result += "\n" 85 | return result 86 | 87 | 88 | # EOF # 89 | -------------------------------------------------------------------------------- /flexlay/flexlay.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | import sys 21 | import logging 22 | 23 | from PyQt5.QtWidgets import QApplication 24 | 25 | from flexlay.gui_manager import GUIManager 26 | 27 | 28 | class Flexlay: 29 | 30 | def __init__(self, app_name: str) -> None: 31 | self.name: str = app_name 32 | 33 | self.application: QApplication = QApplication(sys.argv) 34 | self.gui_manager: Optional[GUIManager] = None 35 | 36 | logging.basicConfig(format="[%(levelname)s] " + self.name + " %(pathname)s:%(lineno)s: %(message)s") 37 | logging.getLogger().setLevel(logging.DEBUG) 38 | 39 | def create_gui_manager(self, title: str = "") -> GUIManager: 40 | if title == "": 41 | title = self.name 42 | self.gui_manager = GUIManager(title) 43 | return self.gui_manager 44 | 45 | 46 | # EOF # 47 | -------------------------------------------------------------------------------- /flexlay/gui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/gui/__init__.py -------------------------------------------------------------------------------- /flexlay/gui/button_panel.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Callable, Optional 19 | 20 | from PyQt5.QtWidgets import QToolBar 21 | from PyQt5.QtGui import QIcon 22 | 23 | from flexlay.gui.icon import Icon 24 | 25 | 26 | class ButtonPanel: 27 | 28 | def __init__(self, toolbar: QToolBar) -> None: 29 | self.toolbar = toolbar 30 | 31 | def add_icon(self, 32 | filename: str, callback: Callable[[], None], 33 | hover: str = "Hover Text", 34 | shortcut: Optional[str] = None) -> Icon: 35 | action = self.toolbar.addAction(QIcon(filename), hover) 36 | if shortcut is not None: 37 | action.setShortcut(shortcut) 38 | if callback: 39 | action.triggered.connect(lambda checked: callback()) 40 | return Icon(action) 41 | 42 | def add_text(self, name: str, callback: Callable[[], None]) -> Icon: 43 | action = self.toolbar.addAction(name) 44 | if callback: 45 | action.triggered.connect(lambda checked: callback()) 46 | return Icon(action) 47 | 48 | def add_separator(self) -> None: 49 | self.toolbar.addSeparator() 50 | 51 | def show(self, visible: bool) -> None: 52 | pass 53 | 54 | 55 | # EOF # 56 | -------------------------------------------------------------------------------- /flexlay/gui/colorpicker.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class ColorPicker: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | 24 | # EOF # 25 | -------------------------------------------------------------------------------- /flexlay/gui/generic_dialog.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtWidgets import (QWidget, QDialog, QDialogButtonBox, QVBoxLayout, 19 | QFormLayout) 20 | 21 | from flexlay.gui.properties_widget import PropertiesWidget 22 | 23 | 24 | class GenericDialog(PropertiesWidget): 25 | """A PropertiesWidget in a QDialog.""" 26 | 27 | def __init__(self, title: str, parent: QWidget) -> None: 28 | super().__init__(parent) 29 | 30 | self.ok_callback = None 31 | 32 | self.dialog = QDialog(parent) 33 | 34 | self.dialog.setModal(True) 35 | self.dialog.setWindowTitle(title) 36 | self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) 37 | 38 | vbox = QVBoxLayout() 39 | self._layout = QFormLayout() 40 | vbox.addLayout(self._layout) 41 | vbox.addWidget(self) 42 | vbox.addWidget(self.buttonbox) 43 | 44 | self.dialog.setLayout(vbox) 45 | self.dialog.setMinimumWidth(300) 46 | self.dialog.show() 47 | 48 | # "Ok" and "Cancel" signals 49 | 50 | def on_accept() -> None: 51 | self.call() 52 | self.dialog.hide() 53 | 54 | def on_rejected() -> None: 55 | self.dialog.hide() 56 | 57 | self.buttonbox.accepted.connect(on_accept) 58 | self.buttonbox.rejected.connect(on_rejected) 59 | 60 | 61 | # EOF # 62 | -------------------------------------------------------------------------------- /flexlay/gui/generic_wizard.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see 16 | 17 | 18 | from typing import Any 19 | 20 | from PyQt5.QtWidgets import QWidget, QWizardPage, QWizard, QVBoxLayout 21 | 22 | from flexlay.util.signal import Signal 23 | from flexlay.gui.properties_widget import PropertiesWidget 24 | 25 | 26 | class GenericWizard(QWizard): 27 | """A Wizard which can display properties easily 28 | 29 | You must use new_property_page to create pages which 30 | are made up of a PropertyWidget. 31 | 32 | Use add_callback to add a function which will be called 33 | when "Finish" is pressed. See that function for more details 34 | """ 35 | 36 | def __init__(self, parent: QWidget, title: str) -> None: 37 | super().__init__(parent) 38 | self.setWindowTitle(title) 39 | self.pages: list[PropertiesWidget] = [] 40 | 41 | self.finish_callback = Signal() 42 | 43 | def on_finish() -> None: 44 | self.finish_callback(*self.get_values()) 45 | for page in self.pages: 46 | page.call() 47 | self.hide() 48 | 49 | def on_cancel() -> None: 50 | self.hide() 51 | 52 | self.finished.connect(on_finish) 53 | self.rejected.connect(on_cancel) 54 | 55 | def add_page(self, title: str, widget: PropertiesWidget) -> None: 56 | """Adds a page to this GenericWizard 57 | 58 | :param page: PropertyWidget to add 59 | """ 60 | self.pages.append(widget) 61 | 62 | page = QWizardPage(self) 63 | page.setTitle(title) 64 | layout = QVBoxLayout() 65 | layout.addWidget(widget) 66 | page.setLayout(layout) 67 | 68 | self.addPage(page) 69 | 70 | def get_values(self) -> list[Any]: 71 | """ Returns a list of lists of all values put into this Wizard 72 | 73 | Best explained by example: 74 | my_wizard.get_values()[page_index][property_index] 75 | 76 | :return: A list of lists ^ 77 | """ 78 | result: list[Any] = [] 79 | 80 | for page in self.pages: 81 | value = page.get_values() 82 | if value is not None: 83 | result.append(value) 84 | 85 | return result 86 | 87 | 88 | # EOF # 89 | -------------------------------------------------------------------------------- /flexlay/gui/icon.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtWidgets import QAction 19 | 20 | 21 | class Icon: 22 | 23 | def __init__(self, action: QAction) -> None: 24 | self.action = action 25 | 26 | def disable(self) -> None: 27 | self.action.setEnabled(False) 28 | 29 | def enable(self) -> None: 30 | self.action.setEnabled(True) 31 | 32 | def set_up(self) -> None: 33 | self.action.setCheckable(True) 34 | self.action.setChecked(False) 35 | 36 | def set_down(self) -> None: 37 | self.action.setCheckable(True) 38 | self.action.setChecked(True) 39 | 40 | 41 | # EOF # 42 | -------------------------------------------------------------------------------- /flexlay/gui/menubar.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Callable 19 | 20 | from PyQt5.QtWidgets import QMenu, QMenuBar, QAction 21 | 22 | 23 | class Menu: 24 | 25 | def __init__(self, menu: QMenu) -> None: 26 | self.menu = menu 27 | 28 | def add_menu(self, label: str) -> 'Menu': 29 | menu = self.menu.addMenu(label) 30 | return Menu(menu) 31 | 32 | def add_item(self, label: str, callback: Callable[[], None]) -> QAction: 33 | action = self.menu.addAction(label) 34 | if callback: 35 | action.triggered.connect(lambda checked: callback()) 36 | return action 37 | 38 | 39 | class Menubar: 40 | 41 | def __init__(self, qmenubar: QMenuBar) -> None: 42 | self.qmenubar = qmenubar 43 | 44 | def add_menu(self, label: str) -> Menu: 45 | menu = self.qmenubar.addMenu(label) 46 | return Menu(menu) 47 | 48 | 49 | # EOF # 50 | -------------------------------------------------------------------------------- /flexlay/gui/minimap.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.minimap_widget import MinimapWidget 19 | from flexlay.gui.editor_map_component import EditorMapComponent 20 | 21 | 22 | class Minimap: 23 | 24 | def __init__(self, editormap_component: EditorMapComponent) -> None: 25 | self.widget = MinimapWidget(editormap_component) 26 | 27 | def update_minimap(self) -> None: 28 | self.widget.update_minimap() 29 | 30 | def get_widget(self) -> MinimapWidget: 31 | return self.widget 32 | 33 | 34 | # EOF # 35 | -------------------------------------------------------------------------------- /flexlay/gui/object_selector.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | from PyQt5.QtCore import Qt 21 | from PyQt5.QtWidgets import QWidget, QScrollArea 22 | 23 | from flexlay.gui.object_selector_widget import ObjectSelectorWidget 24 | from flexlay.object_brush import ObjectBrush 25 | 26 | 27 | class ObjectSelector: 28 | 29 | current: Optional['ObjectSelector'] = None 30 | 31 | def __init__(self, obj_w: int, obj_h: int, parent: Optional[QWidget]) -> None: 32 | ObjectSelector.current = self 33 | 34 | self.scroll_area = QScrollArea(parent) 35 | self.scroll_area.setWidgetResizable(True) 36 | self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) 37 | self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) 38 | 39 | self.widget = ObjectSelectorWidget(obj_w, obj_h, self.scroll_area.viewport()) 40 | self.scroll_area.setWidget(self.widget) 41 | 42 | def add_brush(self, brush: ObjectBrush) -> None: 43 | self.widget.add_brush(brush) 44 | 45 | def get_brush(self, brush_id: int) -> ObjectBrush: 46 | return self.widget.brushes[brush_id] 47 | 48 | def get_widget(self) -> QScrollArea: 49 | return self.scroll_area 50 | 51 | 52 | # EOF # 53 | -------------------------------------------------------------------------------- /flexlay/gui/statusbar.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtWidgets import QLabel, QStatusBar 19 | 20 | from flexlay.math.point import Point 21 | 22 | 23 | class StatusBar: 24 | 25 | def __init__(self, widget: QStatusBar) -> None: 26 | self.widget = widget 27 | self.mouse_coordinate_label = QLabel() 28 | self.mouse_coordinate_label.setText("99, 100") 29 | self.widget.addPermanentWidget(self.mouse_coordinate_label) 30 | 31 | def clear_message(self) -> None: 32 | self.widget.clearMessage() 33 | 34 | def show_message(self, text: str) -> None: 35 | self.widget.showMessage(text) 36 | 37 | def set_mouse_coordinates(self, pos: Point) -> None: 38 | self.mouse_coordinate_label.setText("(%d, %d)" % (pos.x, pos.y)) 39 | 40 | 41 | # EOF # 42 | -------------------------------------------------------------------------------- /flexlay/gui/tile_brush_selector.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtWidgets import QListWidget 19 | 20 | from flexlay.tile_brush import TileBrush 21 | 22 | 23 | class TileBrushSelector: 24 | 25 | def __init__(self) -> None: 26 | self.brushes: list[TileBrush] = [] 27 | self.list_widget = QListWidget() 28 | 29 | def add_brush(self, name: str, brush: TileBrush) -> None: 30 | self.list_widget.addItem(name) 31 | self.brushes.append(brush) 32 | 33 | def get_widget(self) -> QListWidget: 34 | return self.list_widget 35 | 36 | 37 | # EOF # 38 | -------------------------------------------------------------------------------- /flexlay/input_event.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | import logging 21 | 22 | from PyQt5.QtGui import QMouseEvent 23 | from PyQt5.QtCore import Qt 24 | 25 | from flexlay.math import Point 26 | 27 | 28 | class InputEvent: 29 | 30 | MOUSE_LEFT = 1 31 | MOUSE_RIGHT = 2 32 | MOUSE_MIDDLE = 3 33 | MOUSE_WHEEL_UP = 4 34 | MOUSE_WHEEL_DOWN = 5 35 | MOUSE_NO_BUTTON = 6 36 | 37 | MOD_SHIFT = (1 << 0) 38 | MOD_CTRL = (1 << 1) 39 | MOD_ALT = (1 << 2) 40 | 41 | def __init__(self) -> None: 42 | self.kind: int = InputEvent.MOUSE_NO_BUTTON 43 | self.mouse_pos: Optional[Point] = None 44 | self.mod: int = 0 45 | 46 | @staticmethod 47 | def from_qt(event: QMouseEvent) -> 'InputEvent': 48 | result = InputEvent() 49 | 50 | result.mouse_pos = Point(event.x(), event.y()) 51 | 52 | if event.button() == 0: 53 | result.kind = InputEvent.MOUSE_NO_BUTTON 54 | elif event.button() == Qt.LeftButton: 55 | result.kind = InputEvent.MOUSE_LEFT 56 | elif event.button() == Qt.MidButton: 57 | result.kind = InputEvent.MOUSE_MIDDLE 58 | elif event.button() == Qt.RightButton: 59 | result.kind = InputEvent.MOUSE_RIGHT 60 | else: 61 | logging.debug("unknown mouse button: " + str(event.button())) 62 | 63 | if event.modifiers() & Qt.ControlModifier: 64 | result.mod |= InputEvent.MOD_CTRL 65 | 66 | if event.modifiers() & Qt.AltModifier: 67 | result.mod |= InputEvent.MOD_ALT 68 | 69 | if event.modifiers() & Qt.ShiftModifier: 70 | result.mod |= InputEvent.MOD_SHIFT 71 | 72 | return result 73 | 74 | 75 | # EOF # 76 | -------------------------------------------------------------------------------- /flexlay/layer.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any 19 | 20 | from flexlay.graphic_context import GraphicContext 21 | from flexlay.math import Pointf, Rectf 22 | 23 | 24 | class Layer: 25 | 26 | def __init__(self) -> None: 27 | self.data = None 28 | self.pos = Pointf(0, 0) 29 | self.metadata: Any = None 30 | 31 | def draw(self, gc: GraphicContext) -> None: 32 | if self.pos.x != 0 or self.pos.y != 0: 33 | gc.push_modelview() 34 | gc.translate(self.pos.x, self.pos.y) 35 | self.draw(gc) 36 | gc.pop_modelview() 37 | else: 38 | self.draw(gc) 39 | 40 | def has_bounding_rect(self) -> bool: 41 | return self.has_bounding_rect() 42 | 43 | def get_bounding_rect(self) -> Rectf: 44 | rect = self.get_bounding_rect() 45 | rect.left += self.pos.x 46 | rect.top += self.pos.y 47 | rect.right += self.pos.x 48 | rect.bottom += self.pos.y 49 | return rect 50 | 51 | def set_pos(self, pos: Pointf) -> None: 52 | self.pos = pos 53 | 54 | def get_pos(self) -> Pointf: 55 | return self.pos 56 | 57 | 58 | # EOF # 59 | -------------------------------------------------------------------------------- /flexlay/math/__init__.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.math.point import Point, Pointf 19 | from flexlay.math.rect import Rect, Rectf 20 | from flexlay.math.size import Size, Sizef 21 | from flexlay.math.origin import Origin 22 | 23 | 24 | __all__ = [ 25 | "Origin", 26 | "Point", "Pointf", 27 | "Size", "Sizef", 28 | "Rect", "Rectf", 29 | ] 30 | 31 | 32 | # EOF # 33 | -------------------------------------------------------------------------------- /flexlay/math/size.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtCore import QSize, QSizeF 19 | 20 | 21 | class Size: 22 | 23 | def __init__(self, w: int, h: int) -> None: 24 | self.width: int = w 25 | self.height: int = h 26 | 27 | def copy(self) -> 'Size': 28 | return Size(self.width, self.height) 29 | 30 | def to_qt(self) -> QSize: 31 | return QSize(self.width, self.height) 32 | 33 | def __eq__(self, rhs: object) -> bool: 34 | if not isinstance(rhs, Size): 35 | return False 36 | 37 | return (self.width == rhs.width and 38 | self.height == rhs.height) 39 | 40 | def __ne__(self, rhs: object) -> bool: 41 | return not self.__eq__(rhs) 42 | 43 | def __str__(self) -> str: 44 | return "Size({}, {})".format(self.width, self.height) 45 | 46 | 47 | class Sizef: 48 | 49 | def __init__(self, w: float, h: float) -> None: 50 | self.width: float = w 51 | self.height: float = h 52 | 53 | def copy(self) -> 'Sizef': 54 | return Sizef(self.width, self.height) 55 | 56 | def to_qt(self) -> QSizeF: 57 | return QSizeF(self.width, self.height) 58 | 59 | def __eq__(self, rhs: object) -> bool: 60 | if not isinstance(rhs, Sizef): 61 | return False 62 | 63 | return (self.width == rhs.width and 64 | self.height == rhs.height) 65 | 66 | def __ne__(self, rhs: object) -> bool: 67 | return not self.__eq__(rhs) 68 | 69 | def __str__(self) -> str: 70 | return "Size({}, {})".format(self.width, self.height) 71 | 72 | 73 | # EOF # 74 | -------------------------------------------------------------------------------- /flexlay/object_brush.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any 19 | 20 | from flexlay.sprite import Sprite 21 | 22 | 23 | class ObjectBrush: 24 | 25 | def __init__(self, sprite: Sprite, metadata: Any, variable: bool = False) -> None: 26 | self.sprite: Sprite = sprite 27 | self.metadata: Any = metadata 28 | self.variable: bool = variable 29 | 30 | def check_sprite(self) -> None: 31 | pass 32 | 33 | def get_sprite(self) -> Sprite: 34 | return self.sprite 35 | 36 | def get_data(self) -> Any: 37 | return self.metadata 38 | 39 | 40 | # EOF # 41 | -------------------------------------------------------------------------------- /flexlay/objmap_control_point.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Optional 19 | 20 | from flexlay.graphic_context import GraphicContext 21 | from flexlay.math import Pointf, Rectf, Origin, Sizef 22 | from flexlay.sprite import Sprite 23 | from flexlay.util.signal import Signal 24 | 25 | 26 | class ObjMapControlPoint: 27 | 28 | def __init__(self, sprite: Sprite, pos: Pointf, metadata: Optional[Any] = None) -> None: 29 | self.sprite = sprite 30 | self.pos = pos 31 | self.metadata = metadata 32 | self.sig_set_pos = Signal() 33 | 34 | def draw(self, gc: GraphicContext) -> None: 35 | self.sprite.draw(int(self.pos.x), int(self.pos.y), gc) 36 | 37 | def set_pos_raw(self, p: Pointf) -> None: 38 | self.pos = p 39 | 40 | def set_pos(self, p: Pointf) -> None: 41 | self.sig_set_pos(p) 42 | 43 | def get_pos(self) -> Pointf: 44 | return self.pos 45 | 46 | def get_bound_rect(self) -> Rectf: 47 | origin_enum, align_x, align_y = self.sprite.get_alignment() 48 | align_x = -align_x 49 | origin = Origin.calc_originf(origin_enum, 50 | Sizef(self.sprite.width, 51 | self.sprite.height)) 52 | 53 | return Rectf.from_ps(self.pos.copy() - origin - Pointf(align_x, align_y), 54 | Sizef(self.sprite.width, self.sprite.height)) 55 | 56 | 57 | # EOF # 58 | -------------------------------------------------------------------------------- /flexlay/objmap_object.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Optional 19 | 20 | from flexlay.util.signal import Signal 21 | from flexlay.math import Pointf, Rectf 22 | from flexlay.graphic_context import GraphicContext 23 | 24 | 25 | class ObjMapObject: 26 | 27 | def __init__(self, pos: Pointf, metadata: Any) -> None: 28 | self.to_draw: bool = True 29 | self.pos: Pointf = pos 30 | self.metadata: Any = metadata 31 | self.sig_select = Signal() 32 | self.sig_deselect = Signal() 33 | self.sig_move = Signal() 34 | 35 | def draw(self, gc: GraphicContext) -> None: 36 | pass 37 | 38 | def is_inside(self, click_pos: Pointf) -> bool: 39 | rect = self.get_bound_rect() 40 | if rect is None: 41 | return False 42 | return rect.is_inside(click_pos) 43 | 44 | def get_bound_rect(self) -> Optional[Rectf]: 45 | return None 46 | 47 | def get_pos(self) -> Pointf: 48 | return self.pos 49 | 50 | def set_pos(self, pos: Pointf) -> None: 51 | self.pos = pos 52 | 53 | def add_control_points(self) -> None: 54 | pass 55 | 56 | def update_control_points(self) -> None: 57 | pass 58 | 59 | 60 | # EOF # 61 | -------------------------------------------------------------------------------- /flexlay/objmap_path_node.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Optional 19 | 20 | from flexlay.objmap_object import ObjMapObject 21 | from flexlay.color import Color 22 | from flexlay.math import Pointf, Sizef, Rectf 23 | from flexlay.graphic_context import GraphicContext 24 | 25 | 26 | class ObjMapPathNode(ObjMapObject): 27 | 28 | def __init__(self, pos: Pointf, metadata: Any) -> None: 29 | super().__init__(pos, metadata) 30 | 31 | self.prev_node: Optional['ObjMapPathNode'] = None 32 | self.next_node: Optional['ObjMapPathNode'] = None 33 | 34 | def draw(self, gc: GraphicContext) -> None: 35 | gc.fill_rect(Rectf.from_ps(self.pos - Pointf(16, 16), 36 | Sizef(32, 32)), 37 | Color(200, 255, 200)) 38 | if self.next_node: 39 | gc.draw_line(self.pos.x, self.pos.y, 40 | (self.pos.x + self.next_node.pos.x) / 2, 41 | (self.pos.y + self.next_node.pos.y) / 2, 42 | Color(255, 255, 0)) 43 | 44 | gc.draw_line((self.pos.x + self.next_node.pos.x) / 2, 45 | (self.pos.y + self.next_node.pos.y) / 2, 46 | self.next_node.pos.x, 47 | self.next_node.pos.y, 48 | Color(255, 0, 0)) 49 | 50 | def get_bound_rect(self) -> Rectf: 51 | return Rectf.from_ps(self.pos - Pointf(16, 16), Sizef(32, 32)) 52 | 53 | def disconnect(self) -> None: 54 | assert self.next_node is not None 55 | assert self.prev_node is not None 56 | 57 | if self.next_node.prev_node is not None: 58 | self.next_node.prev_node = None 59 | 60 | if self.prev_node.prev_node is not None: 61 | self.prev_node.next_node = None 62 | 63 | self.next_node = None 64 | self.prev_node = None 65 | 66 | def connect(self, node: 'ObjMapPathNode') -> None: 67 | assert node != self 68 | 69 | # ensure that each node links exactly to one prev and one next node 70 | if node.prev_node: 71 | node.prev_node.next_node = None 72 | node.prev_node = None 73 | 74 | self.next_node = node 75 | node.prev_node = self 76 | 77 | 78 | # EOF # 79 | -------------------------------------------------------------------------------- /flexlay/objmap_tilemap_object.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any 19 | 20 | from flexlay.graphic_context import GraphicContext 21 | from flexlay.math import Pointf, Rectf, Sizef 22 | from flexlay.objmap_object import ObjMapObject 23 | from flexlay.tilemap_layer import TilemapLayer 24 | 25 | 26 | class ObjMapTilemapObject(ObjMapObject): 27 | 28 | def __init__(self, tilemap_layer: TilemapLayer, metadata: Any) -> None: 29 | super().__init__(Pointf(0, 0), metadata) 30 | 31 | self.tilemap_layer = tilemap_layer 32 | 33 | def draw(self, gc: GraphicContext) -> None: 34 | self.tilemap_layer.draw(gc, self.metadata.pos) 35 | 36 | def get_pos(self) -> Pointf: 37 | return self.pos 38 | 39 | def is_inside(self, click_pos: Pointf) -> bool: 40 | return False 41 | 42 | def get_bound_rect(self) -> Rectf: 43 | return Rectf.from_ps(self.tilemap_layer.metadata.pos, 44 | Sizef(self.tilemap_layer.width * 32, 45 | self.tilemap_layer.height * 32)) 46 | 47 | def set_pos(self, pos: Pointf) -> None: 48 | self.pos = pos 49 | 50 | def add_control_points(self) -> None: 51 | pass 52 | 53 | def update_control_points(self) -> None: 54 | pass 55 | 56 | 57 | # EOF # 58 | -------------------------------------------------------------------------------- /flexlay/pixel_buffer.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.sip import voidptr # type: ignore 19 | from PyQt5.QtCore import QSize 20 | from PyQt5.QtGui import QImage 21 | 22 | from flexlay.math import Size 23 | 24 | 25 | class PixelBuffer: 26 | 27 | cache: dict[str, QImage] = {} 28 | 29 | @staticmethod 30 | def subregion_from_file(filename: str, x: int, y: int, w: int, h: int) -> 'PixelBuffer': 31 | from flexlay.blitter import blit_clear, blit_opaque 32 | 33 | source = PixelBuffer.from_file(filename) 34 | target = PixelBuffer.from_size(Size(w, h)) 35 | blit_clear(target) 36 | blit_opaque(target, source, -x, -y) 37 | return target 38 | 39 | @staticmethod 40 | def from_file(filename: str) -> 'PixelBuffer': 41 | cached_image = PixelBuffer.cache.get(filename) 42 | if cached_image is None: 43 | cached_image = QImage(filename) 44 | if cached_image.isNull(): 45 | raise RuntimeError(f"Failed to load image: {filename}") 46 | PixelBuffer.cache[filename] = cached_image 47 | 48 | return PixelBuffer(cached_image) 49 | 50 | @staticmethod 51 | def from_size(size: Size) -> 'PixelBuffer': 52 | return PixelBuffer(QImage(QSize(size.to_qt()), QImage.Format_ARGB32)) 53 | 54 | def __init__(self, image: QImage) -> None: 55 | self.image = image 56 | 57 | def get_qimage(self) -> QImage: 58 | return self.image 59 | 60 | def lock(self) -> None: 61 | pass 62 | 63 | def unlock(self) -> None: 64 | pass 65 | 66 | @property 67 | def width(self) -> int: 68 | return self.image.width() 69 | 70 | @property 71 | def height(self) -> int: 72 | return self.image.height() 73 | 74 | def get_pitch(self) -> int: 75 | return self.image.bytesPerLine() 76 | 77 | def get_depth(self) -> int: 78 | return self.image.depth() 79 | 80 | def get_data(self) -> voidptr: 81 | return self.image.bits() 82 | 83 | 84 | # EOF # 85 | -------------------------------------------------------------------------------- /flexlay/sprite_brush.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.math import Origin 19 | from flexlay.sprite import Sprite 20 | 21 | 22 | class SpriteBrush: 23 | 24 | def __init__(self, sprite: Sprite) -> None: 25 | self.sprite = sprite 26 | self.sprite.set_alignment(Origin.center, 0, 0) 27 | 28 | def get_sprite(self) -> Sprite: 29 | return self.sprite 30 | 31 | 32 | # EOF # 33 | -------------------------------------------------------------------------------- /flexlay/tile.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | import logging 21 | 22 | from flexlay.color import Color 23 | from flexlay.pixel_buffer import PixelBuffer 24 | from flexlay.sprite import Sprite 25 | 26 | 27 | class Tile: 28 | 29 | def __init__(self, pixelbuffer: Optional[PixelBuffer] = None, sprite: Optional[Sprite] = None) -> None: 30 | self.sprite: Optional[Sprite] = sprite 31 | self.pixelbuffer: Optional[PixelBuffer] = pixelbuffer 32 | self.transparent: bool = False 33 | self.color: Optional[Color] = None 34 | self.attribute_color: Color = Color(255, 255, 255) 35 | self.filename: Optional[str] = None 36 | 37 | def get_color(self) -> Color: 38 | if self.color is not None: 39 | return self.color 40 | else: 41 | self.color = self.calc_color() 42 | return self.color 43 | 44 | def get_attribute_color(self) -> Color: 45 | return self.attribute_color 46 | 47 | def get_sprite(self) -> Sprite: 48 | if self.sprite is not None: 49 | return self.sprite 50 | else: 51 | self.sprite = Sprite(self.get_pixelbuffer()) 52 | return self.sprite 53 | 54 | def get_pixelbuffer(self) -> PixelBuffer: 55 | if self.pixelbuffer is not None: 56 | return self.pixelbuffer 57 | else: 58 | assert self.filename is not None 59 | self.pixelbuffer = PixelBuffer.from_file(self.filename) 60 | return self.pixelbuffer 61 | 62 | def calc_color(self) -> Color: 63 | logging.info("Tile::calc_color not implemented") 64 | return Color(255, 255, 255, 255) 65 | 66 | def get_filename(self) -> Optional[str]: 67 | return self.filename 68 | 69 | 70 | # EOF # 71 | -------------------------------------------------------------------------------- /flexlay/tileset.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | from flexlay.tile import Tile 21 | 22 | 23 | class Tileset: 24 | 25 | def __init__(self, tile_size: int) -> None: 26 | self.tiles: dict[int, Optional[Tile]] = {} 27 | self.tile_size = tile_size 28 | 29 | def add_tile(self, tile_id: int, tile: Optional[Tile]) -> None: 30 | self.tiles[tile_id] = tile 31 | 32 | def create(self, tile_id: int) -> Tile: 33 | tile = self.tiles.get(tile_id) 34 | assert tile is not None 35 | return tile 36 | 37 | def get_tile_size(self) -> int: 38 | return self.tile_size 39 | 40 | def get_tiles(self) -> list[int]: 41 | return list(self.tiles.keys()) 42 | 43 | 44 | # EOF # 45 | -------------------------------------------------------------------------------- /flexlay/tool_context.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | from flexlay.gui.tile_selection import TileSelection 21 | from flexlay.tile_brush import TileBrush 22 | from flexlay.object_layer import ObjectLayer 23 | from flexlay.tilemap_layer import TilemapLayer 24 | from flexlay.objmap_object import ObjMapObject 25 | 26 | 27 | class ToolContext: 28 | 29 | current = None 30 | 31 | def __init__(self) -> None: 32 | ToolContext.current = self 33 | self.tile_brush = TileBrush(1, 1) 34 | self.tile_brush.put(0, 0, 0) 35 | self.tile_brush.set_opaque() 36 | 37 | self.tile_selection = TileSelection() 38 | 39 | self.object_selection: list[ObjMapObject] = [] 40 | 41 | self.tilemap_layer: Optional[TilemapLayer] = None 42 | self.object_layer: Optional[ObjectLayer] = None 43 | 44 | 45 | # EOF # 46 | -------------------------------------------------------------------------------- /flexlay/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/tools/__init__.py -------------------------------------------------------------------------------- /flexlay/tools/tile_fill_tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.editor_map_component import EditorMapComponent 19 | from flexlay.tool_context import ToolContext 20 | from flexlay.tools.tool import Tool 21 | from flexlay.input_event import InputEvent 22 | 23 | 24 | class TileFillTool(Tool): 25 | current = None 26 | 27 | def __init__(self) -> None: 28 | super().__init__() 29 | 30 | TileFillTool.current = self 31 | 32 | def on_mouse_down(self, event: InputEvent) -> None: 33 | assert EditorMapComponent.current is not None 34 | assert ToolContext.current is not None 35 | assert event.mouse_pos is not None 36 | 37 | tilemap = ToolContext.current.tilemap_layer 38 | 39 | if tilemap and not tilemap.hidden: 40 | parent = EditorMapComponent.current 41 | pos = tilemap.world2tile(parent.screen2world(event.mouse_pos.to_f())) 42 | tilemap.flood_fill_at(pos, ToolContext.current.tile_brush) 43 | # GRUMBEL: undo missing 44 | 45 | 46 | # EOF # 47 | -------------------------------------------------------------------------------- /flexlay/tools/tile_replace_tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.editor_map_component import EditorMapComponent 19 | from flexlay.tool_context import ToolContext 20 | from flexlay.tools.tool import Tool 21 | from flexlay.input_event import InputEvent 22 | 23 | 24 | class TileReplaceTool(Tool): 25 | 26 | current = None 27 | 28 | def __init__(self) -> None: 29 | super().__init__() 30 | 31 | TileReplaceTool.current = self 32 | 33 | def on_mouse_down(self, event: InputEvent) -> None: 34 | assert EditorMapComponent.current is not None 35 | assert ToolContext.current is not None 36 | assert event.mouse_pos is not None 37 | assert ToolContext.current.tilemap_layer is not None 38 | 39 | tilemap = ToolContext.current.tilemap_layer 40 | if tilemap and not tilemap.hidden: 41 | assert EditorMapComponent.current is not None 42 | parent = EditorMapComponent.current 43 | pos = tilemap.world2tile(parent.screen2world(event.mouse_pos.to_f())) 44 | tilemap.replace_tile(tilemap.field.at(pos.x, pos.y), 45 | ToolContext.current.tile_brush.at(0, 0)) 46 | # GRUMBEL: undo missing 47 | 48 | 49 | # EOF # 50 | -------------------------------------------------------------------------------- /flexlay/tools/tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.graphic_context import GraphicContext 19 | from flexlay.input_event import InputEvent 20 | 21 | 22 | class Tool: 23 | 24 | def __init__(self) -> None: 25 | pass 26 | 27 | def draw(self, gc: GraphicContext) -> None: 28 | pass 29 | 30 | def on_mouse_down(self, event: InputEvent) -> None: 31 | pass 32 | 33 | def on_mouse_up(self, event: InputEvent) -> None: 34 | pass 35 | 36 | def on_mouse_move(self, event: InputEvent) -> None: 37 | pass 38 | 39 | def grab_mouse(self) -> None: 40 | from flexlay.gui.editor_map_component import EditorMapComponent 41 | 42 | assert EditorMapComponent.current is not None 43 | EditorMapComponent.current.grab_mouse() 44 | 45 | def release_mouse(self) -> None: 46 | from flexlay.gui.editor_map_component import EditorMapComponent 47 | 48 | assert EditorMapComponent.current is not None 49 | EditorMapComponent.current.release_mouse() 50 | 51 | 52 | # EOF # 53 | -------------------------------------------------------------------------------- /flexlay/tools/workspace_move_tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import math 19 | 20 | from flexlay.gui.editor_map_component import EditorMapComponent 21 | from flexlay.math import Point, Pointf 22 | from flexlay.input_event import InputEvent 23 | from flexlay.graphic_context import GraphicContext 24 | from flexlay.tools.tool import Tool 25 | 26 | 27 | class WorkspaceMoveTool(Tool): 28 | 29 | def __init__(self) -> None: 30 | self.scrolling: bool = False 31 | self.click_pos: Point = Point(0, 0) 32 | self.old_trans_offset: Pointf = Pointf(0, 0) 33 | 34 | def on_mouse_down(self, event: InputEvent) -> None: 35 | assert EditorMapComponent.current is not None 36 | assert event.mouse_pos is not None 37 | 38 | self.scrolling = True 39 | self.old_trans_offset = EditorMapComponent.current.get_gc_state().get_pos() 40 | self.click_pos = event.mouse_pos 41 | EditorMapComponent.current.grab_mouse() 42 | 43 | def on_mouse_up(self, event: InputEvent) -> None: 44 | assert event.mouse_pos is not None 45 | assert EditorMapComponent.current is not None 46 | 47 | self.scrolling = False 48 | self.update(event) 49 | self.old_trans_offset = EditorMapComponent.current.get_gc_state().get_pos() 50 | EditorMapComponent.current.release_mouse() 51 | 52 | def on_mouse_move(self, event: InputEvent) -> None: 53 | if self.scrolling: 54 | self.update(event) 55 | 56 | def draw(self, gc: GraphicContext) -> None: 57 | pass 58 | 59 | def update(self, event: InputEvent) -> None: 60 | assert EditorMapComponent.current is not None 61 | 62 | gc_state = EditorMapComponent.current.get_gc_state() 63 | 64 | sa = math.sin(-gc_state.get_rotation() / 180.0 * math.pi) 65 | ca = math.cos(-gc_state.get_rotation() / 180.0 * math.pi) 66 | 67 | assert event.mouse_pos is not None 68 | dx = ca * (self.click_pos.x - event.mouse_pos.x) - sa * (self.click_pos.y - event.mouse_pos.y) 69 | dy = sa * (self.click_pos.x - event.mouse_pos.x) + ca * (self.click_pos.y - event.mouse_pos.y) 70 | 71 | gc_state.set_pos(Pointf(self.old_trans_offset.x + dx / EditorMapComponent.current.get_gc_state().get_zoom(), 72 | self.old_trans_offset.y + dy / EditorMapComponent.current.get_gc_state().get_zoom())) 73 | 74 | 75 | # EOF # 76 | -------------------------------------------------------------------------------- /flexlay/tools/zoom2_tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.editor_map_component import EditorMapComponent 19 | from flexlay.math import Pointf 20 | from flexlay.tools.tool import Tool 21 | from flexlay.input_event import InputEvent 22 | 23 | 24 | class Zoom2Tool(Tool): 25 | 26 | def __init__(self) -> None: 27 | super().__init__() 28 | 29 | self.active: bool = False 30 | self.click_pos = Pointf(0, 0) 31 | self.old_zoom: float = 0.0 32 | 33 | def on_mouse_up(self, event: InputEvent) -> None: 34 | self.active = False 35 | 36 | def on_mouse_down(self, event: InputEvent) -> None: 37 | assert EditorMapComponent.current is not None 38 | assert event.mouse_pos is not None 39 | 40 | self.active = True 41 | self.click_pos = event.mouse_pos.to_f() 42 | 43 | gc = EditorMapComponent.current.get_gc_state() 44 | self.old_zoom = gc.get_zoom() 45 | 46 | def on_mouse_move(self, event: InputEvent) -> None: 47 | assert EditorMapComponent.current is not None 48 | assert event.mouse_pos is not None 49 | 50 | if self.active: 51 | gc = EditorMapComponent.current.get_gc_state() 52 | zoom_pos = Pointf(gc.width / 2, gc.height / 2) 53 | 54 | factor = (event.mouse_pos.y - self.click_pos.y) / 20.0 55 | if factor > 0: 56 | gc.set_zoom(self.old_zoom * pow(1.25, factor), zoom_pos) 57 | elif factor < 0: 58 | gc.set_zoom(self.old_zoom / pow(1.25, -factor), zoom_pos) 59 | else: 60 | gc.set_zoom(self.old_zoom, zoom_pos) 61 | 62 | 63 | # EOF # 64 | -------------------------------------------------------------------------------- /flexlay/tools/zoom_out_tool.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.editor_map_component import EditorMapComponent 19 | from flexlay.input_event import InputEvent 20 | from flexlay.tools.tool import Tool 21 | 22 | 23 | class ZoomOutTool(Tool): 24 | 25 | def __init__(self) -> None: 26 | super().__init__() 27 | 28 | def on_mouse_down(self, event: InputEvent) -> None: 29 | assert EditorMapComponent.current is not None 30 | assert event.mouse_pos is not None 31 | 32 | parent = EditorMapComponent.current 33 | if event.kind == InputEvent.MOUSE_RIGHT: 34 | parent.zoom_out(event.mouse_pos.to_f()) 35 | 36 | 37 | # EOF # 38 | -------------------------------------------------------------------------------- /flexlay/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/util/__init__.py -------------------------------------------------------------------------------- /flexlay/util/sexpr_reader.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Optional 19 | 20 | 21 | SExprValue = Any # Union[bool, int, float, str, list] 22 | 23 | 24 | def sexpr_filter(name: str, tree: list[SExprValue]) -> SExprValue: 25 | ret = [] 26 | for i in tree: 27 | if i[0] == name: 28 | ret.append(i[1:]) 29 | return ret 30 | 31 | 32 | def assoc_ref(lst: list[SExprValue], key: str) -> Optional[SExprValue]: 33 | if lst == []: 34 | return None 35 | elif lst[0][0] == key: 36 | return lst[0][1:] 37 | else: 38 | return assoc_ref(lst[1:], key) 39 | 40 | 41 | def get_value_from_tree(spec: list[str], tree: SExprValue, default: Any) -> Any: 42 | if spec == []: 43 | return tree 44 | elif spec == ['_']: 45 | # is it a translatable string? 46 | if isinstance(tree[0], list) and tree[0][0] == "_": 47 | return tree[0][1] 48 | else: 49 | return tree[0] 50 | elif tree == []: 51 | return default 52 | else: 53 | el = assoc_ref(tree, spec[0]) 54 | if el is not None: 55 | return get_value_from_tree(spec[1:], el, default) 56 | else: 57 | return default 58 | 59 | 60 | class SExprReader: 61 | 62 | def __init__(self) -> None: 63 | pass 64 | 65 | 66 | # EOF # 67 | -------------------------------------------------------------------------------- /flexlay/util/signal.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Callable 19 | 20 | 21 | SignalCallback = Callable[..., None] 22 | 23 | 24 | class Signal: 25 | 26 | def __init__(self) -> None: 27 | self.subscribers: list[SignalCallback] = [] 28 | 29 | def connect(self, callback: SignalCallback, ignore_repeats: bool = True) -> None: 30 | if not ignore_repeats and callback in self.subscribers: 31 | return 32 | self.subscribers.append(callback) 33 | 34 | def disconnect(self, callback: SignalCallback) -> None: 35 | self.subscribers.remove(callback) 36 | 37 | def clear(self) -> None: 38 | self.subscribers = [] 39 | 40 | def __call__(self, *args: Any) -> None: 41 | for sub in self.subscribers: 42 | sub(*args) 43 | 44 | 45 | # EOF # 46 | -------------------------------------------------------------------------------- /flexlay/util/version.py: -------------------------------------------------------------------------------- 1 | # EOF # 2 | -------------------------------------------------------------------------------- /flexlay/wip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/flexlay/wip/__init__.py -------------------------------------------------------------------------------- /flexlay/wip/brush.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class Brush: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | def get_sprite(self) -> None: 24 | pass 25 | 26 | def copy(self) -> None: 27 | pass 28 | 29 | 30 | # EOF # 31 | -------------------------------------------------------------------------------- /flexlay/wip/brushmask.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class BrushMask: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | 24 | # EOF # 25 | -------------------------------------------------------------------------------- /flexlay/wip/canvas.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.wip.surface import Surface 19 | 20 | 21 | class Canvas: 22 | 23 | def __init__(self, surface: Surface) -> None: 24 | pass 25 | 26 | def get_gc(self) -> None: 27 | pass 28 | 29 | def sync_surface(self) -> None: 30 | pass 31 | 32 | def get_pixeldata(self) -> None: 33 | pass 34 | 35 | 36 | # EOF # 37 | -------------------------------------------------------------------------------- /flexlay/wip/display.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class Display: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | @property 24 | def width(self) -> int: 25 | return 0 26 | 27 | @property 28 | def height(self) -> int: 29 | return 0 30 | 31 | def get_modelview(self) -> None: 32 | pass 33 | 34 | 35 | # EOF # 36 | -------------------------------------------------------------------------------- /flexlay/wip/stroke_drawer.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.graphic_context import GraphicContext 19 | from flexlay.wip.stroke import Stroke 20 | 21 | 22 | class StrokeDrawer: 23 | 24 | def __init__(self) -> None: 25 | pass 26 | 27 | def draw(self, stroke: Stroke, gc: GraphicContext) -> None: 28 | pass 29 | 30 | 31 | # EOF # 32 | -------------------------------------------------------------------------------- /flexlay/wip/surface.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.math import Rect 19 | from flexlay.pixel_buffer import PixelBuffer 20 | 21 | 22 | class Surface: 23 | 24 | def __init__(self, pixelbuffer: PixelBuffer) -> None: 25 | pass 26 | 27 | def draw_stretched(self, rect: Rect) -> None: 28 | pass 29 | 30 | def draw(self, x: int, y: int) -> None: 31 | pass 32 | 33 | def set_alignment(self, origin: int, x: int = 0, y: int = 0) -> None: 34 | pass 35 | 36 | def set_alpha(self, alpha: int) -> None: 37 | pass 38 | 39 | def set_scale(self, x: float, y: float) -> None: 40 | pass 41 | 42 | def set_blend_func(self, src, dest) -> None: 43 | pass 44 | 45 | @property 46 | def width(self) -> int: 47 | return 0 48 | 49 | @property 50 | def height(self) -> int: 51 | return 0 52 | 53 | 54 | # EOF # 55 | -------------------------------------------------------------------------------- /flexlay/wip/tile_provider.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class TileProvider: 19 | 20 | def __init__(self) -> None: 21 | pass 22 | 23 | 24 | # EOF # 25 | -------------------------------------------------------------------------------- /flexlay/workspace.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, Optional 19 | 20 | import logging 21 | 22 | from flexlay.editor_map import EditorMap 23 | from flexlay.graphic_context import GraphicContext 24 | from flexlay.input_event import InputEvent 25 | from flexlay.tools.tool import Tool 26 | 27 | # from supertux.sector import Sector 28 | 29 | 30 | class Workspace: 31 | 32 | current = None 33 | 34 | def __init__(self) -> None: 35 | Workspace.current = self 36 | 37 | self.tools: dict[int, 'Tool'] = {} 38 | self.editor_map: Optional[EditorMap] = None 39 | self.current_sector: Optional[Any] = None 40 | 41 | def draw(self, gc: GraphicContext) -> None: 42 | if self.editor_map: 43 | self.editor_map.draw(gc) 44 | 45 | # FIXME: Only draw active tool?! 46 | for tool in self.tools.values(): 47 | tool.draw(gc) 48 | 49 | def mouse_up(self, event: InputEvent) -> None: 50 | tool = self.tools.get(event.kind) 51 | if tool is not None: 52 | tool.on_mouse_up(event) 53 | 54 | def mouse_move(self, event: InputEvent) -> None: 55 | for tool in self.tools.values(): 56 | tool.on_mouse_move(event) 57 | 58 | def mouse_down(self, event: InputEvent) -> None: 59 | tool = self.tools.get(event.kind) 60 | if tool is not None: 61 | tool.on_mouse_down(event) 62 | 63 | def key_up(self, event: InputEvent) -> None: 64 | tool = self.tools.get(event.kind) 65 | if tool is not None: 66 | tool.on_mouse_up(event) 67 | 68 | def key_down(self, event: InputEvent) -> None: 69 | tool = self.tools.get(event.kind) 70 | if tool is not None: 71 | tool.on_mouse_down(event) 72 | else: 73 | logging.info("Workspace: " + str(event.kind)) 74 | 75 | def get_map(self) -> EditorMap: 76 | assert self.editor_map is not None 77 | return self.editor_map 78 | 79 | def set_map(self, editor_map: EditorMap) -> None: 80 | self.editor_map = editor_map 81 | 82 | def set_tool(self, button: int, tool: Optional[Tool]) -> None: 83 | from flexlay.tools.tool import Tool 84 | if tool is None: 85 | tool = Tool() 86 | self.tools[button] = tool 87 | 88 | 89 | # EOF # 90 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/logo.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.pyright] 2 | include = ["flexlay", "supertux", "tests"] 3 | exclude = ["flexlay/wip"] 4 | 5 | # EOF # 6 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = flexlay 3 | version = 0.2.0 4 | description = "A Generic 2D Game Editor" 5 | long_description = file: README.md 6 | license = GPLv3+ 7 | author = "Ingo Ruhnke" 8 | author_email = "grumbel@gmail.com" 9 | url = http://github.com/flexlay/flexlay 10 | 11 | [options] 12 | packages = find: 13 | 14 | [options.entry_points] 15 | gui_scripts = 16 | supertux-editor = supertux.supertux:main 17 | supertux-texteditor = supertux.text_editor.cmd_supertux_textedit:main 18 | 19 | [flake8] 20 | max-line-length = 120 21 | 22 | [mypy] 23 | plugins = numpy.typing.mypy_plugin 24 | strict = True 25 | check_untyped_defs = True 26 | disallow_untyped_defs = True 27 | warn_return_any = True 28 | warn_unreachable = True 29 | warn_unused_configs = True 30 | warn_unused_ignores = False 31 | 32 | # must be False, see https://github.com/python/mypy/issues/10757 33 | disallow_untyped_calls = False 34 | 35 | # triggered by QObject 36 | disallow_subclassing_any = False 37 | 38 | # Can't use this due to mypy/pyright having different ideas about cast() 39 | warn_redundant_casts = False 40 | 41 | [mypy-flexlay.wip.*] 42 | ignore_errors = True 43 | 44 | [pylint] 45 | extension-pkg-whitelist = PyQt5 46 | disable = 47 | broad-except, 48 | consider-using-f-string, 49 | consider-using-in, 50 | duplicate-code, 51 | fixme, 52 | import-outside-toplevel, 53 | invalid-name, 54 | logging-format-interpolation, 55 | logging-fstring-interpolation, 56 | missing-class-docstring, 57 | missing-function-docstring, 58 | missing-module-docstring, 59 | no-else-return, 60 | no-self-use, 61 | protected-access, 62 | superfluous-parens, 63 | too-few-public-methods, 64 | too-many-arguments, 65 | too-many-branches, 66 | too-many-instance-attributes, 67 | too-many-locals, 68 | too-many-public-methods, 69 | too-many-return-statements, 70 | too-many-statements, 71 | unnecessary-lambda, 72 | unspecified-encoding, 73 | unused-argument, 74 | unused-variable, 75 | using-constant-test, 76 | too-many-nested-blocks, 77 | use-implicit-booleaness-not-comparison, 78 | consider-using-from-import, 79 | useless-super-delegation, 80 | consider-iterating-dictionary, 81 | 82 | [pylint.FORMAT] 83 | max-line-length = 120 84 | 85 | # EOF # 86 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | setup() 3 | -------------------------------------------------------------------------------- /supertux-editor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2014 Ingo Ruhnke 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import sys 21 | 22 | import supertux 23 | 24 | if __name__ == "__main__": 25 | sys.path.append(".") 26 | supertux.main() 27 | 28 | 29 | # EOF # 30 | -------------------------------------------------------------------------------- /supertux-level: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2014 Ingo Ruhnke 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import argparse 21 | import logging 22 | import sys 23 | 24 | from flexlay.util.config import Config 25 | from supertux.level import Level 26 | from supertux.config import make_config 27 | 28 | 29 | def main(): 30 | has_error = False 31 | parser = argparse.ArgumentParser(description="SuperTux Level Tool") 32 | parser.add_argument("LEVELFILE", action="store", type=str, nargs="+", 33 | help=".stl file to load") 34 | parser.add_argument("-d", "--datadir", metavar="DIR", action="store", type=str, 35 | help="SuperTux data directory directory") 36 | parser.add_argument("-o", "--output", metavar="FILE", action="store", type=str, 37 | help="Load and resave the level to FILE") 38 | parser.add_argument("--resave", action="store_true", default=False, 39 | help="Load and resave level in place") 40 | args = parser.parse_args() 41 | 42 | config = make_config() 43 | if args.datadir is not None: 44 | config.datadir = args.datadir 45 | elif not config.datadir: 46 | raise RuntimeError("datadir missing, use --datadir DIR") 47 | 48 | for levelfile in args.LEVELFILE: 49 | logging.info("Loading {}".format(levelfile)) 50 | try: 51 | level = Level.from_file(levelfile) 52 | if args.output: 53 | level.save(args.output) 54 | elif args.resave: 55 | print("resaving {}".format(levelfile)) 56 | level.save(levelfile) 57 | except Exception as err: 58 | logging.exception("ERROR: {}", err) 59 | has_error = True 60 | 61 | return 1 if has_error else 0 62 | 63 | 64 | if __name__ == "__main__": 65 | sys.exit(main()) 66 | 67 | 68 | # EOF # 69 | -------------------------------------------------------------------------------- /supertux/TODO: -------------------------------------------------------------------------------- 1 | ToDo: 2 | ===== 3 | 4 | - smooth selection 5 | - tile editor 6 | - wrapper sexpr parser into a read class, LispReader like 7 | - turn proc{} into blocks 8 | - get rid of 'mysprite' 9 | - scrollbar in tileselector 10 | - gui and some magic to set the supertux datadir 11 | - support additional layers (paralax and normal) 12 | - doors/sector support needs improvement 13 | - moving platforms + path 14 | - camera path 15 | - automatic backup of files 16 | - get rid of make_metadat, get_ruby_object in SuperTux code 17 | - faster tile-loading (load on demand, pixelbuffer cache) 18 | - make controlpoints unzoomable 19 | - fix load/save and write a few testcases for them 20 | - seperate undoable functions from not undoable ones 21 | - provide feature to group/suspend undo/redo 22 | - objects need to have visible text-lables attached to them (name of 23 | spawnpoints, etc.) 24 | - sexpr based config file, no evil eval games 25 | - all pseudo object without position (background, particle-system) should be 26 | placed beside each other beginning at 0, -32. (Currently they're all placed 27 | at 0,0) 28 | 29 | New Object Types: 30 | ================= 31 | writer.start_list("camera"); 32 | if(mode == NORMAL) { 33 | writer.write_string("mode", "normal"); 34 | writer.write_bool("backscrolling", do_backscrolling); 35 | } else if(mode == AUTOSCROLL) { 36 | writer.write_string("mode", "autoscroll"); 37 | writer.start_list("path"); 38 | for(std::vector::iterator i = scrollpoints.begin(); 39 | i != scrollpoints.end(); ++i) { 40 | writer.start_list("point"); 41 | writer.write_float("x", i->position.x); 42 | writer.write_float("y", i->position.y); 43 | writer.write_float("speed", i->speed); 44 | writer.end_list("point"); 45 | } 46 | writer.end_list("path"); 47 | } else if(mode == MANUAL) { 48 | writer.write_string("mode", "manual"); 49 | } 50 | 51 | 52 | Bugs 53 | ==== 54 | 55 | - switching to the current sector resets visible properties 56 | - sometime the tilemap is alot huger than the level 57 | 58 | # EOF # 59 | -------------------------------------------------------------------------------- /supertux/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/supertux/__init__.py -------------------------------------------------------------------------------- /supertux/__main__.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2022 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | import supertux.supertux 18 | 19 | supertux.supertux.main() 20 | 21 | # EOF # 22 | -------------------------------------------------------------------------------- /supertux/addon_dialog.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.file_dialog import OpenFileDialog, SaveDirectoryDialog 19 | 20 | 21 | class OpenAddonDialog(OpenFileDialog): 22 | 23 | def __init__(self, title: str) -> None: 24 | super().__init__(title, ("SuperTux Add-ons (*.zip)", 25 | "All Files (*)")) 26 | 27 | 28 | class SaveAddonDialog(SaveDirectoryDialog): 29 | 30 | def __init__(self, title: str, is_worldmap: bool = False) -> None: 31 | super().__init__(title) 32 | 33 | 34 | # EOF # 35 | -------------------------------------------------------------------------------- /supertux/config.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2018 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.util.config import Config 19 | 20 | 21 | def make_config() -> Config: 22 | config = Config.create("supertux-editor") 23 | config.create_attribute("datadir") 24 | config.create_attribute("binary") 25 | config.create_attribute("name", "Anonymous") 26 | config.load() 27 | return config 28 | 29 | 30 | # EOF # 31 | -------------------------------------------------------------------------------- /supertux/constraint.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class Constraint: 19 | 20 | def __init(self) -> None: 21 | pass 22 | 23 | 24 | class GridConstraint(Constraint): 25 | 26 | def __init__(self, width: int, height: int, offset_x: int, offset_y: int) -> None: 27 | pass 28 | 29 | 30 | # EOF # 31 | -------------------------------------------------------------------------------- /supertux/data.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | solid_itiles = [10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 30, 31, 113, 114] 19 | 20 | itile_conditions = [ 21 | [0, 0, 0, 0, 0, 1, 0, 1, 1, 7], 22 | [0, 0, 1, 0, 0, 1, 0, 1, 1, 7], 23 | [0, 0, 0, 0, 0, 0, 0, 1, 1, 7], 24 | [0, 0, 0, 0, 0, 0, 1, 1, 1, 8], 25 | [0, 0, 0, 0, 0, 0, 1, 1, 0, 9], 26 | [0, 1, 1, 0, 0, 0, 0, 0, 0, 16], 27 | 28 | [1, 1, 1, 0, 0, 0, 0, 0, 0, 17], 29 | [1, 1, 1, 1, 0, 0, 0, 0, 0, 17], 30 | [1, 1, 1, 0, 0, 1, 0, 0, 0, 17], 31 | [1, 1, 1, 1, 0, 0, 1, 0, 0, 17], 32 | [1, 1, 1, 0, 0, 1, 0, 0, 1, 17], 33 | 34 | [1, 1, 0, 0, 0, 0, 0, 0, 0, 18], 35 | 36 | [0, 1, 1, 0, 1, 1, 0, 0, 0, 10], 37 | [1, 1, 1, 0, 1, 1, 0, 0, 0, 11], 38 | [1, 1, 0, 1, 1, 0, 0, 0, 0, 12], 39 | 40 | [0, 1, 1, 0, 1, 1, 0, 1, 1, 10], 41 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 11], 42 | [1, 1, 0, 1, 1, 0, 1, 1, 0, 12], 43 | 44 | [0, 0, 0, 0, 1, 1, 0, 1, 1, 13], 45 | [0, 0, 0, 1, 1, 1, 1, 1, 1, 14], 46 | [0, 0, 0, 1, 1, 0, 1, 1, 0, 15], 47 | [1, 0, 0, 1, 1, 1, 1, 1, 1, 20], 48 | [1, 1, 0, 1, 1, 0, 1, 1, 1, 21], 49 | [0, 1, 1, 0, 1, 1, 1, 1, 1, 22], 50 | [0, 0, 1, 1, 1, 1, 1, 1, 1, 23], 51 | 52 | [1, 1, 1, 1, 1, 0, 1, 1, 0, 30], 53 | [1, 1, 1, 0, 1, 1, 0, 1, 1, 31], 54 | 55 | [0, 0, 0, 1, 1, 0, 1, 1, 1, 113], 56 | [0, 0, 0, 0, 1, 1, 1, 1, 1, 114], 57 | ] 58 | 59 | 60 | # EOF # 61 | -------------------------------------------------------------------------------- /supertux/gameobj_props_change_command.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2016 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See this 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Any, TYPE_CHECKING 19 | 20 | from flexlay.commands.command import Command 21 | 22 | if TYPE_CHECKING: 23 | from supertux.gameobj import GameObj 24 | 25 | 26 | class GameObjPropsChangeCommand(Command): 27 | """ 28 | This Command is run when a set of properties of an object are 29 | changed. 30 | """ 31 | 32 | def __init__(self, gameobj: 'GameObj', prop_diff: list[tuple[Any, Any, Any]]) -> None: 33 | """It's probably not a good idea to use this for non-directly 34 | editable properties. 35 | Warning: This will accept any value 36 | 37 | :param gameobj: GameObj this affects 38 | :param prop_diff: list of tuples of the form: 39 | (prop_index, execute_value, undo_value) 40 | """ 41 | super().__init__() 42 | 43 | self.gameobj = gameobj 44 | self.prop_diff = prop_diff 45 | 46 | def execute(self) -> None: 47 | for diff in self.prop_diff: 48 | print(self.gameobj.properties[diff[0]].value, "=", diff[1]) 49 | self.gameobj.properties[diff[0]].value = diff[1] 50 | 51 | def redo(self) -> None: 52 | for diff in self.prop_diff: 53 | self.gameobj.properties[diff[0]].value = diff[1] 54 | 55 | def undo(self) -> None: 56 | for diff in self.prop_diff: 57 | self.gameobj.properties[diff[0]].value = diff[2] 58 | 59 | 60 | # EOF # 61 | -------------------------------------------------------------------------------- /supertux/level_file_dialog.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.gui.file_dialog import OpenFileDialog, SaveFileDialog 19 | 20 | 21 | class OpenLevelFileDialog(OpenFileDialog): 22 | 23 | def __init__(self, title: str) -> None: 24 | super().__init__(title, ("SuperTux Files (*.stl *.stwm)", 25 | "SuperTux Levels (*.stl)", 26 | "SuperTux Worldmaps (*.stwm)", 27 | "All Files (*)")) 28 | 29 | 30 | class SaveLevelFileDialog(SaveFileDialog): 31 | 32 | def __init__(self, title: str, is_worldmap: bool = False) -> None: 33 | super().__init__(title, ".stwm" if is_worldmap else ".stl") 34 | 35 | 36 | # EOF # 37 | -------------------------------------------------------------------------------- /supertux/supertux_arguments.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import Optional 19 | 20 | from flexlay.util.config import Config 21 | 22 | 23 | class SuperTuxArguments: 24 | """A container for the various command line arguments of the SuperTux binary (not supertux-editor!)""" 25 | 26 | def __init__(self) -> None: 27 | self.run_level: Optional[str] = None 28 | # Not the same as a spawn point 29 | # Currently does nothing. 30 | self.spawn_at: Optional[str] = None 31 | self.record_demo_file: Optional[str] = None 32 | self.play_demo_file: Optional[str] = None 33 | 34 | def get_popen_arg(self) -> list[str]: 35 | """Returns a list to be passed straight into subprocess.Popen 36 | 37 | :return: A list to be passed as an argument for Popen 38 | """ 39 | run_level = [self.run_level] 40 | play_demo = ["--play-demo", self.play_demo_file] if self.record_demo_file is not None else [] 41 | record_demo = ["--record-demo", self.record_demo_file] if self.record_demo_file is not None else [] 42 | developer_mode = ["--developer"] 43 | # Not implemented in SuperTux! 44 | # spawn_at = ["--spawn-pos", 45 | # str(self.spawn_at.x), ",", 46 | # str(self.spawn_at.y)] \ 47 | # if self.spawn_at is not None \ 48 | # else [] 49 | assert Config.current is not None 50 | return [Config.current.binary] + run_level + play_demo + record_demo + developer_mode # + spawn_at 51 | 52 | 53 | # EOF # 54 | -------------------------------------------------------------------------------- /supertux/text_editor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/supertux/text_editor/__init__.py -------------------------------------------------------------------------------- /supertux/text_editor/cmd_supertux_textedit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2015 Karkus476 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | from typing import IO, Optional 21 | 22 | import sys 23 | 24 | from PyQt5.QtWidgets import (QMainWindow, QApplication, QVBoxLayout, 25 | QWidget) 26 | 27 | from supertux.text_editor.supertux_text_edit import SupertuxTextEdit 28 | from supertux.text_editor.highlighters.lisp_highlighter import SuperTuxLispHighlighter 29 | 30 | 31 | class SupertuxTextEditMainWindow(QMainWindow): 32 | 33 | def __init__(self, text_file: Optional[IO[str]] = None) -> None: 34 | super().__init__() 35 | 36 | self.setWindowTitle("Supertux Text Editor") 37 | 38 | self.central_widget = QWidget() 39 | self.setCentralWidget(self.central_widget) 40 | layout = QVBoxLayout() 41 | self.ide_widget = SupertuxTextEdit(self) 42 | layout.addWidget(self.ide_widget) 43 | self.central_widget.setLayout(layout) 44 | 45 | assert text_file is not None 46 | highlighter = SuperTuxLispHighlighter(self.ide_widget, text_file) 47 | highlighter.rehighlight() 48 | 49 | 50 | def main() -> None: 51 | sys.path.append(".") 52 | 53 | # file_path = input("Type the path to the file you'd like to open:") 54 | text_file = open("example.stl") # open(file_path, "r") 55 | 56 | app = QApplication(sys.argv) 57 | 58 | window = SupertuxTextEditMainWindow(text_file) 59 | window.show() 60 | 61 | app.exec_() 62 | 63 | # text_file.close() 64 | 65 | 66 | # EOF # 67 | -------------------------------------------------------------------------------- /supertux/text_editor/highlighters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SuperTux/flexlay/5e11055da6ba79c096128f450d3c317ddef04264/supertux/text_editor/highlighters/__init__.py -------------------------------------------------------------------------------- /supertux/text_editor/highlighters/patterns.json: -------------------------------------------------------------------------------- 1 | { 2 | "supertux-level":[ 3 | { 4 | "id":"version", 5 | "find":"\\(version [1-9]\\)", 6 | "type":"int", 7 | "color":"blue", 8 | "bold":true, 9 | "italic":false 10 | }, 11 | { 12 | "id":"name", 13 | "find":"\\(name .*\\)", 14 | "type":"str", 15 | "color":"blue", 16 | "bold":true, 17 | "italic":false 18 | }, 19 | { 20 | "id":"author", 21 | "find":"\\(author .*\\)", 22 | "type":"str", 23 | "color":"blue", 24 | "bold":true, 25 | "italic":false 26 | }, 27 | { 28 | "id":"target-time", 29 | "find":"\\(target-time [0-9]+\\)", 30 | "type":"int", 31 | "color":"blue", 32 | "bold":true, 33 | "italic":false 34 | }, 35 | { 36 | "id": "license", 37 | "find": "\\(license .*\\)", 38 | "type": "str", 39 | "color": "blue", 40 | "bold": true, 41 | "italic": false 42 | }, 43 | { 44 | "id":"x", 45 | "find":"\\(x [0-9]+(\\.[0-9]+)?\\)", 46 | "type":"int", 47 | "color":"red", 48 | "bold":false, 49 | "italic":true 50 | }, 51 | { 52 | "id":"y", 53 | "find":"\\(y [0-9]+(\\.[0-9]+)?\\)", 54 | "type":"int", 55 | "color":"red", 56 | "bold":false, 57 | "italic":true 58 | }, 59 | { 60 | "id":"width", 61 | "find":"\\(width [0-9]+(\\.[0-9]+)?\\)", 62 | "type":"int", 63 | "color":"red", 64 | "bold":false, 65 | "italic":true 66 | }, 67 | { 68 | "id":"height", 69 | "find":"\\(height [0-9]+(\\.[0-9]+)?\\)", 70 | "type":"int", 71 | "color":"red", 72 | "bold":false, 73 | "italic":true 74 | }, 75 | { 76 | "id":"root", 77 | "find":"supertux-level", 78 | "type":"list", 79 | "color":"red", 80 | "bold":true, 81 | "italic":false 82 | }, 83 | { 84 | "id": "comment", 85 | "find": ";.*", 86 | "type": "comment", 87 | "color": "darkGreen", 88 | "bold": false, 89 | "italic": true 90 | }, 91 | { 92 | "id":"sector", 93 | "find":"sector", 94 | "type":"list", 95 | "color":"darkBlue", 96 | "bold":true, 97 | "italic":false 98 | }, 99 | { 100 | "id":"tiles", 101 | "find":"\\(tiles\\)", 102 | "type":"tiles", 103 | "color":"magenta", 104 | "bold":true, 105 | "italic":false 106 | } 107 | ], 108 | "squirrel":[] 109 | } -------------------------------------------------------------------------------- /supertux/text_editor/highlighters/patterns2.json: -------------------------------------------------------------------------------- 1 | { 2 | "supertux-level":{ 3 | "id":"root", 4 | "type":"tree", 5 | "color": "red", 6 | "bold":true, 7 | "italic":false, 8 | "branches":{ 9 | "version":{ 10 | "id":"level-version", 11 | "type":"int", 12 | "color": "blue", 13 | "bold":true, 14 | "italic":false, 15 | "branches":{} 16 | }, 17 | "name":{ 18 | "id":"level-name", 19 | "type":"str", 20 | "color": "blue", 21 | "bold":true, 22 | "italic":false, 23 | "branches":{} 24 | }, 25 | "author":{ 26 | "id":"level-author", 27 | "type":"str", 28 | "color": "blue", 29 | "bold":true, 30 | "italic":false, 31 | "branches":{} 32 | }, 33 | "target-time":{ 34 | "id":"level-target-time", 35 | "type":"int", 36 | "color": "blue", 37 | "bold":true, 38 | "italic":false, 39 | "branches":{} 40 | }, 41 | "license":{ 42 | "id":"level-license", 43 | "type":"str", 44 | "color": "blue", 45 | "bold":true, 46 | "italic":false, 47 | "branches":{} 48 | }, 49 | "sector":{ 50 | "id":"level-sector", 51 | "type":"tree", 52 | "color": "darkBlue", 53 | "bold":true, 54 | "italic":false, 55 | "branches":{ 56 | "name":{ 57 | "id":"sector-name", 58 | "type":"str", 59 | "color": "darkGreen", 60 | "bold":false, 61 | "italic":false, 62 | "branches":{} 63 | } 64 | } 65 | } 66 | } 67 | }, 68 | "squirrel":[] 69 | } -------------------------------------------------------------------------------- /supertux/text_editor/highlighters/squirrel_highlighter.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | # EOF # 19 | -------------------------------------------------------------------------------- /supertux/text_editor/supertux_text_edit.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from PyQt5.QtWidgets import QWidget, QTextEdit 19 | 20 | 21 | class SupertuxTextEdit(QTextEdit): 22 | 23 | def __init__(self, parent: QWidget) -> None: 24 | super().__init__(parent) 25 | 26 | 27 | # EOF # 28 | -------------------------------------------------------------------------------- /supertux/util.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.util.sexpr import SExprValue, sexpr_read_from_file, SExprParseError 19 | 20 | 21 | def load_lisp(filename: str, root_symbol: str) -> SExprValue: 22 | """Convenience function that loads a lisp file from disk and checks for a root symbol""" 23 | 24 | tree = sexpr_read_from_file(filename)[0] 25 | if not isinstance(tree, list) or tree[0] != root_symbol: 26 | raise SExprParseError(filename, 0, 0, "Error: '{filename}' is not a '{root_symbol}' file") 27 | 28 | return tree 29 | 30 | 31 | # EOF # 32 | -------------------------------------------------------------------------------- /supertux/worldmap_object.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from flexlay.property import ( 19 | BoolProperty, 20 | StringProperty, 21 | ) 22 | from supertux.property import ( 23 | SpriteProperty, 24 | InlineTilePosProperty, 25 | ) 26 | from supertux.gameobj import GameObj, make_sprite_object 27 | 28 | 29 | class WorldmapLevel(GameObj): 30 | 31 | label = "WorldmapLevel" 32 | identifier = "level" 33 | sprite = "images/worldmap/common/leveldot_green.png" 34 | 35 | def __init__(self) -> None: 36 | super().__init__() 37 | 38 | self.objmap_object = make_sprite_object(self, self.sprite) 39 | self.signal_connect() 40 | 41 | self.properties = [ 42 | StringProperty("Level File", "name", ""), 43 | StringProperty("Extro Script", "extro-script", "", optional=True), 44 | BoolProperty("auto-play", "auto-play", False, optional=True), 45 | SpriteProperty("Sprite", "sprite"), 46 | InlineTilePosProperty() 47 | ] 48 | 49 | 50 | class SpecialTile(GameObj): 51 | 52 | label = "SpecialTile" 53 | identifier = "special-tile" 54 | sprite = "images/worldmap/common/leveldot.sprite" 55 | 56 | def __init__(self) -> None: 57 | super().__init__() 58 | 59 | self.objmap_object = make_sprite_object(self, self.sprite) 60 | self.signal_connect() 61 | 62 | self.properties = [ 63 | StringProperty("Name", "name", "main"), 64 | InlineTilePosProperty() 65 | ] 66 | 67 | 68 | class WorldmapSpawnpoint(GameObj): 69 | 70 | label = "WorldmapSpawnpoint" 71 | identifier = "worldmap-spawnpoint" 72 | sprite = "images/worldmap/common/tux.sprite" 73 | 74 | def __init__(self) -> None: 75 | super().__init__() 76 | 77 | self.objmap_object = make_sprite_object(self, self.sprite) 78 | self.signal_connect() 79 | 80 | self.properties = [ 81 | StringProperty("Name", "name", "main"), 82 | InlineTilePosProperty() 83 | ] 84 | 85 | 86 | # EOF # 87 | -------------------------------------------------------------------------------- /tests/test_flexlay.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2014 Ingo Ruhnke 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import unittest 19 | 20 | import flexlay 21 | import flexlay.gui 22 | import flexlay.math 23 | import flexlay.tools 24 | import flexlay.util 25 | 26 | 27 | class FlexlayTestCase(unittest.TestCase): 28 | 29 | def test_imports(self) -> None: 30 | id(flexlay) 31 | id(flexlay.math) 32 | id(flexlay.util) 33 | id(flexlay.tools) 34 | id(flexlay.gui) 35 | 36 | 37 | # EOF # 38 | -------------------------------------------------------------------------------- /tests/test_generic_wizard.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from typing import cast 19 | 20 | import sys 21 | import unittest 22 | 23 | from PyQt5.QtWidgets import QApplication, QWidget 24 | 25 | from flexlay.gui.generic_wizard import GenericWizard 26 | from flexlay.gui.properties_widget import PropertiesWidget 27 | 28 | 29 | class FlexlayGenericWizardTestCase(unittest.TestCase): 30 | 31 | def simple_test(self) -> None: 32 | test_app = QApplication(sys.argv) 33 | 34 | test_wizard = GenericWizard(cast(QWidget, None), "Generic Wizard Test") 35 | 36 | page1 = PropertiesWidget(test_wizard) 37 | page1.add_label("Hello World!") 38 | page1.add_string("Type:", "Initial Value", (lambda val: print(val))) 39 | test_wizard.add_page("Page 1", page1) 40 | 41 | page2 = PropertiesWidget(test_wizard) 42 | page2.add_label("Hello World Again!") 43 | test_wizard.add_page("Page 2", page2) 44 | 45 | test_wizard.finish_callback.connect(lambda x: print(x)) 46 | 47 | test_wizard.show() 48 | 49 | test_app.exec() 50 | 51 | 52 | # EOF # 53 | -------------------------------------------------------------------------------- /tests/test_math.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2014 Ingo Ruhnke 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import unittest 21 | 22 | from flexlay.math import Point 23 | 24 | 25 | class FlexlayMathTestCase(unittest.TestCase): 26 | 27 | def test_point(self) -> None: 28 | p = Point(11, 17) 29 | self.assertEqual(p.x, 11) 30 | self.assertEqual(p.y, 17) 31 | 32 | p = 3 * p 33 | p = p * 4 34 | p *= 5 35 | self.assertEqual(p.x, 660) 36 | self.assertEqual(p.y, 1020) 37 | 38 | p = Point(0, 3) + p 39 | p = p + Point(4, 0) 40 | p += Point(1, 2) 41 | self.assertEqual(p.x, 665) 42 | self.assertEqual(p.y, 1025) 43 | 44 | self.assertEqual(Point(11, 17), Point(11, 17)) 45 | 46 | p2 = p.copy() 47 | self.assertEqual(p, p2) 48 | p2.x += 2 49 | p2.y += 3 50 | self.assertNotEqual(p, p2) 51 | 52 | 53 | # EOF # 54 | -------------------------------------------------------------------------------- /tests/test_signal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2014 Ingo Ruhnke 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import unittest 21 | import unittest.mock 22 | 23 | from flexlay.util.signal import Signal 24 | 25 | 26 | class SignalTestCase(unittest.TestCase): 27 | 28 | def setUp(self) -> None: 29 | pass 30 | 31 | def tearDown(self) -> None: 32 | pass 33 | 34 | def test_signal_args(self) -> None: 35 | signal = Signal() 36 | mock1 = unittest.mock.Mock() 37 | mock2 = unittest.mock.Mock() 38 | signal.connect(mock1) 39 | signal.connect(mock2) 40 | signal(9, 11, 13) 41 | mock1.assert_called_with(9, 11, 13) 42 | mock2.assert_called_with(9, 11, 13) 43 | self.assertEqual(mock1.call_count, 1) 44 | self.assertEqual(mock2.call_count, 1) 45 | 46 | def test_signal_connect(self) -> None: 47 | signal = Signal() 48 | mock1 = unittest.mock.Mock() 49 | mock2 = unittest.mock.Mock() 50 | signal.connect(mock1) 51 | signal.connect(mock2) 52 | signal() 53 | mock1.assert_called_with() 54 | mock2.assert_called_with() 55 | self.assertEqual(mock1.call_count, 1) 56 | self.assertEqual(mock2.call_count, 1) 57 | 58 | def test_signal_disconnect(self) -> None: 59 | signal = Signal() 60 | mock1 = unittest.mock.Mock() 61 | mock2 = unittest.mock.Mock() 62 | signal.connect(mock1) 63 | signal.connect(mock2) 64 | signal.disconnect(mock1) 65 | signal() 66 | self.assertEqual(mock1.call_count, 0) 67 | self.assertEqual(mock2.call_count, 1) 68 | 69 | 70 | if __name__ == '__main__': 71 | unittest.main() 72 | 73 | 74 | # EOF # 75 | -------------------------------------------------------------------------------- /tests/test_supertux.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Flexlay - A Generic 2D Game Editor 4 | # Copyright (C) 2014 Ingo Ruhnke 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import io 21 | import os 22 | import unittest 23 | import unittest.mock 24 | 25 | from flexlay.util.config import Config 26 | from flexlay.math import Point, Pointf, Size 27 | from supertux.gameobj_factor import supertux_gameobj_factory 28 | from supertux.level import Level 29 | 30 | test_levelfile = os.path.join(os.path.dirname(__file__), "test.stl") 31 | 32 | 33 | class SuperTuxTestCase(unittest.TestCase): 34 | 35 | def setUp(self) -> None: 36 | Config.create("supertux-editor") 37 | 38 | def tearDown(self) -> None: 39 | Config.current = None 40 | 41 | def test_level_load(self) -> None: 42 | level = Level.from_file(test_levelfile) 43 | self.assertEqual(level.name, "Welcome to Antarctica") 44 | 45 | def test_level_save(self) -> None: 46 | level = Level.from_file(test_levelfile) 47 | # with open("/tmp/test.stl", "w") as out: 48 | with io.StringIO() as out: 49 | level.save_io(out) 50 | # print(out.getvalue()) 51 | 52 | def test_level_new(self) -> None: 53 | level = Level.from_size(400, 300) 54 | self.assertEqual(level.name, "No Name") 55 | 56 | def test_gameobj_factory_create_object_brushes(self) -> None: 57 | supertux_gameobj_factory.create_object_brushes() 58 | 59 | def test_gameobj_factory_create_gameobj_at(self) -> None: 60 | for identifier, (_, _) in supertux_gameobj_factory.objects.items(): 61 | try: 62 | _ = supertux_gameobj_factory.create_gameobj_at(identifier, Pointf(0, 0)) 63 | except Exception: 64 | print(f"Exception received: {identifier}") 65 | raise 66 | 67 | def test_level_resize(self) -> None: 68 | level = Level.from_file(test_levelfile) 69 | level.sectors[0].resize(Size(10, 10), Point(10, 10)) 70 | 71 | 72 | if __name__ == '__main__': 73 | unittest.main() 74 | 75 | 76 | # EOF # 77 | -------------------------------------------------------------------------------- /tests/test_supertux_properties.py: -------------------------------------------------------------------------------- 1 | # Flexlay - A Generic 2D Game Editor 2 | # Copyright (C) 2015 Karkus476 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | # TODO: This! 18 | 19 | # EOF # 20 | --------------------------------------------------------------------------------