Passed
Pull Request — master (#21)
by Matt
02:43
created

PyDMXControl.design._screen.Screen.__init__()   A

Complexity

Conditions 1

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nop 1
dl 0
loc 20
rs 9.7
c 0
b 0
f 0
1
"""
2
 *  PyDMXControl: A Python 3 module to control DMX using uDMX.
3
 *                Featuring fixture profiles, built-in effects and a web control panel.
4
 *  <https://github.com/MattIPv4/PyDMXControl/>
5
 *  Copyright (C) 2018 Matt Cowley (MattIPv4) ([email protected])
6
"""
7
8
import os.path  # User files
9
from datetime import datetime  # Dates
10
from math import ceil, floor  # Rounding
11
12
import pygame  # PyGame
13
14
15
class Screen:
16
17
    def __init__(self):
18
        self.__thread = None
19
        self.__running = False
20
        self.__grid = False
21
        self.__parts = []
22
        self.__bg = (245, 245, 245)
23
        self.block_size = 19
24
25
        # Init pygame
26
        pygame.init()
27
28
        # Get font
29
        self.__font = pygame.font.SysFont("monospace", 15)
30
31
        # Create pygame screen
32
        display_info = pygame.display.Info()
33
        self.parts_render = None
34
        self.last_render = None
35
        self.screen = pygame.display.set_mode((display_info.current_w - 20, display_info.current_h - 70))
36
        pygame.display.set_caption("PyDMXControl Design")
37
38
    def add_part(self, part: 'Part'):
39
        self.__parts.append(part)
40
41
    def __events(self):
42
        for e in pygame.event.get():
43
            if e.type == pygame.KEYDOWN:
44
                # if e.key == pygame.K_g:
45
                #    self.__grid = not self.__grid
46
                if e.key == pygame.K_q:
47
                    self.__running = False
48
                if e.key == pygame.K_s:
49
                    if self.parts_render:
50
                        file = "{}/PYDMXControl_Design_{}.png".format(
51
                            os.path.expanduser("~/Desktop"),
52
                            datetime.now().strftime("%Y%m%d_%H%M%S")
53
                        )
54
                        pygame.image.save(self.parts_render, file)
55
56
    def __draw_parts(self):
57
        # Get render of each
58
        parts = []
59
        for part in self.__parts:
60
            try:
61
                parts.append(part.design_render(self))
62
            except:
63
                pass
64
65
        # Generate size
66
        maxx = max([f[0] + f[2].get_width() for f in parts])
67
        maxy = max([f[1] + f[2].get_height() for f in parts])
68
        surface = pygame.Surface((maxx, maxy), pygame.SRCALPHA, 32)
69
        surface.convert_alpha()
70
71
        # Render
72
        for part in parts:
73
            surface.blit(part[2], (part[0], part[1]))
74
75
        # Save full res
76
        self.parts_render = surface
77
78
    def __draw_bg(self):
79
        # New surface
80
        sx, sy = self.parts_render.get_size()
81
        surface = pygame.Surface((sx, sy), pygame.SRCALPHA, 32)
82
        surface.convert_alpha()
83
        surface.fill(self.__bg)
84
85
        # Draw grid
86
        if self.__grid:
87
            w, h = pygame.display.get_surface().get_size()
88
            w = ceil(w / self.block_size)
89
            h = ceil(h / self.block_size)
90
            for y in range(h):
91
                for x in range(w):
92
                    invert = ((x + (y % 2)) % 2 == 0)
93
                    color = [200] * 3 if invert else [250] * 3
94
                    rect = pygame.Rect(x * self.block_size, y * self.block_size, self.block_size, self.block_size)
95
                    pygame.draw.rect(surface, color, rect)
96
97
        # Add parts
98
        surface.blit(self.parts_render, (0, 0))
99
100
        # Save full res
101
        self.last_render = surface
102
103
    def __draw_mouse(self):
104
        # Generate text
105
        mx, my = pygame.mouse.get_pos()
106
        text = self.__font.render("x: {:,} y: {:,}".format(
107
            floor(mx / self.block_size),
108
            floor(my / self.block_size),
109
        ), True, (0, 0, 0))
110
111
        # Generate background
112
        padding = 5
113
        x, y = text.get_size()
114
        surface = pygame.Surface((x + padding * 2, y + padding * 2), pygame.SRCALPHA, 32)
115
        surface = surface.convert_alpha()
116
        surface.fill((225, 225, 225, 128))
117
118
        # Add text
119
        surface.blit(text, (padding, padding))
120
121
        # Add border
122
        x, y = surface.get_size()
123
        rectv = pygame.Rect(0, y / 4 * 3, int(floor(padding / 2)), y / 4)
124
        pygame.draw.rect(surface, (0, 0, 0), rectv)
125
        recth = pygame.Rect(0, y - int(floor(padding / 2)), y / 4, int(floor(padding / 2)))
126
        pygame.draw.rect(surface, (0, 0, 0), recth)
127
128
        # Render
129
        self.screen.blit(surface, (mx, my - y))
130
131
    def __draw(self):
132
        # Draw parts
133
        self.__draw_parts()
134
135
        # Draw base
136
        self.__draw_bg()
137
138
        # Draw mouse
139
        # self.__draw_mouse()
140
141
        # Resize if bigger than screen
142
        mx, my = self.last_render.get_size()
143
        sx, sy = self.screen.get_size()
144
        if mx > sx:
145
            my = my * (sx / mx)
146
            mx = sx
147
        if my > sy:
148
            mx = mx * (sy / my)
149
            my = sy
150
        surface = pygame.transform.scale(self.last_render, (floor(mx), floor(my)))
151
152
        # Render
153
        self.screen.fill(self.__bg)
154
        self.screen.blit(surface, (0, 0))
155
156
    def __start(self):
157
        self.clock = pygame.time.Clock()
158
159
        # Draw to screen
160
        self.__draw()
161
        redraw = 0
162
163
        while self.__running:
164
            # Handle events
165
            self.__events()
166
167
            # Draw to screen (every 10 cycles)
168
            if redraw == 10:
169
                redraw = 0
170
                self.__draw()
171
            redraw += 1
172
173
            # Update display
174
            self.clock.tick(60)
175
            pygame.display.flip()
176
177
        pygame.quit()
178
179
    def render(self):
180
        self.__running = True
181
        self.__start()
182
        quit()
183