Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ def process_card_data(data: dict, card: CardDetails) -> dict:
data['layout'] = 'planeswalker'
return data

# Check for Station layout
if 'STATION ' in data.get('oracle_text', ''):
data['layout'] = 'station'

# Return updated data
return data

Expand Down
5 changes: 5 additions & 0 deletions src/enums/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class LAYERS (StrConstant):
FULL = 'Full'
NORMAL = 'Normal'
SNOW = 'Snow'
LEVEL = 'Level'

# Borders
BORDER = 'Border'
Expand Down Expand Up @@ -249,3 +250,7 @@ class LAYERS (StrConstant):
# Battles
DEFENSE = 'Defense'
DEFENSE_REFERENCE = 'Defense Reference'

# Station
STATION = 'Station'
REQUIREMENT = 'Requirement'
6 changes: 5 additions & 1 deletion src/enums/mtg.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class LayoutCategory(StrConstant):
Prototype = 'Prototype'
Saga = 'Saga'
Split = 'Split'
Station = 'Station'
Token = 'Token'
Transform = 'Transform'

Expand All @@ -52,6 +53,7 @@ class LayoutType(StrConstant):
Prototype = 'prototype'
Saga = 'saga'
Split = 'split'
Station = 'station'
TransformBack = 'transform_back'
TransformFront = 'transform_front'

Expand Down Expand Up @@ -86,6 +88,7 @@ class LayoutScryfall(StrConstant):
Planeswalker = 'planeswalker'
PlaneswalkerMDFC = 'planeswalker_mdfc'
PlaneswalkerTransform = 'planeswalker_tf'
Station = 'station'


"""Maps Layout categories to a list of equivalent Layout types."""
Expand All @@ -104,7 +107,8 @@ class LayoutScryfall(StrConstant):
LayoutCategory.Leveler: [LayoutType.Leveler],
LayoutCategory.Split: [LayoutType.Split],
LayoutCategory.Battle: [LayoutType.Battle],
LayoutCategory.Planar: [LayoutType.Planar]
LayoutCategory.Planar: [LayoutType.Planar],
LayoutCategory.Station: [LayoutType.Station],
}

"""Maps Layout types to their equivalent Layout category."""
Expand Down
31 changes: 24 additions & 7 deletions src/helpers/bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from src import APP
from src.helpers.descriptors import get_layer_action_ref
from src.helpers.document import undo_action
from src.helpers.layers import duplicate_group, select_layer
from src.utils.adobe import PS_EXCEPTIONS

# QOL Definitions
Expand All @@ -24,8 +25,8 @@
* Types
"""

# Layer bounds: left, top, right, bottom
LayerBounds = tuple[int, int, int, int]
"""left, top, right, bottom"""


class LayerDimensions(TypedDict):
Expand All @@ -51,7 +52,7 @@ class TextboxDimensions(TypedDict):
"""


def get_dimensions_from_bounds(bounds: LayerBounds) -> type[LayerDimensions]:
def get_dimensions_from_bounds(bounds: LayerBounds) -> LayerDimensions:
"""Compute width and height based on a set of bounds given.

Args:
Expand All @@ -71,7 +72,7 @@ def get_dimensions_from_bounds(bounds: LayerBounds) -> type[LayerDimensions]:
top=int(bounds[1]), bottom=int(bounds[3]))


def get_layer_dimensions(layer: Union[ArtLayer, LayerSet]) -> type[LayerDimensions]:
def get_layer_dimensions(layer: Union[ArtLayer, LayerSet]) -> LayerDimensions:
"""Compute the width and height dimensions of a layer.

Args:
Expand All @@ -83,6 +84,22 @@ def get_layer_dimensions(layer: Union[ArtLayer, LayerSet]) -> type[LayerDimensio
return get_dimensions_from_bounds(layer.bounds)


def get_group_dimensions(group: LayerSet) -> LayerDimensions:
"""
Compute the dimensions of a group.

Uses a workaround to avoid erroneous dimensions, which might occur
when the group contains shapes.
"""
select_layer(group)
group_copy = duplicate_group(group.name)
group_copy.visible = True
merged = group_copy.merge()
dims = get_layer_dimensions(merged)
merged.remove()
return dims


def get_layer_width(layer: Union[ArtLayer, LayerSet]) -> Union[float, int]:
"""Returns the width of a given layer.

Expand Down Expand Up @@ -140,7 +157,7 @@ def get_bounds_no_effects(layer: Union[ArtLayer, LayerSet]) -> LayerBounds:
return layer.bounds


def get_dimensions_no_effects(layer: Union[ArtLayer, LayerSet]) -> type[LayerDimensions]:
def get_dimensions_no_effects(layer: Union[ArtLayer, LayerSet]) -> LayerDimensions:
"""Compute the dimensions of a layer without its effects applied.

Args:
Expand All @@ -153,7 +170,7 @@ def get_dimensions_no_effects(layer: Union[ArtLayer, LayerSet]) -> type[LayerDim
return get_dimensions_from_bounds(bounds)


def get_width_no_effects(layer: Union[ArtLayer, LayerSet]) -> int:
def get_width_no_effects(layer: Union[ArtLayer, LayerSet]) -> float | int:
"""Returns the width of a given layer without its effects applied.

Args:
Expand All @@ -170,7 +187,7 @@ def get_width_no_effects(layer: Union[ArtLayer, LayerSet]) -> int:
return get_layer_width(layer)


def get_height_no_effects(layer: Union[ArtLayer, LayerSet]) -> int:
def get_height_no_effects(layer: Union[ArtLayer, LayerSet]) -> float | int:
"""Returns the height of a given layer without its effects applied.

Args:
Expand Down Expand Up @@ -230,7 +247,7 @@ def get_textbox_bounds(layer: ArtLayer) -> LayerBounds:
)


def get_textbox_dimensions(layer: ArtLayer) -> type[TextboxDimensions]:
def get_textbox_dimensions(layer: ArtLayer) -> TextboxDimensions:
"""Get the dimensions of a TextLayer's bounding box.

Args:
Expand Down
62 changes: 61 additions & 1 deletion src/layouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"""
# Standard Library Imports
from datetime import date, datetime
from typing import Optional, Match, Union, Type, ForwardRef
import re
from typing import NotRequired, Optional, Match, TypedDict, Union, Type, ForwardRef
from os import path as osp
from pathlib import Path
from functools import cached_property
Expand Down Expand Up @@ -35,6 +36,12 @@
check_hybrid_mana_cost,
get_mana_cost_colors)


class PowerToughness(TypedDict):
power: str
toughness: str


"""
* Layout Processing
"""
Expand Down Expand Up @@ -1524,6 +1531,58 @@ def card_count(self) -> Optional[int]:
return self.set_data.get('count_tokens', None)


class StationDetails(TypedDict):
requirement: str
ability: str
pt: NotRequired[PowerToughness]


class StationLayout(NormalLayout):
_pt_pattern = re.compile(r"([0-9]+)/([0-9]+)")

card_class: str = LayoutType.Station

@cached_property
def oracle_text_unprocessed(self) -> str:
"""Unaltered oracle text."""
return (
self.card.get("printed_text", self.oracle_text_raw)
if self.is_alt_lang
else self.oracle_text_raw
)

@cached_property
def oracle_text(self) -> str:
"""Oracle text with station levels stripped."""
stations_start = self.oracle_text_unprocessed.index("\nSTATION ")
return self.oracle_text_unprocessed[0:stations_start]

@cached_property
def stations(self) -> list[StationDetails]:
stations_start = self.oracle_text_unprocessed.index("\nSTATION ")
station_splits = self.oracle_text_unprocessed[stations_start:].split("STATION ")
out: list[StationDetails] = []
for split in station_splits:
if stripped := split.strip():
lines = stripped.split("\n")

details: StationDetails = {"requirement": lines.pop(0), "ability": ""}

for line in lines:
if match := self._pt_pattern.match(line):
details["pt"] = {
"power": match[1],
"toughness": match[2]
}
else:
details["ability"] += line + "\n"

details["ability"] = details["ability"].strip()

out.append(details)
return out


"""
* Types & Enums
"""
Expand Down Expand Up @@ -1575,6 +1634,7 @@ def card_count(self) -> Optional[int]:
LayoutScryfall.Planeswalker: PlaneswalkerLayout,
LayoutScryfall.PlaneswalkerMDFC: PlaneswalkerMDFCLayout,
LayoutScryfall.PlaneswalkerTransform: PlaneswalkerTransformLayout,
LayoutScryfall.Station: StationLayout,

# TODO: Supported by Scryfall, not implemented
LayoutScryfall.Flip: TransformLayout,
Expand Down
1 change: 1 addition & 0 deletions src/templates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
from src.templates.prototype import *
from src.templates.planar import *
from src.templates.split import *
from src.templates.station import *
Loading