Compare commits
7 commits
9b7e7becc5
...
e924e8eb75
| Author | SHA1 | Date | |
|---|---|---|---|
| e924e8eb75 | |||
| 3c3cae682f | |||
| 536dce6a98 | |||
| 4619444ed1 | |||
| 7abbb6bffb | |||
| 09a9059b27 | |||
| d84d1d809b |
89 changed files with 329 additions and 289 deletions
|
|
@ -7,7 +7,7 @@ we maintain our own git repo.
|
|||
|
||||
running
|
||||
-------
|
||||
just run launch the app (uv run python playscii.py)
|
||||
just run launch the app (uv run python -m playscii)
|
||||
just check lint gate (ruff check + format)
|
||||
just lint ruff check --fix + ruff format
|
||||
just typecheck ty check (601 errors, legacy code, not in check gate)
|
||||
|
|
@ -16,14 +16,19 @@ running
|
|||
|
||||
project structure
|
||||
-----------------
|
||||
all python source lives at the repo root (no src/ layout)
|
||||
~50 .py files, flat structure, no packages
|
||||
python source organized as playscii/ package (~50 .py files)
|
||||
data directories (charsets/, palettes/, etc.) live at repo root
|
||||
formats/ and games/ also at root (loaded dynamically via importlib)
|
||||
|
||||
playscii.py main entry point, app init, SDL2/OpenGL setup
|
||||
playscii/
|
||||
__init__.py package marker
|
||||
__main__.py entry point for python -m playscii
|
||||
app.py main application, SDL2/OpenGL setup (was playscii.py)
|
||||
art.py art/canvas management, the core data model
|
||||
ui*.py ~20 UI modules (dialogs, panels, menus, toolbar, etc.)
|
||||
game_*.py game engine (objects, rooms, world, HUD)
|
||||
renderable*.py rendering pipeline (sprites, lines, framebuffer)
|
||||
|
||||
formats/ import/export handlers (ANS, ATA, BMP, EDSCII, PNG, GIF, TXT)
|
||||
games/ bundled example games (crawler, fireplace, flood, maze, shmup, etc.)
|
||||
charsets/ 30+ classic computer character sets (.char + .png)
|
||||
|
|
@ -44,6 +49,12 @@ dependencies
|
|||
|
||||
gotchas
|
||||
-------
|
||||
package structure:
|
||||
all python source now lives in playscii/ package. files use relative
|
||||
imports (from .art import ...). formats/ and games/ use absolute imports
|
||||
(from playscii.art import ...). data directories stay at root since the
|
||||
app uses CWD-relative paths to load charsets, shaders, etc.
|
||||
|
||||
art scripts and exec():
|
||||
art.py imports random at module level with a noqa comment. art scripts
|
||||
(.arsc files) are loaded via exec() in art.py's scope. they use random
|
||||
|
|
@ -52,14 +63,14 @@ gotchas
|
|||
in art.py — check before removing anything.
|
||||
|
||||
pdoc detection:
|
||||
playscii.py has a contextlib.suppress block that tries to import pdoc.
|
||||
app.py has a contextlib.suppress block that tries to import pdoc.
|
||||
the import MUST stay inside the suppress block. if it gets moved or
|
||||
removed, pdoc_available becomes unconditionally True and the help menu
|
||||
breaks when pdoc isn't installed.
|
||||
|
||||
SDL2 init ordering:
|
||||
many modules import from playscii.py's namespace or expect SDL2 to be
|
||||
initialized before they run. import order in playscii.py matters — E402
|
||||
many modules import from app.py's namespace or expect SDL2 to be
|
||||
initialized before they run. import order in app.py matters — E402
|
||||
is disabled for this reason.
|
||||
|
||||
mutable default arguments:
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
venv/*.*
|
||||
dist/*.*
|
||||
build/*.*
|
||||
playscii/__pycache__/*.*
|
||||
__pycache__/*.*
|
||||
.idea/*.*
|
||||
playscii.profile
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_import import ArtImporter
|
||||
from playscii.art_import import ArtImporter
|
||||
|
||||
DEFAULT_FG, DEFAULT_BG = 7, 0
|
||||
WIDTH = 80
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_import import ArtImporter
|
||||
from playscii.art_import import ArtImporter
|
||||
|
||||
# import as white on black for ease of edit + export
|
||||
DEFAULT_FG, DEFAULT_BG = 113, 1
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@
|
|||
import os
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from art import DEFAULT_CHARSET, DEFAULT_HEIGHT, DEFAULT_PALETTE, DEFAULT_WIDTH
|
||||
from art_import import ArtImporter
|
||||
from image_convert import ImageConverter
|
||||
from palette import PaletteFromFile
|
||||
from ui_art_dialog import ImportOptionsDialog
|
||||
from ui_dialog import Field, UIDialog
|
||||
from ui_file_chooser_dialog import ImageFileChooserDialog
|
||||
from playscii.art import DEFAULT_CHARSET, DEFAULT_HEIGHT, DEFAULT_PALETTE, DEFAULT_WIDTH
|
||||
from playscii.art_import import ArtImporter
|
||||
from playscii.image_convert import ImageConverter
|
||||
from playscii.palette import PaletteFromFile
|
||||
from playscii.ui_art_dialog import ImportOptionsDialog
|
||||
from playscii.ui_dialog import Field, UIDialog
|
||||
from playscii.ui_file_chooser_dialog import ImageFileChooserDialog
|
||||
|
||||
# custom chooser showing image previews, shares parent w/ "palette from image"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import numpy as np
|
||||
|
||||
from formats.in_bitmap import (
|
||||
BitmapImageImporter,
|
||||
ConvertImageChooserDialog,
|
||||
ConvertImageOptionsDialog,
|
||||
)
|
||||
from image_convert import ImageConverter
|
||||
from ui_dialog import Field, SkipFieldType, UIDialog
|
||||
from playscii.image_convert import ImageConverter
|
||||
from playscii.ui_dialog import Field, SkipFieldType, UIDialog
|
||||
|
||||
|
||||
class TwoColorConvertImageOptionsDialog(ConvertImageOptionsDialog):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import os
|
|||
import time
|
||||
|
||||
import formats.in_bitmap as bm
|
||||
import image_convert
|
||||
from playscii import image_convert
|
||||
|
||||
|
||||
class ImageSequenceConverter:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from art_import import ArtImporter
|
||||
from ui_art_dialog import ImportOptionsDialog
|
||||
from ui_dialog import Field, UIDialog
|
||||
from playscii.art_import import ArtImporter
|
||||
from playscii.ui_art_dialog import ImportOptionsDialog
|
||||
from playscii.ui_dialog import Field, UIDialog
|
||||
|
||||
|
||||
class EDSCIIImportOptionsDialog(ImportOptionsDialog):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_import import ArtImporter
|
||||
from playscii.art_import import ArtImporter
|
||||
|
||||
|
||||
class EndDoomImporter(ArtImporter):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_import import ArtImporter
|
||||
from playscii.art_import import ArtImporter
|
||||
|
||||
|
||||
class TextImporter(ArtImporter):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_export import ArtExporter
|
||||
from playscii.art_export import ArtExporter
|
||||
|
||||
WIDTH = 80
|
||||
ENCODING = "cp1252" # old default
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from art import TileIter
|
||||
from art_export import ArtExporter
|
||||
from playscii.art import TileIter
|
||||
from playscii.art_export import ArtExporter
|
||||
|
||||
|
||||
class ANSExporter(ArtExporter):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_export import ArtExporter
|
||||
from playscii.art_export import ArtExporter
|
||||
|
||||
WIDTH, HEIGHT = 80, 25
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from art_export import ArtExporter
|
||||
from image_export import export_animation
|
||||
from playscii.art_export import ArtExporter
|
||||
from playscii.image_export import export_animation
|
||||
|
||||
|
||||
class GIFExporter(ArtExporter):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from art_export import ArtExporter
|
||||
from image_export import export_still_image
|
||||
from ui_art_dialog import ExportOptionsDialog
|
||||
from ui_dialog import Field, UIDialog
|
||||
from playscii.art_export import ArtExporter
|
||||
from playscii.image_export import export_still_image
|
||||
from playscii.ui_art_dialog import ExportOptionsDialog
|
||||
from playscii.ui_dialog import Field, UIDialog
|
||||
|
||||
DEFAULT_SCALE = 4
|
||||
DEFAULT_CRT = True
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import os
|
||||
|
||||
from art_export import ArtExporter
|
||||
from image_export import export_still_image
|
||||
from renderable import LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from ui_art_dialog import ExportOptionsDialog
|
||||
from ui_dialog import Field, UIDialog
|
||||
from playscii.art_export import ArtExporter
|
||||
from playscii.image_export import export_still_image
|
||||
from playscii.renderable import LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from playscii.ui_art_dialog import ExportOptionsDialog
|
||||
from playscii.ui_dialog import Field, UIDialog
|
||||
|
||||
FILE_EXTENSION = "png"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from art_export import ArtExporter
|
||||
from playscii.art_export import ArtExporter
|
||||
|
||||
|
||||
class TextExporter(ArtExporter):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from game_object import GameObject
|
||||
from playscii.game_object import GameObject
|
||||
|
||||
# initial work: 2019-02-17 and 18
|
||||
# FP view research: 2021-11-22
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import vector
|
||||
from game_object import GameObject
|
||||
from renderable_line import DebugLineRenderable
|
||||
from playscii import vector
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.renderable_line import DebugLineRenderable
|
||||
|
||||
# stuff for troubleshooting "get tiles intersecting line" etc
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from game_util_objects import Player
|
||||
from games.crawler.scripts.crawler import (
|
||||
DIR_EAST,
|
||||
DIR_NAMES,
|
||||
|
|
@ -9,6 +8,7 @@ from games.crawler.scripts.crawler import (
|
|||
OPPOSITE_DIRS,
|
||||
RIGHT_TURN_DIRS,
|
||||
)
|
||||
from playscii.game_util_objects import Player
|
||||
|
||||
|
||||
class CrawlPlayer(Player):
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
from art import TileIter
|
||||
from game_object import GameObject
|
||||
from games.crawler.scripts.crawler import (
|
||||
DIR_EAST,
|
||||
DIR_NORTH,
|
||||
DIR_SOUTH,
|
||||
DIR_WEST,
|
||||
)
|
||||
from vector import get_tiles_along_integer_line
|
||||
from playscii.art import TileIter
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.vector import get_tiles_along_integer_line
|
||||
|
||||
|
||||
class CrawlTopDownView(GameObject):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
from game_util_objects import DynamicBoxObject, Pickup, StaticTileObject, TopDownPlayer
|
||||
from playscii.game_util_objects import (
|
||||
DynamicBoxObject,
|
||||
Pickup,
|
||||
StaticTileObject,
|
||||
TopDownPlayer,
|
||||
)
|
||||
|
||||
|
||||
class CronoPlayer(TopDownPlayer):
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import os
|
|||
import webbrowser
|
||||
from random import choice, randint
|
||||
|
||||
from art import TileIter
|
||||
from game_object import GameObject
|
||||
from playscii.art import TileIter
|
||||
from playscii.game_object import GameObject
|
||||
|
||||
#
|
||||
# some tuning knobs
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from random import choice
|
||||
|
||||
from art import TileIter
|
||||
from game_object import GameObject
|
||||
from playscii.art import TileIter
|
||||
from playscii.game_object import GameObject
|
||||
|
||||
# TODO:
|
||||
# solver? https://stackoverflow.com/questions/1430962/how-to-optimally-solve-the-flood-fill-puzzle
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from game_hud import GameHUD, GameHUDRenderable
|
||||
from playscii.game_hud import GameHUD, GameHUDRenderable
|
||||
|
||||
|
||||
class MazeHUD(GameHUD):
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import math
|
||||
import random
|
||||
|
||||
from art import TileIter
|
||||
from collision import (
|
||||
from playscii.art import TileIter
|
||||
from playscii.collision import (
|
||||
CST_CIRCLE,
|
||||
CST_TILE,
|
||||
CT_GENERIC_DYNAMIC,
|
||||
CT_GENERIC_STATIC,
|
||||
CT_NONE,
|
||||
)
|
||||
from game_object import GameObject
|
||||
from game_util_objects import Player, StaticTileBG
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.game_util_objects import Player, StaticTileBG
|
||||
|
||||
|
||||
class MazeBG(StaticTileBG):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import math
|
||||
|
||||
from game_util_objects import BlobShadow, Player
|
||||
from games.maze.scripts.rooms import OutsideRoom
|
||||
from playscii.game_util_objects import BlobShadow, Player
|
||||
|
||||
|
||||
class PlayerBlobShadow(BlobShadow):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from game_room import GameRoom
|
||||
from playscii.game_room import GameRoom
|
||||
|
||||
|
||||
class MazeRoom(GameRoom):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import math
|
||||
import random
|
||||
|
||||
from game_util_objects import Character, Player, StaticTileBG, WarpTrigger
|
||||
from playscii.game_util_objects import Character, Player, StaticTileBG, WarpTrigger
|
||||
|
||||
|
||||
class PlatformWorld(StaticTileBG):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import math
|
||||
import random
|
||||
|
||||
from game_object import GameObject
|
||||
from game_util_objects import Character, ObjectSpawner, Player, Projectile, StaticTileBG
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.game_util_objects import (
|
||||
Character,
|
||||
ObjectSpawner,
|
||||
Player,
|
||||
Projectile,
|
||||
StaticTileBG,
|
||||
)
|
||||
|
||||
|
||||
class ShmupPlayer(Player):
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import random
|
||||
import time
|
||||
|
||||
from art import ART_DIR, UV_FLIPX, UV_FLIPY, UV_ROTATE180
|
||||
from game_object import GameObject
|
||||
from games.wildflowers.scripts.frond import Frond
|
||||
from games.wildflowers.scripts.petal import Petal
|
||||
from games.wildflowers.scripts.ramps import PALETTE_RAMPS
|
||||
from renderable import TileRenderable
|
||||
from playscii.art import ART_DIR, UV_FLIPX, UV_FLIPY, UV_ROTATE180
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.renderable import TileRenderable
|
||||
|
||||
# TODO: random size range?
|
||||
# (should also change camera zoom, probably frond/petal counts)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from game_util_objects import GameObject, WorldGlobalsObject
|
||||
from image_export import export_still_image
|
||||
from playscii.game_util_objects import GameObject, WorldGlobalsObject
|
||||
from playscii.image_export import export_still_image
|
||||
|
||||
"""
|
||||
overall approach:
|
||||
|
|
|
|||
2
justfile
2
justfile
|
|
@ -11,4 +11,4 @@ test:
|
|||
check: lint
|
||||
|
||||
run:
|
||||
uv run python playscii.py
|
||||
uv run python -m playscii
|
||||
|
|
|
|||
1
playscii/__init__.py
Normal file
1
playscii/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# playscii package
|
||||
9
playscii/__main__.py
Normal file
9
playscii/__main__.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import sys
|
||||
|
||||
from .app import get_app
|
||||
|
||||
app = get_app()
|
||||
error = app.main_loop()
|
||||
app.quit()
|
||||
app.logger.close()
|
||||
sys.exit(error)
|
||||
|
|
@ -49,7 +49,7 @@ with contextlib.suppress(Exception):
|
|||
pdoc_available = True
|
||||
|
||||
# submodules - set here so cfg file can modify them all easily
|
||||
from art import (
|
||||
from .art import (
|
||||
ART_DIR,
|
||||
ART_FILE_EXTENSION,
|
||||
ART_SCRIPT_DIR,
|
||||
|
|
@ -61,25 +61,25 @@ from art import (
|
|||
Art,
|
||||
ArtFromDisk,
|
||||
)
|
||||
from art_export import ArtExporter
|
||||
from art_import import ArtImporter
|
||||
from audio import AudioLord
|
||||
from camera import Camera
|
||||
from charset import CHARSET_DIR, CharacterSet, CharacterSetLord
|
||||
from cursor import Cursor
|
||||
from framebuffer import Framebuffer
|
||||
from game_world import TOP_GAME_DIR, GameWorld
|
||||
from grid import ArtGrid
|
||||
from input_handler import InputLord
|
||||
from palette import PALETTE_DIR, Palette, PaletteLord
|
||||
from renderable import OnionTileRenderable, TileRenderable
|
||||
from .art_export import ArtExporter
|
||||
from .art_import import ArtImporter
|
||||
from .audio import AudioLord
|
||||
from .camera import Camera
|
||||
from .charset import CHARSET_DIR, CharacterSet, CharacterSetLord
|
||||
from .cursor import Cursor
|
||||
from .framebuffer import Framebuffer
|
||||
from .game_world import TOP_GAME_DIR, GameWorld
|
||||
from .grid import ArtGrid
|
||||
from .input_handler import InputLord
|
||||
from .palette import PALETTE_DIR, Palette, PaletteLord
|
||||
from .renderable import OnionTileRenderable, TileRenderable
|
||||
|
||||
# some classes are imported only so the cfg file can modify their defaults
|
||||
from renderable_line import DebugLineRenderable
|
||||
from renderable_sprite import SpriteRenderable, UIBGTextureRenderable
|
||||
from shader import ShaderLord
|
||||
from ui import OIS_WIDTH, UI
|
||||
from ui_file_chooser_dialog import THUMBNAIL_CACHE_DIR
|
||||
from .renderable_line import DebugLineRenderable
|
||||
from .renderable_sprite import SpriteRenderable, UIBGTextureRenderable
|
||||
from .shader import ShaderLord
|
||||
from .ui import OIS_WIDTH, UI
|
||||
from .ui_file_chooser_dialog import THUMBNAIL_CACHE_DIR
|
||||
|
||||
APP_NAME = "Playscii"
|
||||
VERSION_FILENAME = "version"
|
||||
|
|
@ -409,6 +409,8 @@ class Application:
|
|||
self.onion_renderables_prev, self.onion_renderables_next = [], []
|
||||
# lists of currently loaded character sets and palettes
|
||||
self.charsets, self.palettes = [], []
|
||||
self._charset_map = {}
|
||||
self._palette_map = {}
|
||||
self.csl = CharacterSetLord(self)
|
||||
self.pl = PaletteLord(self)
|
||||
# set/create an active art
|
||||
|
|
@ -739,12 +741,13 @@ class Application:
|
|||
# already loaded?
|
||||
base_charset_to_load = os.path.basename(charset_to_load)
|
||||
base_charset_to_load = os.path.splitext(base_charset_to_load)[0]
|
||||
for charset in self.charsets:
|
||||
if charset.base_filename == base_charset_to_load:
|
||||
return charset
|
||||
cached = self._charset_map.get(base_charset_to_load)
|
||||
if cached is not None:
|
||||
return cached
|
||||
new_charset = CharacterSet(self, charset_to_load, log)
|
||||
if new_charset.init_success:
|
||||
self.charsets.append(new_charset)
|
||||
self._charset_map[base_charset_to_load] = new_charset
|
||||
return new_charset
|
||||
elif self.ui and self.ui.active_art:
|
||||
# if init failed (eg bad filename) return something safe
|
||||
|
|
@ -753,12 +756,13 @@ class Application:
|
|||
def load_palette(self, palette_to_load, log=False):
|
||||
base_palette_to_load = os.path.basename(palette_to_load)
|
||||
base_palette_to_load = os.path.splitext(base_palette_to_load)[0]
|
||||
for palette in self.palettes:
|
||||
if palette.base_filename == base_palette_to_load:
|
||||
return palette
|
||||
cached = self._palette_map.get(base_palette_to_load)
|
||||
if cached is not None:
|
||||
return cached
|
||||
new_palette = Palette(self, palette_to_load, log)
|
||||
if new_palette.init_success:
|
||||
self.palettes.append(new_palette)
|
||||
self._palette_map[base_palette_to_load] = new_palette
|
||||
return new_palette
|
||||
elif self.ui and self.ui.active_art:
|
||||
# if init failed (eg bad filename) return something safe
|
||||
|
|
@ -1145,7 +1149,8 @@ class Application:
|
|||
return
|
||||
for module_name in AUTOGEN_DOC_MODULES:
|
||||
# pdoc.pdoc takes module name as string, returns HTML doc string
|
||||
html = pdoc.pdoc(module_name)
|
||||
qualified_name = f"playscii.{module_name}"
|
||||
html = pdoc.pdoc(qualified_name)
|
||||
docfile = open(AUTOGEN_DOCS_PATH + module_name + ".html", "w")
|
||||
docfile.write(html)
|
||||
docfile.close()
|
||||
|
|
@ -1317,11 +1322,3 @@ def get_app():
|
|||
autoplay_game,
|
||||
)
|
||||
return app
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = get_app()
|
||||
error = app.main_loop()
|
||||
app.quit()
|
||||
app.logger.close()
|
||||
sys.exit(error)
|
||||
|
|
@ -6,8 +6,8 @@ import traceback
|
|||
|
||||
import numpy as np
|
||||
|
||||
from edit_command import CommandStack, EntireArtCommand
|
||||
from image_export import write_thumbnail
|
||||
from .edit_command import CommandStack, EntireArtCommand
|
||||
from .image_export import write_thumbnail
|
||||
|
||||
# X, Y, Z
|
||||
VERT_LENGTH = 3
|
||||
|
|
@ -141,6 +141,7 @@ class Art:
|
|||
self.instances = []
|
||||
"List of ArtInstances using us as their source"
|
||||
# init frames and layers - ArtFromDisk has its own logic for this
|
||||
self._sorted_layers = None
|
||||
self.init_layers()
|
||||
self.init_frames()
|
||||
# support non-square characters:
|
||||
|
|
@ -177,6 +178,14 @@ class Art:
|
|||
self.layers_visibility = [True]
|
||||
self.layer_names = ["Layer 1"]
|
||||
|
||||
def get_sorted_layers(self):
|
||||
"Return layer indices sorted by Z depth, cached until invalidated."
|
||||
if self._sorted_layers is None:
|
||||
self._sorted_layers = tuple(
|
||||
sorted(range(self.layers), key=lambda i: self.layers_z[i])
|
||||
)
|
||||
return self._sorted_layers
|
||||
|
||||
def init_frames(self):
|
||||
self.frames = 0
|
||||
# current frame being edited
|
||||
|
|
@ -309,6 +318,7 @@ class Art:
|
|||
self.layer_names.append(new_name)
|
||||
# rebuild geo with added verts for new layer
|
||||
self.geo_changed = True
|
||||
self._sorted_layers = None
|
||||
# set new layer as active
|
||||
if self is self.app.ui.active_art:
|
||||
self.app.ui.set_active_layer(self.layers - 1)
|
||||
|
|
@ -346,6 +356,7 @@ class Art:
|
|||
self.layer_names.pop(index)
|
||||
self.layers -= 1
|
||||
self.geo_changed = True
|
||||
self._sorted_layers = None
|
||||
self.mark_all_frames_changed()
|
||||
if self.active_layer > self.layers - 1:
|
||||
self.app.ui.set_active_layer(self.layers - 1)
|
||||
|
|
@ -517,14 +528,17 @@ class Art:
|
|||
x2, y2 = left_x, bottom_y
|
||||
x3, y3 = right_x, bottom_y
|
||||
# Z of all layers is 0, layer Z set in shader
|
||||
verts = [x0, y0, 0]
|
||||
verts += [x1, y1, 0]
|
||||
verts += [x2, y2, 0]
|
||||
verts += [x3, y3, 0]
|
||||
verts = [x0, y0, 0, x1, y1, 0, x2, y2, 0, x3, y3, 0]
|
||||
self.vert_array[layer][tile_y][tile_x] = verts
|
||||
# vertex elements
|
||||
elements = [vert_index, vert_index + 1, vert_index + 2]
|
||||
elements += [vert_index + 1, vert_index + 2, vert_index + 3]
|
||||
elements = [
|
||||
vert_index,
|
||||
vert_index + 1,
|
||||
vert_index + 2,
|
||||
vert_index + 1,
|
||||
vert_index + 2,
|
||||
vert_index + 3,
|
||||
]
|
||||
self.elem_array[elem_index : elem_index + ELEM_STRIDE] = elements
|
||||
elem_index += ELEM_STRIDE
|
||||
# 4 verts in a quad
|
||||
|
|
@ -535,11 +549,7 @@ class Art:
|
|||
shape = (layers, self.height, self.width, UV_STRIDE)
|
||||
array = np.zeros(shape, dtype=np.float32)
|
||||
# default new layer of UVs to "normal" transform
|
||||
uvs = uv_types[UV_NORMAL]
|
||||
for layer in range(layers):
|
||||
for y in range(self.height):
|
||||
for x in range(self.width):
|
||||
array[layer][y][x] = uvs
|
||||
array[:] = uv_types[UV_NORMAL]
|
||||
return array
|
||||
|
||||
def is_tile_inside(self, x, y):
|
||||
|
|
@ -1320,6 +1330,7 @@ class ArtInstance(Art):
|
|||
self.renderables = []
|
||||
# instances shouldn't have instances; cause user problems if attempted
|
||||
self.instances = None
|
||||
self._sorted_layers = None
|
||||
self.restore_from_source()
|
||||
self.source.instances.append(self)
|
||||
|
||||
|
|
@ -1343,6 +1354,7 @@ class ArtInstance(Art):
|
|||
setattr(self, prop, getattr(self.source, prop))
|
||||
# copy lists
|
||||
self.layers_z = self.source.layers_z[:]
|
||||
self._sorted_layers = None
|
||||
self.layers_visibility = self.source.layers_visibility[:]
|
||||
self.layer_names = self.source.layer_names[:]
|
||||
self.frame_delays = self.source.frame_delays[:]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import traceback
|
||||
|
||||
from art import ART_DIR
|
||||
from .art import ART_DIR
|
||||
|
||||
|
||||
class ArtExporter:
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import os
|
||||
import traceback
|
||||
|
||||
from art import ART_FILE_EXTENSION, DEFAULT_CHARSET, DEFAULT_PALETTE
|
||||
from ui_file_chooser_dialog import GenericImportChooserDialog
|
||||
from .art import ART_FILE_EXTENSION, DEFAULT_CHARSET, DEFAULT_PALETTE
|
||||
from .ui_file_chooser_dialog import GenericImportChooserDialog
|
||||
|
||||
|
||||
class ArtImporter:
|
||||
|
|
@ -2,7 +2,7 @@ import math
|
|||
|
||||
import numpy as np
|
||||
|
||||
import vector
|
||||
from . import vector
|
||||
|
||||
|
||||
def clamp(val, lowest, highest):
|
||||
|
|
@ -4,7 +4,7 @@ import time
|
|||
|
||||
from PIL import Image
|
||||
|
||||
from texture import Texture
|
||||
from .texture import Texture
|
||||
|
||||
CHARSET_DIR = "charsets/"
|
||||
CHARSET_FILE_EXTENSION = "char"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import math
|
||||
from collections import namedtuple
|
||||
|
||||
from renderable_line import (
|
||||
from .renderable_line import (
|
||||
BoxCollisionRenderable,
|
||||
CircleCollisionRenderable,
|
||||
TileBoxCollisionRenderable,
|
||||
|
|
@ -4,9 +4,9 @@ import math
|
|||
import numpy as np
|
||||
from OpenGL import GL
|
||||
|
||||
import vector
|
||||
from edit_command import EditCommand
|
||||
from renderable_sprite import UISpriteRenderable
|
||||
from . import vector
|
||||
from .edit_command import EditCommand
|
||||
from .renderable_sprite import UISpriteRenderable
|
||||
|
||||
"""
|
||||
reference diagram:
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from art import Art
|
||||
from renderable import TileRenderable
|
||||
from .art import Art
|
||||
from .renderable import TileRenderable
|
||||
|
||||
|
||||
class GameHUDArt(Art):
|
||||
|
|
@ -2,9 +2,9 @@ import math
|
|||
import os
|
||||
import random
|
||||
|
||||
import vector
|
||||
from art import ArtInstance
|
||||
from collision import (
|
||||
from . import vector
|
||||
from .art import ArtInstance
|
||||
from .collision import (
|
||||
CST_AABB,
|
||||
CST_CIRCLE,
|
||||
CST_NONE,
|
||||
|
|
@ -15,8 +15,8 @@ from collision import (
|
|||
Contact,
|
||||
point_in_box,
|
||||
)
|
||||
from renderable import GameObjectRenderable
|
||||
from renderable_line import BoundsIndicatorRenderable, OriginIndicatorRenderable
|
||||
from .renderable import GameObjectRenderable
|
||||
from .renderable_line import BoundsIndicatorRenderable, OriginIndicatorRenderable
|
||||
|
||||
# facings
|
||||
GOF_LEFT = 0
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from game_object import GameObject
|
||||
from .game_object import GameObject
|
||||
|
||||
|
||||
class GameRoom:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import os.path
|
||||
import random
|
||||
|
||||
from collision import (
|
||||
from .collision import (
|
||||
CST_AABB,
|
||||
CST_CIRCLE,
|
||||
CST_TILE,
|
||||
|
|
@ -10,7 +10,7 @@ from collision import (
|
|||
CT_NONE,
|
||||
CT_PLAYER,
|
||||
)
|
||||
from game_object import FACING_DIRS, GameObject
|
||||
from .game_object import FACING_DIRS, GameObject
|
||||
|
||||
|
||||
class GameObjectAttachment(GameObject):
|
||||
|
|
@ -9,17 +9,12 @@ from collections import namedtuple
|
|||
|
||||
import sdl2
|
||||
|
||||
import collision
|
||||
import game_hud
|
||||
import game_object
|
||||
import game_room
|
||||
import game_util_objects
|
||||
import vector
|
||||
from art import ART_DIR
|
||||
from camera import Camera
|
||||
from charset import CHARSET_DIR
|
||||
from grid import GameGrid
|
||||
from palette import PALETTE_DIR
|
||||
from . import collision, game_hud, game_object, game_room, game_util_objects, vector
|
||||
from .art import ART_DIR
|
||||
from .camera import Camera
|
||||
from .charset import CHARSET_DIR
|
||||
from .grid import GameGrid
|
||||
from .palette import PALETTE_DIR
|
||||
|
||||
TOP_GAME_DIR = "games/"
|
||||
DEFAULT_STATE_FILENAME = "start"
|
||||
|
|
@ -29,8 +24,8 @@ SOUNDS_DIR = "sounds/"
|
|||
|
||||
# generic starter script with a GO and Player subclass
|
||||
STARTER_SCRIPT = """
|
||||
from game_object import GameObject
|
||||
from game_util_objects import Player
|
||||
from playscii.game_object import GameObject
|
||||
from playscii.game_util_objects import Player
|
||||
|
||||
|
||||
class MyGamePlayer(Player):
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import numpy as np
|
||||
|
||||
from renderable_line import LineRenderable
|
||||
from .renderable_line import LineRenderable
|
||||
|
||||
# grid that displays as guide for Cursor
|
||||
|
||||
|
|
@ -5,8 +5,8 @@ import time
|
|||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
from lab_color import lab_color_diff, rgb_to_lab
|
||||
from renderable_sprite import SpriteRenderable
|
||||
from .lab_color import lab_color_diff, rgb_to_lab
|
||||
from .renderable_sprite import SpriteRenderable
|
||||
|
||||
"""
|
||||
notes / future research
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from OpenGL import GL
|
||||
from PIL import GifImagePlugin, Image, ImageChops
|
||||
|
||||
from framebuffer import ExportFramebuffer, ExportFramebufferNoCRT
|
||||
from .framebuffer import ExportFramebuffer, ExportFramebufferNoCRT
|
||||
|
||||
|
||||
def get_frame_image(app, art, frame, allow_crt=True, scale=1, bg_color=(0, 0, 0, 0)):
|
||||
|
|
@ -5,12 +5,12 @@ from sys import exit
|
|||
|
||||
import sdl2
|
||||
|
||||
from art import ART_DIR, ART_FILE_EXTENSION
|
||||
from collision import CT_NONE
|
||||
from key_shifts import NUMLOCK_OFF_MAP, NUMLOCK_ON_MAP
|
||||
from renderable import LAYER_VIS_DIM, LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from ui import OIS_FILL, OIS_HEIGHT, OIS_WIDTH, SCALE_INCREMENT
|
||||
from ui_art_dialog import (
|
||||
from .art import ART_DIR, ART_FILE_EXTENSION
|
||||
from .collision import CT_NONE
|
||||
from .key_shifts import NUMLOCK_OFF_MAP, NUMLOCK_ON_MAP
|
||||
from .renderable import LAYER_VIS_DIM, LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from .ui import OIS_FILL, OIS_HEIGHT, OIS_WIDTH, SCALE_INCREMENT
|
||||
from .ui_art_dialog import (
|
||||
AddFrameDialog,
|
||||
AddLayerDialog,
|
||||
CloseUnsavedChangesDialog,
|
||||
|
|
@ -32,7 +32,7 @@ from ui_art_dialog import (
|
|||
SetLayerNameDialog,
|
||||
SetLayerZDialog,
|
||||
)
|
||||
from ui_file_chooser_dialog import (
|
||||
from .ui_file_chooser_dialog import (
|
||||
ArtChooserDialog,
|
||||
CharSetChooserDialog,
|
||||
OverlayImageFileChooserDialog,
|
||||
|
|
@ -40,7 +40,7 @@ from ui_file_chooser_dialog import (
|
|||
PaletteFromImageChooserDialog,
|
||||
RunArtScriptDialog,
|
||||
)
|
||||
from ui_game_dialog import (
|
||||
from .ui_game_dialog import (
|
||||
AddRoomDialog,
|
||||
NewGameDirDialog,
|
||||
RenameRoomDialog,
|
||||
|
|
@ -49,7 +49,7 @@ from ui_game_dialog import (
|
|||
SetRoomCamDialog,
|
||||
SetRoomEdgeWarpsDialog,
|
||||
)
|
||||
from ui_list_operations import (
|
||||
from .ui_list_operations import (
|
||||
LO_LOAD_STATE,
|
||||
LO_OPEN_GAME_DIR,
|
||||
LO_SELECT_OBJECTS,
|
||||
|
|
@ -5,8 +5,8 @@ from random import randint
|
|||
|
||||
from PIL import Image
|
||||
|
||||
from lab_color import lab_color_diff, rgb_to_lab
|
||||
from texture import Texture
|
||||
from .lab_color import lab_color_diff, rgb_to_lab
|
||||
from .texture import Texture
|
||||
|
||||
PALETTE_DIR = "palettes/"
|
||||
PALETTE_EXTENSIONS = ["png", "gif", "bmp"]
|
||||
|
|
@ -72,6 +72,7 @@ class Palette:
|
|||
# scan image L->R T->B for unique colors, store em as tuples
|
||||
# color 0 is always fully transparent
|
||||
self.colors = [(0, 0, 0, 0)]
|
||||
seen = {(0, 0, 0, 0)}
|
||||
# determine lightest and darkest colors in palette for defaults
|
||||
lightest = 0
|
||||
darkest = 255 * 3 + 1
|
||||
|
|
@ -82,7 +83,8 @@ class Palette:
|
|||
if len(self.colors) >= MAX_COLORS:
|
||||
break
|
||||
color = src_img.getpixel((x, y))
|
||||
if color not in self.colors:
|
||||
if color not in seen:
|
||||
seen.add(color)
|
||||
self.colors.append(color)
|
||||
# is this lightest/darkest unique color so far? save index
|
||||
luminosity = color[0] * 0.21 + color[1] * 0.72 + color[2] * 0.07
|
||||
|
|
@ -4,8 +4,8 @@ import math
|
|||
import numpy as np
|
||||
from OpenGL import GL
|
||||
|
||||
from art import VERT_LENGTH
|
||||
from palette import MAX_COLORS
|
||||
from .art import VERT_LENGTH
|
||||
from .palette import MAX_COLORS
|
||||
|
||||
# inactive layer alphas
|
||||
LAYER_VIS_FULL = 1
|
||||
|
|
@ -92,6 +92,11 @@ class TileRenderable:
|
|||
self.alpha_uniform = self.shader.get_uniform_location("alpha")
|
||||
self.brightness_uniform = self.shader.get_uniform_location("brightness")
|
||||
self.bg_alpha_uniform = self.shader.get_uniform_location("bgColorAlpha")
|
||||
self.attrib_vert_position = self.shader.get_attrib_location("vertPosition")
|
||||
self.attrib_char_index = self.shader.get_attrib_location("charIndex")
|
||||
self.attrib_uv_mod = self.shader.get_attrib_location("uvMod")
|
||||
self.attrib_fg_color_index = self.shader.get_attrib_location("fgColorIndex")
|
||||
self.attrib_bg_color_index = self.shader.get_attrib_location("bgColorIndex")
|
||||
self.create_buffers()
|
||||
# finish
|
||||
if self.app.use_vao:
|
||||
|
|
@ -485,48 +490,45 @@ class TileRenderable:
|
|||
if self.app.use_vao:
|
||||
GL.glBindVertexArray(self.vao)
|
||||
else:
|
||||
attrib = self.shader.get_attrib_location # for brevity
|
||||
vp = ctypes.c_void_p(0)
|
||||
# bind each buffer and set its attrib:
|
||||
# verts
|
||||
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vert_buffer)
|
||||
GL.glVertexAttribPointer(
|
||||
attrib("vertPosition"), VERT_LENGTH, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
self.attrib_vert_position, VERT_LENGTH, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
)
|
||||
GL.glEnableVertexAttribArray(attrib("vertPosition"))
|
||||
GL.glEnableVertexAttribArray(self.attrib_vert_position)
|
||||
# chars
|
||||
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.char_buffer)
|
||||
GL.glVertexAttribPointer(
|
||||
attrib("charIndex"), 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
self.attrib_char_index, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
)
|
||||
GL.glEnableVertexAttribArray(attrib("charIndex"))
|
||||
GL.glEnableVertexAttribArray(self.attrib_char_index)
|
||||
# uvs
|
||||
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.uv_buffer)
|
||||
GL.glVertexAttribPointer(
|
||||
attrib("uvMod"), 2, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
self.attrib_uv_mod, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
)
|
||||
GL.glEnableVertexAttribArray(attrib("uvMod"))
|
||||
GL.glEnableVertexAttribArray(self.attrib_uv_mod)
|
||||
# fg colors
|
||||
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.fg_buffer)
|
||||
GL.glVertexAttribPointer(
|
||||
attrib("fgColorIndex"), 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
self.attrib_fg_color_index, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
)
|
||||
GL.glEnableVertexAttribArray(attrib("fgColorIndex"))
|
||||
GL.glEnableVertexAttribArray(self.attrib_fg_color_index)
|
||||
# bg colors
|
||||
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.bg_buffer)
|
||||
GL.glVertexAttribPointer(
|
||||
attrib("bgColorIndex"), 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
self.attrib_bg_color_index, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, vp
|
||||
)
|
||||
GL.glEnableVertexAttribArray(attrib("bgColorIndex"))
|
||||
GL.glEnableVertexAttribArray(self.attrib_bg_color_index)
|
||||
# finally, bind element buffer
|
||||
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.elem_buffer)
|
||||
GL.glEnable(GL.GL_BLEND)
|
||||
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
|
||||
# draw all specified layers if no list given
|
||||
if layers is None:
|
||||
# sort layers in Z depth
|
||||
layers = list(range(self.art.layers))
|
||||
layers.sort(key=lambda i: self.art.layers_z[i], reverse=False)
|
||||
layers = self.art.get_sorted_layers()
|
||||
# handle a single int param
|
||||
elif type(layers) is int:
|
||||
layers = [layers]
|
||||
|
|
@ -6,7 +6,7 @@ import time
|
|||
import numpy as np
|
||||
from OpenGL import GL
|
||||
|
||||
from renderable import TileRenderable
|
||||
from .renderable import TileRenderable
|
||||
|
||||
|
||||
class LineRenderable:
|
||||
|
|
@ -5,7 +5,7 @@ import numpy as np
|
|||
from OpenGL import GL
|
||||
from PIL import Image
|
||||
|
||||
from texture import Texture
|
||||
from .texture import Texture
|
||||
|
||||
|
||||
class SpriteRenderable:
|
||||
|
|
@ -2,7 +2,7 @@ import math
|
|||
|
||||
import numpy as np
|
||||
|
||||
from renderable_line import LineRenderable
|
||||
from .renderable_line import LineRenderable
|
||||
|
||||
|
||||
class SelectionRenderable(LineRenderable):
|
||||
|
|
@ -3,17 +3,17 @@ import sdl2
|
|||
from OpenGL import GL
|
||||
from PIL import Image
|
||||
|
||||
from art import (
|
||||
from .art import (
|
||||
UV_FLIP270,
|
||||
UV_NORMAL,
|
||||
uv_names,
|
||||
)
|
||||
from edit_command import EditCommand, EditCommandTile, EntireArtCommand
|
||||
from texture import Texture
|
||||
from ui_colors import UIColors
|
||||
from ui_console import ConsoleUI
|
||||
from ui_edit_panel import EditListPanel
|
||||
from ui_element import (
|
||||
from .edit_command import EditCommand, EditCommandTile, EntireArtCommand
|
||||
from .texture import Texture
|
||||
from .ui_colors import UIColors
|
||||
from .ui_console import ConsoleUI
|
||||
from .ui_edit_panel import EditListPanel
|
||||
from .ui_element import (
|
||||
DebugTextUI,
|
||||
FPSCounterUI,
|
||||
GameHoverLabel,
|
||||
|
|
@ -22,12 +22,12 @@ from ui_element import (
|
|||
ToolTip,
|
||||
UIArt,
|
||||
)
|
||||
from ui_menu_bar import ArtMenuBar, GameMenuBar
|
||||
from ui_menu_pulldown import PulldownMenu
|
||||
from ui_object_panel import EditObjectPanel
|
||||
from ui_popup import ToolPopup
|
||||
from ui_status_bar import StatusBarUI
|
||||
from ui_tool import (
|
||||
from .ui_menu_bar import ArtMenuBar, GameMenuBar
|
||||
from .ui_menu_pulldown import PulldownMenu
|
||||
from .ui_object_panel import EditObjectPanel
|
||||
from .ui_popup import ToolPopup
|
||||
from .ui_status_bar import StatusBarUI
|
||||
from .ui_tool import (
|
||||
EraseTool,
|
||||
FillTool,
|
||||
GrabTool,
|
||||
|
|
@ -37,7 +37,7 @@ from ui_tool import (
|
|||
SelectTool,
|
||||
TextTool,
|
||||
)
|
||||
from ui_toolbar import ArtToolBar
|
||||
from .ui_toolbar import ArtToolBar
|
||||
|
||||
UI_ASSET_DIR = "ui/"
|
||||
SCALE_INCREMENT = 0.25
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import os.path
|
||||
|
||||
from art import (
|
||||
from .art import (
|
||||
ART_DIR,
|
||||
ART_FILE_EXTENSION,
|
||||
DEFAULT_FRAME_DELAY,
|
||||
|
|
@ -8,10 +8,10 @@ from art import (
|
|||
DEFAULT_LAYER_Z_OFFSET,
|
||||
DEFAULT_WIDTH,
|
||||
)
|
||||
from palette import PaletteFromFile
|
||||
from ui_chooser_dialog import ChooserDialog, ChooserItem, ChooserItemButton
|
||||
from ui_console import SaveCommand
|
||||
from ui_dialog import Field, UIDialog
|
||||
from .palette import PaletteFromFile
|
||||
from .ui_chooser_dialog import ChooserDialog, ChooserItem, ChooserItemButton
|
||||
from .ui_console import SaveCommand
|
||||
from .ui_dialog import Field, UIDialog
|
||||
|
||||
|
||||
class BaseFileDialog(UIDialog):
|
||||
|
|
@ -693,6 +693,7 @@ class SetLayerZDialog(UIDialog):
|
|||
return
|
||||
new_z = float(self.field_texts[0])
|
||||
self.ui.active_art.layers_z[self.ui.active_art.active_layer] = new_z
|
||||
self.ui.active_art._sorted_layers = None
|
||||
self.ui.active_art.set_unsaved_changes(True)
|
||||
self.ui.app.grid.reset()
|
||||
self.dismiss()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from ui_colors import UIColors
|
||||
from .ui_colors import UIColors
|
||||
|
||||
TEXT_LEFT = 0
|
||||
TEXT_CENTER = 1
|
||||
|
|
@ -2,11 +2,11 @@ import os
|
|||
|
||||
import sdl2
|
||||
|
||||
from art import UV_FLIPY, UV_NORMAL
|
||||
from renderable_sprite import UISpriteRenderable
|
||||
from ui_button import UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_dialog import Field, UIDialog
|
||||
from .art import UV_FLIPY, UV_NORMAL
|
||||
from .renderable_sprite import UISpriteRenderable
|
||||
from .ui_button import UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_dialog import Field, UIDialog
|
||||
|
||||
|
||||
class ChooserItemButton(UIButton):
|
||||
|
|
@ -4,12 +4,12 @@ from math import ceil
|
|||
import sdl2
|
||||
|
||||
# imports for console execution namespace - be careful!
|
||||
from art import UV_FLIPY
|
||||
from image_convert import ImageConverter
|
||||
from image_export import export_animation, export_still_image
|
||||
from key_shifts import SHIFT_MAP
|
||||
from palette import PaletteFromFile
|
||||
from ui_element import UIElement
|
||||
from .art import UV_FLIPY
|
||||
from .image_convert import ImageConverter
|
||||
from .image_export import export_animation, export_still_image
|
||||
from .key_shifts import SHIFT_MAP
|
||||
from .palette import PaletteFromFile
|
||||
from .ui_element import UIElement
|
||||
|
||||
CONSOLE_HISTORY_FILENAME = "console_history"
|
||||
|
||||
|
|
@ -3,10 +3,10 @@ from collections import namedtuple
|
|||
|
||||
import sdl2
|
||||
|
||||
from key_shifts import SHIFT_MAP
|
||||
from ui_button import TEXT_CENTER, UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIElement
|
||||
from .key_shifts import SHIFT_MAP
|
||||
from .ui_button import TEXT_CENTER, UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIElement
|
||||
|
||||
Field = namedtuple(
|
||||
"Field",
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import os
|
||||
|
||||
from game_world import STATE_FILE_EXTENSION, TOP_GAME_DIR
|
||||
from ui_button import UIButton
|
||||
from ui_chooser_dialog import ScrollArrowButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIElement
|
||||
from ui_list_operations import (
|
||||
from .game_world import STATE_FILE_EXTENSION, TOP_GAME_DIR
|
||||
from .ui_button import UIButton
|
||||
from .ui_chooser_dialog import ScrollArrowButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIElement
|
||||
from .ui_list_operations import (
|
||||
LO_LOAD_STATE,
|
||||
LO_NONE,
|
||||
LO_OPEN_GAME_DIR,
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import time
|
||||
from math import ceil
|
||||
|
||||
import vector
|
||||
from art import Art
|
||||
from renderable import TileRenderable
|
||||
from . import vector
|
||||
from .art import Art
|
||||
from .renderable import TileRenderable
|
||||
|
||||
|
||||
class UIElement:
|
||||
|
|
@ -4,20 +4,20 @@ import time
|
|||
|
||||
from PIL import Image
|
||||
|
||||
from art import (
|
||||
from .art import (
|
||||
ART_DIR,
|
||||
ART_FILE_EXTENSION,
|
||||
ART_SCRIPT_DIR,
|
||||
SCRIPT_FILE_EXTENSION,
|
||||
THUMBNAIL_CACHE_DIR,
|
||||
)
|
||||
from charset import CHARSET_DIR, CHARSET_FILE_EXTENSION
|
||||
from image_export import write_thumbnail
|
||||
from palette import PALETTE_DIR, PALETTE_EXTENSIONS
|
||||
from texture import Texture
|
||||
from ui_art_dialog import ImportOptionsDialog, PaletteFromFileDialog
|
||||
from ui_chooser_dialog import ChooserDialog, ChooserItem
|
||||
from ui_console import OpenCommand
|
||||
from .charset import CHARSET_DIR, CHARSET_FILE_EXTENSION
|
||||
from .image_export import write_thumbnail
|
||||
from .palette import PALETTE_DIR, PALETTE_EXTENSIONS
|
||||
from .texture import Texture
|
||||
from .ui_art_dialog import ImportOptionsDialog, PaletteFromFileDialog
|
||||
from .ui_chooser_dialog import ChooserDialog, ChooserItem
|
||||
from .ui_console import OpenCommand
|
||||
|
||||
|
||||
class BaseFileChooserItem(ChooserItem):
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from ui_console import LoadGameStateCommand, SaveGameStateCommand
|
||||
from ui_dialog import Field, UIDialog
|
||||
from ui_list_operations import (
|
||||
from .ui_console import LoadGameStateCommand, SaveGameStateCommand
|
||||
from .ui_dialog import Field, UIDialog
|
||||
from .ui_list_operations import (
|
||||
LO_NONE,
|
||||
)
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from ui_menu_pulldown_item import (
|
||||
from .ui_menu_pulldown_item import (
|
||||
FileQuitItem,
|
||||
PulldownMenuData,
|
||||
PulldownMenuItem,
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import sdl2
|
||||
|
||||
from ui_dialog import UIDialog
|
||||
from ui_element import UIElement
|
||||
from .ui_dialog import UIDialog
|
||||
from .ui_element import UIElement
|
||||
|
||||
|
||||
class PagedInfoDialog(UIDialog):
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
from math import ceil
|
||||
|
||||
from renderable_sprite import UISpriteRenderable
|
||||
from ui_button import TEXT_CENTER, UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIElement
|
||||
from ui_game_menu_pulldown_item import (
|
||||
from .renderable_sprite import UISpriteRenderable
|
||||
from .ui_button import TEXT_CENTER, UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIElement
|
||||
from .ui_game_menu_pulldown_item import (
|
||||
GameMenuData,
|
||||
GameObjectMenuData,
|
||||
GameRoomMenuData,
|
||||
|
|
@ -12,8 +12,8 @@ from ui_game_menu_pulldown_item import (
|
|||
GameViewMenuData,
|
||||
GameWorldMenuData,
|
||||
)
|
||||
from ui_info_dialog import AboutDialog
|
||||
from ui_menu_pulldown_item import (
|
||||
from .ui_info_dialog import AboutDialog
|
||||
from .ui_menu_pulldown_item import (
|
||||
ArtMenuData,
|
||||
CharColorMenuData,
|
||||
EditMenuData,
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
from art import UV_FLIPX, UV_FLIPY, UV_ROTATE180
|
||||
from ui_button import UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIElement
|
||||
from ui_menu_pulldown_item import PulldownMenuData, PulldownMenuItem, SeparatorItem
|
||||
from .art import UV_FLIPX, UV_FLIPY, UV_ROTATE180
|
||||
from .ui_button import UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIElement
|
||||
from .ui_menu_pulldown_item import PulldownMenuData, PulldownMenuItem, SeparatorItem
|
||||
|
||||
|
||||
class MenuItemButton(UIButton):
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from renderable import LAYER_VIS_DIM, LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from ui_tool import (
|
||||
from .renderable import LAYER_VIS_DIM, LAYER_VIS_FULL, LAYER_VIS_NONE
|
||||
from .ui_tool import (
|
||||
EraseTool,
|
||||
FillTool,
|
||||
GrabTool,
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import os
|
||||
|
||||
from ui_button import TEXT_RIGHT, UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_dialog import Field, UIDialog
|
||||
from ui_edit_panel import GamePanel
|
||||
from .ui_button import TEXT_RIGHT, UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_dialog import Field, UIDialog
|
||||
from .ui_edit_panel import GamePanel
|
||||
|
||||
|
||||
class ResetObjectButton(UIButton):
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
from art import UV_FLIPX, UV_FLIPY, UV_NORMAL, UV_ROTATE90, UV_ROTATE180, UV_ROTATE270
|
||||
from renderable_line import SwatchSelectionBoxRenderable
|
||||
from ui_button import TEXT_CENTER, UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIArt, UIElement
|
||||
from ui_file_chooser_dialog import CharSetChooserDialog, PaletteChooserDialog
|
||||
from ui_swatch import MIN_CHARSET_WIDTH, CharacterSetSwatch, PaletteSwatch
|
||||
from ui_tool import FILL_BOUND_BG_COLOR, FILL_BOUND_CHAR, FILL_BOUND_FG_COLOR, FillTool
|
||||
from .art import UV_FLIPX, UV_FLIPY, UV_NORMAL, UV_ROTATE90, UV_ROTATE180, UV_ROTATE270
|
||||
from .renderable_line import SwatchSelectionBoxRenderable
|
||||
from .ui_button import TEXT_CENTER, UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIArt, UIElement
|
||||
from .ui_file_chooser_dialog import CharSetChooserDialog, PaletteChooserDialog
|
||||
from .ui_swatch import MIN_CHARSET_WIDTH, CharacterSetSwatch, PaletteSwatch
|
||||
from .ui_tool import FILL_BOUND_BG_COLOR, FILL_BOUND_CHAR, FILL_BOUND_FG_COLOR, FillTool
|
||||
|
||||
TOOL_PANE_WIDTH = 10
|
||||
|
||||
|
|
@ -2,11 +2,11 @@ import os.path
|
|||
import time
|
||||
from math import ceil
|
||||
|
||||
from art import uv_names
|
||||
from renderable_line import UIRenderableX
|
||||
from ui_button import TEXT_CENTER, TEXT_RIGHT, UIButton
|
||||
from ui_colors import UIColors
|
||||
from ui_element import UIArt, UIElement, UIRenderable
|
||||
from .art import uv_names
|
||||
from .renderable_line import UIRenderableX
|
||||
from .ui_button import TEXT_CENTER, TEXT_RIGHT, UIButton
|
||||
from .ui_colors import UIColors
|
||||
from .ui_element import UIArt, UIElement, UIRenderable
|
||||
|
||||
# buttons to toggle "affects" status / cycle through choices, respectively
|
||||
|
||||
|
|
@ -3,8 +3,8 @@ import time
|
|||
|
||||
import numpy as np
|
||||
|
||||
from renderable_line import LineRenderable, SwatchSelectionBoxRenderable, UIRenderableX
|
||||
from ui_element import UIArt, UIElement, UIRenderable
|
||||
from .renderable_line import LineRenderable, SwatchSelectionBoxRenderable, UIRenderableX
|
||||
from .ui_element import UIArt, UIElement, UIRenderable
|
||||
|
||||
# min width for charset; if charset is tiny adjust to this
|
||||
MIN_CHARSET_WIDTH = 16
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import sdl2
|
||||
from PIL import Image
|
||||
|
||||
from art import (
|
||||
from .art import (
|
||||
UV_FLIP90,
|
||||
UV_FLIP270,
|
||||
UV_FLIPX,
|
||||
|
|
@ -11,10 +11,10 @@ from art import (
|
|||
UV_ROTATE180,
|
||||
UV_ROTATE270,
|
||||
)
|
||||
from edit_command import EditCommandTile
|
||||
from key_shifts import SHIFT_MAP
|
||||
from selection import SelectionRenderable
|
||||
from texture import Texture
|
||||
from .edit_command import EditCommandTile
|
||||
from .key_shifts import SHIFT_MAP
|
||||
from .selection import SelectionRenderable
|
||||
from .texture import Texture
|
||||
|
||||
|
||||
class UITool:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from renderable_line import ToolSelectionBoxRenderable
|
||||
from renderable_sprite import UISpriteRenderable
|
||||
from ui_button import UIButton
|
||||
from ui_element import UIElement
|
||||
from .renderable_line import ToolSelectionBoxRenderable
|
||||
from .renderable_sprite import UISpriteRenderable
|
||||
from .ui_button import UIButton
|
||||
from .ui_element import UIElement
|
||||
|
||||
|
||||
class ToolBar(UIElement):
|
||||
|
|
@ -23,7 +23,7 @@ requires = ["hatchling"]
|
|||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.ruff]
|
||||
src = ["."]
|
||||
src = ["playscii"]
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.lint]
|
||||
|
|
|
|||
Loading…
Reference in a new issue