122 lines
3.0 KiB
Python
122 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
import copy
|
|
|
|
|
|
@dataclass
|
|
class CompositionInfo:
|
|
width: int = 1200
|
|
height: int = 600
|
|
|
|
|
|
@dataclass
|
|
class SourceInfo:
|
|
original_export: str = ""
|
|
derived_from: str = ""
|
|
composition: CompositionInfo = field(default_factory=CompositionInfo)
|
|
|
|
|
|
@dataclass
|
|
class LogicalDisplayConfig:
|
|
rows: int = 3
|
|
cols: int = 6
|
|
preview_width: int = 1200
|
|
preview_height: int = 600
|
|
tile_width: int = 200
|
|
tile_height: int = 200
|
|
|
|
|
|
@dataclass
|
|
class DefaultsConfig:
|
|
protocol: str = "artnet"
|
|
subnet: int = 0
|
|
color_format: str = "rgb"
|
|
tile_behavior: str = "solid_color_per_tile"
|
|
global_gamma: float = 2.2
|
|
|
|
|
|
@dataclass
|
|
class CalibrationConfig:
|
|
brightness: float = 1.0
|
|
red_gain: float = 1.0
|
|
green_gain: float = 1.0
|
|
blue_gain: float = 1.0
|
|
|
|
|
|
@dataclass
|
|
class SegmentConfig:
|
|
name: str
|
|
side: str
|
|
start_channel: int
|
|
led_count: int
|
|
orientation_rad: float = 0.0
|
|
x0: float = 0.0
|
|
y0: float = 0.0
|
|
x1: float = 0.0
|
|
y1: float = 0.0
|
|
reverse: bool = False
|
|
|
|
|
|
@dataclass
|
|
class TileConfig:
|
|
tile_id: str
|
|
row: int
|
|
col: int
|
|
screen_name: str = ""
|
|
controller_ip: str = ""
|
|
controller_host: str = ""
|
|
controller_name: str = ""
|
|
controller_mac: str = ""
|
|
universe: int = 0
|
|
subnet: int = 0
|
|
led_total: int = 0
|
|
x0: float = 0.0
|
|
y0: float = 0.0
|
|
x1: float = 0.0
|
|
y1: float = 0.0
|
|
enabled: bool = True
|
|
calibration: CalibrationConfig = field(default_factory=CalibrationConfig)
|
|
segments: list[SegmentConfig] = field(default_factory=list)
|
|
|
|
@property
|
|
def brightness_factor(self) -> float:
|
|
return self.calibration.brightness
|
|
|
|
@brightness_factor.setter
|
|
def brightness_factor(self, value: float) -> None:
|
|
self.calibration.brightness = value
|
|
|
|
|
|
@dataclass
|
|
class InfinityMirrorConfig:
|
|
name: str = "Infinity Mirror"
|
|
version: str = "1.0"
|
|
source: SourceInfo = field(default_factory=SourceInfo)
|
|
logical_display: LogicalDisplayConfig = field(default_factory=LogicalDisplayConfig)
|
|
defaults: DefaultsConfig = field(default_factory=DefaultsConfig)
|
|
tiles: list[TileConfig] = field(default_factory=list)
|
|
file_path: Path | None = None
|
|
|
|
def clone(self) -> "InfinityMirrorConfig":
|
|
return copy.deepcopy(self)
|
|
|
|
def sorted_tiles(self) -> list[TileConfig]:
|
|
return sorted(self.tiles, key=lambda tile: (tile.row, tile.col, tile.tile_id))
|
|
|
|
def tile_lookup(self) -> dict[str, TileConfig]:
|
|
return {tile.tile_id: tile for tile in self.tiles}
|
|
|
|
def tile_at(self, row: int, col: int) -> TileConfig | None:
|
|
for tile in self.tiles:
|
|
if tile.row == row and tile.col == col:
|
|
return tile
|
|
return None
|
|
|
|
def all_segments(self) -> Iterable[tuple[TileConfig, SegmentConfig]]:
|
|
for tile in self.sorted_tiles():
|
|
for segment in tile.segments:
|
|
yield tile, segment
|