class Renderer(): ORIGIN = QPoint(230, 230) def __init__(self): self.commands = None self.animations = None self.paths = [] self.angle = 0 self.position = Renderer.ORIGIN def set_commands(self, cmds): self.commands = cmds def paint(self, painter): if self.animations: self.animations.draw_paths(painter) def reset(self): self.paths = [] self.angle = 0 self.position = Renderer.ORIGIN def render(self, commands=None, loop=False): if not loop: self.reset() if commands is None and self.commands is not None: commands = self.commands for i in range(len(commands)): cmd = commands[i] action = cmd.get('action', None) magnitude = cmd.get('magnitude', None) direction = cmd.get('direction', None) x, y = self.position.x(), self.position.y() if action == 'move': self.move_action(cmd, x, y) elif action == 'draw': self.draw_action(cmd, x, y) elif action == 'rotate': self.rotate_action(magnitude) elif action == 'jumpto': self.jumpto_action(magnitude) elif action == 'circle': self.circle_action(magnitude, x, y) elif action == 'repeat': self.repeat_action(commands, magnitude, i) elif action == 'endrepeat' or action == 'pass': continue else: print("UNKNOWN RENDER ACTION") break def move_action(self, cmd, x, y): magnitude = self.calculate_magnitude(cmd) end_point = self.calculate_end_point(x, y, magnitude) self.position = end_point def draw_action(self, cmd, x, y): magnitude = self.calculate_magnitude(cmd) end_point = self.calculate_end_point(x, y, magnitude) self.position = end_point self.paths.append(LinePath(QPoint(x, y), end_point)) def rotate_action(self, angle): self.angle += float(angle) def jumpto_action(self, magnitude): coords = magnitude.split(',') x, y = self.normalize(int(coords[0])), self.normalize(int(coords[1])) self.position = QPoint(x, y) def normalize(self, i): return min(max(i, 0), 460) def circle_action(self, radius, x, y): self.paths.append(CirclePath(x, y, float(radius))) def repeat_action(self, commands, iterations, index): start = index + 1 # Index of cmd after 'repeat' statement end = len(commands) - start looped_cmds = 0 # Amounts of commands within the loop for j in range(end+(start)-1, start, -1): if commands[j]['action'] == 'endrepeat': end = j - 1 # Don't want to render 'endrepeat' looped_cmds = end - start + 1 if int(iterations) == 0: for j in range(looped_cmds+1): commands[j] = {'action': 'pass'} else: looped_cmds_list = [] for j in range(int(iterations)-1): for cmd_index in range(start, end+1): looped_cmds_list.append(commands[cmd_index]) self.render(looped_cmds_list, loop=True) def start_animations(self, speed): self.animations = SequentialAnimationGroup(self.paths, speed) self.animations.start_sequence() def calculate_magnitude(self, cmd): magnitude = int(cmd['magnitude']) if 'b' in cmd['direction']: magnitude *= -1 return magnitude # Returns end point of line dependant on angle of drawing_point def calculate_end_point(self, x, y, magnitude): #angle = self.drawing_point.get_angle() end_x = round(x + magnitude * sin(radians(self.angle))) end_y = round(y - magnitude * cos(radians(self.angle))) return QPoint(end_x, end_y) def get_x(self): return self.position.x() def get_y(self): return self.position.y()
def start_animations(self, speed): self.animations = SequentialAnimationGroup(self.paths, speed) self.animations.start_sequence()