-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
113 lines (86 loc) · 2.89 KB
/
utils.py
File metadata and controls
113 lines (86 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from enum import Enum, auto
from typing import Optional, Callable, TYPE_CHECKING, TypeVar, Union
import pygame
if TYPE_CHECKING:
from views import Clip
Surface = Union[pygame.Surface, pygame.surface.Surface]
F = TypeVar('F')
class AttachedEnum(Enum):
'''
Contains a dict with mapping of decorated functions
to their corresponding enum variants.
'''
attached: dict
def __init_subclass__(cls):
cls.attached = {}
def attach(self, fn: F) -> F: # decorator names are usually adjectives
self.attached[fn] = self
return fn
class Mode(AttachedEnum):
__getitem__: Callable[..., 'Mode'] # Just an annotation can't hurt.
type_colour = auto()
type_text = auto()
type_number = auto()
paint = auto()
frame_select = auto() # click to set only selected, not playhead
pixel_region_select = auto()
# tool modes
# attach these to functions to annotate required function signature
frame_dest = auto()
frame_direct = auto() # applies directly if selection exists
pixel_dest = auto()
region_direct = auto() # applies directly if selection is a region
region_extract = auto() # applies directly if selection is a region
fill = auto() # applies directly if selection is a region
class DragMode(Enum):
none = auto()
scrolling = auto()
default = auto() # default drag mode for either frame panel or viewport
scrub = auto() # used to select current frame
pixel_region_select = auto() # while making a selection
# frame_region_select = auto()
class FrameIdent:
def __init__(self, clip: 'Clip', frame: int):
self.clip = clip
self.frame = frame
def frame_surf(self) -> Surface:
return self.clip.surf_at(self.frame)
class RegionIdent:
def __init__(self, clip: 'Clip', frame: int, region: 'Region'):
self.frame_ident = FrameIdent(clip, frame)
self.region = region
def __bool__(self):
return not not self.region
def __repr__(self):
return f'RegionIdent({self.frame_ident.clip}, {self.frame_ident.frame}, {self.region})'
class Region:
def __init__(self, start: tuple[int, int], end: tuple[int, int]):
self._start = start
self._end = end
print('end set to', end)
self._reorganised: Optional[Region] = None
def __bool__(self):
return self._start != None != self._end
def __repr__(self):
return f'Region({self._start} to {self._end})'
def set_end(self, end):
self._end = end
print('end updated to', end)
self._reorganised = None
def set_start(self, start):
self._start = start
self._reorganised = None
def reorganised(self) -> 'Region':
if self._reorganised is not None: return self._reorganised
x1, y1 = self._start
print('trying to unpack', self._end)
x2, y2 = self._end
if x2 < x1: x1, x2 = x2, x1
if y2 < y1: y1, y2 = y2, y1
self._reorganised = self.__class__((x1, y1), (x2, y2))
return self._reorganised
def as_rect(self) -> tuple[int, int, int, int]:
region = self.reorganised()
x1, y1 = region._start
x2, y2 = region._end
return x1, y1, x2-x1, y2-y1