class __Game(): __FPS = 0 def __init__(self, defaults, window_attributes): random.seed() Game.__Game.__FPS = defaults["FPS"] pygame.init() self.time_since_started = pygame.time.get_ticks() self.clock = Clock() self.delta = 0 self.screen = pygame.display.set_mode(window_attributes["size"]) pygame.display.set_caption(window_attributes["caption"]) from src.scene import Scene self.scene = Scene() self.is_start = False self.is_run = False def start(self): scene_started = self.scene.start() self.is_run = True return self.is_run and scene_started def process_events(self): for evt in pygame.event.get(): if evt.type == QUIT: self.quit() def update(self, delta): self.scene.update(delta) def render(self, target): #target.fill((200, 200, 200)) self.scene.render(target) pygame.display.flip() def run(self): if self.is_start: return self.is_start = self.start() if not self.is_start: raise RuntimeError("could not start") while self.is_run: self.process_events() self.update(self.delta) self.render(self.screen) self.delta = self.clock.tick(Game.instance.__FPS) self.time_since_started = pygame.time.get_ticks() pygame.quit() def quit(self): self.is_run = False
def load(self): Scene.load(self) print('loading world') self.TestMap.loadMap('pygame-roguelike-layout-01') Keyboard.on(Keyboard.keymap['PAUSE'], self.pauseUnpause) pass
def __init__(self): Scene.__init__(self) self.next = None self.music = "assets/music/Phillip_Gross_-_02_-_Neon_Twin.mp3" self.background_1 = load_image("assets/images/scenes/background_credits.png") self.buttons = [ ButtonPlay(lambda: self.assign_next_scene("main_menu")) ] self.mouse_state = 1 # Up
def __init__(self, data, level): Scene.__init__(self) self.level = level self.music = "assets/music/{}".format(data["music"]) self.sound_time_over = load_sound("assets/sounds/time_over.wav") self.sound_game_over = load_sound("assets/sounds/game_over.wav") self.sound_level_completed = load_sound("assets/sounds/level_completed.wav") self.background = load_image("assets/images/scenes/{}".format(data["background"])) # Things self.good_objets_data = data["good_objets"] # List of tuples (object, probability 0-1, needs) self.good_objets = [] for ii in range(len(self.good_objets_data)): self.good_objets.append(self.good_objets_data[ii][0](ICON_LOCATIONS[ii])) self.bad_objects = data["bad_objets"] self.new_object_probability = data["new_object_probability"] self.probabilities = [self.good_objets_data[0][1] * self.new_object_probability] for ii in range(1, len(self.good_objets_data)): self.probabilities.append(self.probabilities[ii-1] + (self.good_objets_data[ii][1] * self.new_object_probability)) # Variables self.things = pygame.sprite.Group() self.level_time = self.countdown = data["level_time"] * 1000 self.start = False self.end_completed = False self.end_failed_time = False self.end_failed_health = False self.mouse_state = 1 # Up #Characters self.player = Player("keyboard", int(WIDTH / 2), GROUND_LEVEL) # Buttons ## Start level button self.start_level_button = load_image("assets/images/buttons/start_level_button.png") self.start_level_button_rect = self.start_level_button.get_rect() self.start_level_button_rect.center = START_FINISH_BUTTON ## Next level button self.next_level_button = load_image("assets/images/buttons/next_level_button.png") self.next_level_button_rect = self.next_level_button.get_rect() self.next_level_button_rect.center = START_FINISH_BUTTON ## Time over button self.time_over_button = load_image("assets/images/buttons/time_over_button.png") self.time_over_button_rect = self.time_over_button.get_rect() self.time_over_button_rect.center = START_FINISH_BUTTON ## Dead button self.dead_button = load_image("assets/images/buttons/dead_button.png") self.dead_button_rect = self.dead_button.get_rect() self.dead_button_rect.center = START_FINISH_BUTTON
def __init__(self): Scene.__init__(self) self.next = None self.music = "assets/music/Phillip_Gross_-_02_-_Neon_Twin.mp3" self.background_1 = load_image( "assets/images/scenes/background_tutorial.png") self.buttons = [ ButtonClose(LOCATION_BUTTON_CLOSE, lambda: self.assign_next_scene("main_menu")) ] self.mouse_state = 1 # Up
def __init__(self): Scene.__init__(self) self.next = None self.music = "assets/music/Phillip_Gross_-_02_-_Neon_Twin.mp3" self.background_1 = load_image( "assets/images/scenes/background_menu_1.png") self.background_2 = load_image( "assets/images/scenes/background_menu_2.png") self.buttons = [ ButtonPlay(lambda: self.assign_next_scene("intro")), ButtonCredits(lambda: self.assign_next_scene("credits")), ButtonTutorial(lambda: self.assign_next_scene("tutorial")), ] self.mouse_state = 1 # Up
def __init__(self, w, h): super().__init__() self.connect('destroy', Gtk.main_quit) self.set_default_size(w, h) drawingarea = Gtk.DrawingArea() drawingarea.set_can_focus(True) drawingarea.add_events(Gdk.EventMask.KEY_PRESS_MASK) drawingarea.connect('draw', self.on_draw) drawingarea.connect('key-press-event', self.on_key_press) self.add(drawingarea) self.drawingarea = drawingarea self.center = (w // 2, h // 2) self.scene = Scene(120)
def __init__(self, defaults, window_attributes): random.seed() Game.__Game.__FPS = defaults["FPS"] pygame.init() self.time_since_started = pygame.time.get_ticks() self.clock = Clock() self.delta = 0 self.screen = pygame.display.set_mode(window_attributes["size"]) pygame.display.set_caption(window_attributes["caption"]) from src.scene import Scene self.scene = Scene() self.is_start = False self.is_run = False
def __init__(self, bot, scenario_data): self.bot = bot self.chat_id = None # not thread-safe self.players = defaultdict(dict) self.picture_sender = PictureSender(self.bot) self.scenario = {} for scene_data in scenario_data: scene = Scene.from_data(scene_data) self.scenario[scene.name] = scene
def __init__(self): Scene.__init__(self) self.next = None self.persiana_sube = True self.fade = False self.changing = False self.alpha = 255 self.music = "assets/music/Phillip_Gross_-_02_-_Neon_Twin.mp3" self.background_persiana = load_image("assets/images/scenes/background_menu_2.png") self.rect_background_persiana = self.background_persiana.get_rect() self.background_blurry = load_image("assets/images/scenes/background_game_blurry.png") self.background_clear = load_image("assets/images/scenes/background_game_clear.png") self.buttons = [ ButtonPlay(lambda: self.assign_next_scene()) ] self.mouse_state = 1 # Up
def __init__(self, level): Scene.__init__(self) self.level = level self.next = None self.music = "assets/music/Phillip_Gross_-_03_-_Optimistic_Bits.mp3" self.sound_notification = load_sound("assets/sounds/notification.wav") self.background = load_image("assets/images/scenes/background_chat.png") self.chat = [] for i in range(6): self.chat.append(pygame.transform.scale(load_image("assets/images/scenes/{}-{}.png".format(level, i)), CHAT_SURFACE)) self.current_chat = -1 self.chat_rect = self.chat[0].get_rect() self.chat_rect.center = (int(WIDTH / 2) , int(HEIGHT / 2)) # Next chat button self.next_chat_button = load_image("assets/images/buttons/next_chat_button.png") self.next_chat_button_rect = self.next_chat_button.get_rect() self.next_chat_button_rect.center = NEXT_CHAT_BUTTON self.mouse_state = 1 # Up
def initUI(self): self.scene = Scene(10, 20) self.view = View(self.scene) self.view.setCacheMode(QGraphicsView.CacheBackground) self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate); self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setCentralWidget(self.view) self._createActions() self._createMenuBar() self._createToolBar() statusbar = self.statusBar() statusbar.setStyleSheet('QStatusBar{border-top: 1px outset grey;}') self.resize(768, 720 + self.statusBar().sizeHint().height() + self.menuBar().sizeHint().height() + self.toolbar.sizeHint().height()) #Toolbar self.center() self.setWindowTitle('Stackmaker') self.show()
def __init__(self): Scene.__init__(self) self.paused = False self.Character = CharacterController(Character(), self.CHARACTER_GROUP) self.TestMap = Map() Scene.add(self, 'CharacterController', self.Character) Scene.add(self, 'TestMap', self.TestMap) pass
def new_file(self): if not self.close_file(): return dialog = NewFileDialog() code = dialog.exec() if code == 0: return self.root.scene = Scene(self.root) self.root.ui.graphicsView.setScene(self.root.scene) white_sheet = QPixmap(dialog.ui.width_spin.value(), dialog.ui.height_spin.value()) white_sheet.fill() bg = QGraphicsPixmapItem(white_sheet) self.root.scene.addItem(bg)
def __init__(self, kernel_filename, scene_filename, width, height, noise, obj, animation, record, no_gui): self._run = self.animation_run if animation else self.normal_run self.record = record self.no_gui = no_gui if self.record: os.makedirs("animation") self.frame = 0 self.wait = animation self.width, self.height = width, height self.actions_list = self.get_action_list() scene = Scene(None, None) scene.load_from_json(scene_filename) if obj: scene.load_from_mesh(obj) self.camera = Camera(width, height) scene.add_object(self.camera) self.connector = Connector(kernel_filename, scene, width, height, noise) if not self.no_gui: self.parent_conn, child_conn = Pipe() self.gui_process = Process(target=gui_worker, args=(child_conn, width, height)) self.gui_process.start() self.running = True self.denoiser = Denoiser.create("CnnAutoencoder", width, height) self.next_frame = True self.actions = { a: False for a in [ "w", "a", "s", "d", "Up", "Left", "Down", "Right", "q", "e", "plus", "minus" ] }
def open_file(self): if not self.close_file(): return new_file_name, _ = QFileDialog.getOpenFileName(self.root, "Open File", "", "Images (*.jpg *.jpeg *.png)", options=self.file_dialog_options) if not new_file_name: return self.root.file_name = new_file_name self.root.scene = Scene(self.root) self.root.ui.graphicsView.setScene(self.root.scene) img = QPixmap(new_file_name) white_sheet = QPixmap(img.width(), img.height()) white_sheet.fill() bg = QGraphicsPixmapItem(white_sheet) insertion = QGraphicsPixmapItem(img) self.root.scene.addItem(bg) self.root.scene.addItem(insertion)
def update(self): Scene.update(self) self.mainCamera.focus(self.Character.character.pos) pass
def end(self): Scene.end(self) print('ending world scene') pass
def start(self): Scene.start(self) print('starting world scene') pass
class StackMaker(QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initUI() def _createActions(self): # https://realpython.com/python-menus-toolbars/ for menu stuff later self.exitAct = QAction(QIcon(resource_path('./assets/icons/exit.png')), '&Exit', self) self.exitAct.setShortcut('Ctrl+Q') self.exitAct.setStatusTip('Exit application') self.exitAct.triggered.connect(qApp.quit) self.copyAct = QAction(QIcon(resource_path('./assets/icons/copy.png')), '&Copy', self) self.copyAct.setShortcut('Ctrl+C') self.copyAct.setStatusTip('Copy entire board') self.copyAct.triggered.connect(self.copy) self.mainActs = QActionGroup(self) self.selectAct = QAction(QIcon(resource_path('./assets/icons/select.ico')), '&Select', self.mainActs) self.selectAct.setShortcut('Shift+S') self.selectAct.setStatusTip('Select board part for copying.') self.selectAct.setCheckable(True) self.selectAct.setEnabled(True) self.selectAct.toggled.connect(self.view.toggleBand) self.undoAct = QAction(QIcon(resource_path('./assets/icons/undo.ico')), '&Undo', self) self.undoAct.setShortcut('Ctrl+Z') self.undoAct.setStatusTip('Undo most recent action') self.undoAct.setEnabled(True) self.undoAct.triggered.connect(self.scene.undo) self.redoAct = QAction(QIcon(resource_path('./assets/icons/redo.ico')), '&Redo', self) self.redoAct.setShortcut('Ctrl+Y') self.redoAct.setStatusTip('Redo most recent action') self.redoAct.setEnabled(True) self.redoAct.triggered.connect(self.scene.redo) self.ccwAct = QAction(QIcon(), '&Counterclockwise') self.ccwAct.setShortcut('Q') self.ccwAct.setStatusTip('Rotate counterclockwise') self.ccwAct.setEnabled(False) self.ccwAct.triggered.connect(self.scene.cursor.ccw) self.cwAct = QAction(QIcon(), '&Clockwise') self.cwAct.setShortcut('W') self.cwAct.setStatusTip('Rotate clockwise') self.cwAct.setEnabled(False) self.cwAct.triggered.connect(self.scene.cursor.cw) pieceNames = ['T','J','Z','O','S','L','I'] self.pieceActs = [] for i in range(7): pieceAct = QAction(QIcon(resource_path(f'./assets/icons/icon{pieceNames[i]}.ico')), pieceNames[i], self.mainActs) pieceAct.setShortcut(pieceNames[i]) pieceAct.setStatusTip(f'Draw the {pieceNames[i]} piece') pieceAct.setCheckable(True) # Ugly solution but it works pieceAct.triggered.connect(lambda x=False,i=i: self.scene.cursor.setType([i, 0])) pieceAct.triggered.connect(lambda : self.ccwAct.setEnabled(True)) pieceAct.triggered.connect(lambda : self.cwAct.setEnabled(True)) self.pieceActs.append(pieceAct) self.cellActs = [] icons = [ QIcon(QPixmap(resource_path('./assets/tile0.png')).scaled(16, 16)), QIcon(resource_path('./assets/icons/whiteCell.ico')), QIcon(resource_path('./assets/icons/darkCell.ico')), QIcon(resource_path('./assets/icons/lightCell.ico')), QIcon(resource_path('./assets/icons/stack.ico')) ] names = ['&Erase', '&White Cell', '&Dark Cell', '&Light Cell', '&Stack Mode'] shortcuts = ['E', '1', '2', '3', 'C'] tips = ['Erase cell', 'Paint the white cell', 'Paint the dark cell', 'Paint the light cell', 'Fill basic stack'] for i in range(5): cellAct = QAction(icons[i], names[i], self.mainActs) cellAct.setShortcut(shortcuts[i]) cellAct.setStatusTip(tips[i]) cellAct.setCheckable(True) if i == 4: cellAct.triggered.connect(lambda : self.scene.setColCursor()) else: cellAct.triggered.connect(lambda x=False,i=i : self.scene.setCellState(i)) cellAct.triggered.connect(lambda : self.ccwAct.setEnabled(False)) cellAct.triggered.connect(lambda : self.cwAct.setEnabled(False)) self.cellActs.append(cellAct) self.cellActs[1].setChecked(True) self.transparentAct = QAction(QIcon(), '&Transparent') self.transparentAct.setShortcut('Ctrl+V') self.transparentAct.setStatusTip('Draw with transparent cells') self.transparentAct.setCheckable(True) self.transparentAct.triggered.connect(lambda x : self.scene.setTransparentDraw(x)) self.rgbAct = QAction(QIcon(), '&Option Colors') self.rgbAct.setShortcut('Ctrl+A') self.rgbAct.setStatusTip('Tint drawn objects with varying colors') self.rgbAct.setCheckable(True) self.connectStatusAct = QAction(QIcon(), '&Enable/Disable', self) self.connectStatusAct.triggered.connect(self.enableTracking) self.toggleMirrorAct = QAction(QIcon(), '&Toggle Mirror', self) self.toggleMirrorAct.setShortcut('Ctrl+M') self.toggleMirrorAct.setEnabled(False) self.toggleMirrorAct.triggered.connect(self.toggleMirror) def _createMenuBar(self): menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(self.exitAct) fileMenu.addAction(self.copyAct) drawMenu = menubar.addMenu('&Draw') drawMenu.addAction(self.selectAct) drawMenu.addAction(self.undoAct) drawMenu.addAction(self.redoAct) for act in self.cellActs: drawMenu.addAction(act) pieceMenu = drawMenu.addMenu('&Piece') for act in self.pieceActs: pieceMenu.addAction(act) pieceMenu.addSeparator() pieceMenu.addAction(self.ccwAct) pieceMenu.addAction(self.cwAct) viewMenu = menubar.addMenu('&View') viewMenu.addAction(self.transparentAct) viewMenu.addAction(self.rgbAct) connectMenu = menubar.addMenu('&Connect') connectMenu.addAction(self.connectStatusAct) connectMenu.addAction(self.toggleMirrorAct) def _createToolBar(self): self.toolbar = self.addToolBar('test') self.toolbar.setMovable(False) self.toolbar.addAction(self.selectAct) self.toolbar.addAction(self.undoAct) self.toolbar.addAction(self.redoAct) self.toolbar.addSeparator() for act in self.cellActs: self.toolbar.addAction(act) self.toolbar.addSeparator() for act in self.pieceActs: self.toolbar.addAction(act) def initUI(self): self.scene = Scene(10, 20) self.view = View(self.scene) self.view.setCacheMode(QGraphicsView.CacheBackground) self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate); self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setCentralWidget(self.view) self._createActions() self._createMenuBar() self._createToolBar() statusbar = self.statusBar() statusbar.setStyleSheet('QStatusBar{border-top: 1px outset grey;}') self.resize(768, 720 + self.statusBar().sizeHint().height() + self.menuBar().sizeHint().height() + self.toolbar.sizeHint().height()) #Toolbar self.center() self.setWindowTitle('Stackmaker') self.show() def center(self): '''centers the window on the screen''' screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move(int((screen.width() - size.width()) // 2), int((screen.height() - size.height()) // 2)) # Resizing the viewport is necessary for some reason. Should check why this needs to be used def resizeEvent(self, e): self.view.viewport().resize(self.width(), self.height() - self.statusBar().sizeHint().height()-self.menuBar().sizeHint().height()-self.toolbar.sizeHint().height()) print(self.width(), self.height()) print(self.view.width(), self.view.height()) # print(self.view.minimumSizeHint()) # # print(self.view.viewport().width(), self.view.viewport().height()) # # self.view.fitInView(self.view.sceneRect(), Qt.KeepAspectRatio) self.view.setRect() def copy(self): clipboard = QGuiApplication.clipboard() rect = self.scene.sceneRect() if self.view.selection() == QRect() else self.view.sceneSelection() board = QImage(rect.size().toSize(), QImage.Format_ARGB32) board.fill(Qt.transparent) painter = QPainter(board) self.scene.render(painter, QRectF(), rect) board1 = board.scaled(board.width()*2, board.height()*2) clipboard.setImage(board1) painter.end() self.statusBar().showMessage('Copied!', 500) def toggleMirror(self): self.scene.ocrHandler.socket.blockSignals(not self.scene.ocrHandler.socket.signalsBlocked()) def enableTracking(self): if not self.scene.ocrHandler.connected: print('Awaiting connection...') self.scene.ocrHandler.listen(QHostAddress.LocalHost, 3338) self.toggleMirrorAct.setEnabled(True) else: print('Disconnecting') self.scene.ocrHandler.exit() self.toggleMirrorAct.setEnabled(False)
import os import fileinput from shutil import copyfile from PySide import QtGui from src.view import View from src.scene import Scene from src.model import * from aether.diagnostics import set_diagnostics_on from aether.geometry import define_elem_geometry_2d, define_node_geometry_2d, define_data_geometry, define_rad_from_file, define_rad_from_geom, append_units from aether.exports import export_node_geometry_2d, export_elem_geometry_2d, export_data_geometry from aether.surface_fitting import fit_surface_geometry from opencmiss.zinc.scenecoordinatesystem import SCENECOORDINATESYSTEM_WINDOW_PIXEL_TOP_LEFT app = QtGui.QApplication(sys.argv) scene = Scene() datacloudModel = FileModel(scene, 'datacloud') surfaceModel = FileModel(scene, 'surface') # the keys in these dicts correspond to the accessibleName in Qt landmarkCoords = {} landmarkModels = {} landmarkMaterials = { 'apex': 'green', 'basal': 'red', 'lateral': 'blue', 'ventral': 'yellow', }
options["lengthLimit"], options["shortestLength"], options["rotationLimit"]) export_node_geometry('.tmp.exnode', 'out') export_1d_elem_geometry('.tmp.exelem', 'out') airwayModel.load('.tmp.exnode', '.tmp.exelem') def save(exnode, exelem): export_node_geometry(exnode, 'out') export_1d_elem_geometry(exelem, 'out') app = QtGui.QApplication(sys.argv) scene = Scene() airwayModel = scene.newModel('airway') surfaceModel = scene.newModel('surface') view = View(scene) view.airwayCallback(loadAirway) view.surfaceCallback(loadSurface) view.generateCallback(generate) view.saveCallback(save) view.setAirways('airway_tree_FRC.ipnode', 'airway_tree_FRC.ipelem') view.setOutputs('out.exnode', 'out.exelem') view.setInfo(""" <h2>Grow airway tree</h2> <p>This GUI provides an easy interface for the grow_tree Fortran code in lungsim. It allows the visualization of the airway tree and the surface mesh and allows configuring the growth algorithm.</p> <p>Created for use within the Auckland Bioengineering Institute at the University of Auckland.</p> <h3>Usage</h3>
class Window(Gtk.Window): def __init__(self, w, h): super().__init__() self.connect('destroy', Gtk.main_quit) self.set_default_size(w, h) drawingarea = Gtk.DrawingArea() drawingarea.set_can_focus(True) drawingarea.add_events(Gdk.EventMask.KEY_PRESS_MASK) drawingarea.connect('draw', self.on_draw) drawingarea.connect('key-press-event', self.on_key_press) self.add(drawingarea) self.drawingarea = drawingarea self.center = (w // 2, h // 2) self.scene = Scene(120) def __fill_triangle(self, ctx, v1, v2, v3, color): # http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html v1, v2, v3 = sorted([v1, v2, v3], key=lambda v: v.y) if v2.y == v3.y: self.__fill_bottom_flat_triangle(ctx, v1, v2, v3, color) elif v1.y == v2.y: self.__fill_top_flat_triangle(ctx, v1, v2, v3, color) else: v = Vector([ v1.x + (v3.x - v1.x) * (v2.y - v1.y) // (v3.y - v1.y), v2.y, 0, ]) self.__fill_bottom_flat_triangle(ctx, v1, v2, v, color) self.__fill_top_flat_triangle(ctx, v2, v, v3, color) def __fill_bottom_flat_triangle(self, ctx, v1, v2, v3, color): scanlineY = v1.y while scanlineY <= v2.y: x1 = v1.x + (scanlineY - v1.y) * (v2.x - v1.x) // (v2.y - v1.y) x2 = v1.x + (scanlineY - v1.y) * (v3.x - v1.x) // (v3.y - v1.y) scanlineY += 1 self.__draw_line(ctx, x1, x2, scanlineY, color) def __fill_top_flat_triangle(self, ctx, v1, v2, v3, color): scanlineY = v3.y while scanlineY > v1.y: x1 = v3.x - (v3.y - scanlineY) * (v3.x - v1.x) // (v3.y - v1.y) x2 = v3.x - (v3.y - scanlineY) * (v3.x - v2.x) // (v3.y - v2.y) scanlineY -= 1 self.__draw_line(ctx, x1, x2, scanlineY, color) def __draw_line(self, ctx, x1, x2, y, color): if x2 < x1: x1, x2 = x2, x1 while x1 < x2: # https://en.wikipedia.org/wiki/Dither if color * 300 >= rgen(): ctx.set_source_rgb(0, 0, 0) else: ctx.set_source_rgb(1, 1, 1) ctx.rectangle(x1 + self.center[0], -y + self.center[1], 1, 1) ctx.fill() x1 += 1 def on_draw(self, _, ctx): ctx.save() ctx.set_line_width(1) ctx.set_source_rgb(1, 1, 1) ctx.new_path() ctx.move_to(0, 0) ctx.line_to(512, 0) ctx.line_to(512, 256) ctx.line_to(0, 256) ctx.close_path() ctx.fill() for v1, v2, v3, cl in self.scene.iter_facets(): self.__fill_triangle(ctx, v1, v2, v3, cl) ctx.set_source_rgb(0, 0, 0) ctx.new_path() ctx.move_to(v1.x + self.center[0], -v1.y + self.center[1]) ctx.line_to(v2.x + self.center[0], -v2.y + self.center[1]) ctx.line_to(v3.x + self.center[0], -v3.y + self.center[1]) ctx.close_path() ctx.stroke() ctx.restore() def on_key_press(self, _, e): if e.keyval == Gdk.KEY_Up: self.scene.rotate_x(-1) elif e.keyval == Gdk.KEY_Down: self.scene.rotate_x(1) elif e.keyval == Gdk.KEY_Left: self.scene.rotate_y(1) elif e.keyval == Gdk.KEY_Right: self.scene.rotate_y(-1) self.drawingarea.queue_draw()