def _create_shadow_window(): global _shadow_window import pyglet if not pyglet.options['shadow_window'] or _is_epydoc: return from pyglet.window import Window _shadow_window = Window(width=1, height=1, visible=False) _shadow_window.switch_to() from pyglet import app app.windows.remove(_shadow_window)
def _create_shadow_window(): global _shadow_window import pyglet if not pyglet.options['shadow_window'] or _is_epydoc: return from pyglet.window import Window _shadow_window = Window(width=1, height=1, visible=False) _shadow_window.switch_to() from pyglet import app app.windows.remove(_shadow_window)
class ImageViewer: def __init__(self, display=None, maxwidth=500): self.window = None self.isopen = False self.display = display def __del__(self): self.close() def imshow(self, arr, caption): if self.window is None: height, width, _ = arr.shape self.window = Window(width=width, height=height, display=self.display, vsync=False, resizable=True) self.width = width self.height = height self.isopen = True assert len(arr.shape) == 3 height, width, _ = arr.shape image = pyglet.image.ImageData(width, height, 'RGB', arr.tobytes(), pitch=-3 * width) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) texture = image.get_texture() texture.width = self.width texture.height = self.height self.window.clear() self.window.switch_to() self.window.dispatch_events() texture.blit(0, 0) self.window.flip() self.window.set_caption(caption) def close(self): if self.isopen: self.window.close() self.isopen = False
class NumpyTube: def __init__(self): self.window = None self.isopen = False def __del__(self): self.close() def imshow(self, img, caption=None): height, width, _ = img.shape pitch = -3 * width if self.window is None: self.window = Window(width=width, height=height, vsync=False) self.width = width self.height = height self.isopen = True data = img.tobytes() image = pyglet.image.ImageData(width, height, "RGB", data, pitch=pitch) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) texture = image.get_texture() texture.width = self.width texture.height = self.height self.window.clear() self.window.switch_to() self.window.dispatch_events() texture.blit(0, 0) self.window.flip() if caption is not None: self.window.set_caption(caption) def close(self): if self.isopen: self.window.close() self.window = None self.isopen = False
class Renderer(object): def __init__(self, client, map_size, minimap_size) -> None: self._client = client self._window = None self._map_size = map_size self._map_image = None self._minimap_size = minimap_size self._minimap_image = None self._mouse_x, self._mouse_y = None, None self._text_supply = None self._text_vespene = None self._text_minerals = None self._text_score = None self._text_time = None async def render(self, observation): render_data = observation.observation.render_data map_size = render_data.map.size map_data = render_data.map.data minimap_size = render_data.minimap.size minimap_data = render_data.minimap.data map_width, map_height = map_size.x, map_size.y map_pitch = -map_width * 3 minimap_width, minimap_height = minimap_size.x, minimap_size.y minimap_pitch = -minimap_width * 3 if not self._window: from pyglet.window import Window from pyglet.image import ImageData from pyglet.text import Label self._window = Window(width=map_width, height=map_height) self._window.on_mouse_press = self._on_mouse_press self._window.on_mouse_release = self._on_mouse_release self._window.on_mouse_drag = self._on_mouse_drag self._map_image = ImageData(map_width, map_height, 'RGB', map_data, map_pitch) self._minimap_image = ImageData(minimap_width, minimap_height, 'RGB', minimap_data, minimap_pitch) self._text_supply = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 10, y=self._map_size[1] - 10, color=(200, 200, 200, 255)) self._text_vespene = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 130, y=self._map_size[1] - 10, color=(28, 160, 16, 255)) self._text_minerals = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 200, y=self._map_size[1] - 10, color=(68, 140, 255, 255)) self._text_score = Label('', font_name='Arial', font_size=16, anchor_x='left', anchor_y='top', x=10, y=self._map_size[1] - 10, color=(219, 30, 30, 255)) self._text_time = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='bottom', x=self._minimap_size[0] - 10, y=self._minimap_size[1] + 10, color=(255, 255, 255, 255)) else: self._map_image.set_data('RGB', map_pitch, map_data) self._minimap_image.set_data('RGB', minimap_pitch, minimap_data) self._text_time.text = str( datetime.timedelta( seconds=(observation.observation.game_loop * 0.725) // 16)) if observation.observation.HasField('player_common'): self._text_supply.text = "{} / {}".format( observation.observation.player_common.food_used, observation.observation.player_common.food_cap) self._text_vespene.text = str( observation.observation.player_common.vespene) self._text_minerals.text = str( observation.observation.player_common.minerals) if observation.observation.HasField('score'): self._text_score.text = "{} score: {}".format( score_pb._SCORE_SCORETYPE.values_by_number[ observation.observation.score.score_type].name, observation.observation.score.score) await self._update_window() if self._client.in_game and (not observation.player_result ) and self._mouse_x and self._mouse_y: await self._client.move_camera_spatial( Point2((self._mouse_x, self._minimap_size[0] - self._mouse_y))) self._mouse_x, self._mouse_y = None, None async def _update_window(self): self._window.switch_to() self._window.dispatch_events() self._window.clear() self._map_image.blit(0, 0) self._minimap_image.blit(0, 0) self._text_time.draw() self._text_score.draw() self._text_minerals.draw() self._text_vespene.draw() self._text_supply.draw() self._window.flip() def _on_mouse_press(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_release(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if not buttons & 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y
class ImageViewer(object): """A simple class for viewing images using pyglet.""" def __init__(self, caption, height, width): """ Initialize a new image viewer. Args: caption (str): the caption/title for the window height (int): the height of the window width (int): the width of the window Returns: None """ self.caption = caption self.height = height self.width = width self._window = None def __repr__(self): """Return an executable string representing this object.""" template = '{}(caption={}, height={}, width={})' return template.format(self.caption, self.height, self.width) def __del__(self): """Close any open windows and delete this object.""" self.close() @property def is_open(self): """Return a boolean determining if this window is open.""" return self._window is not None def open(self): """Open the window.""" self._window = Window( caption=self.caption, height=self.height, width=self.width, vsync=False, resizable=True, ) def show(self, frame): """ Show an array of pixels on the window. Args: frame (numpy.ndarray): the frame to show on the window Returns: None """ # check that the frame has the correct dimensions if len(frame.shape) != 3: raise ValueError('frame should have shape with only 3 dimensions') # open the window if it isn't open already if not self.is_open: self.open() # prepare the window for the next frame self._window.clear() self._window.switch_to() self._window.dispatch_events() # create an image data object image = ImageData(frame.shape[1], frame.shape[0], 'RGB', frame.tobytes(), pitch=frame.shape[1] * -3) # send the image to the window image.blit(0, 0, width=self._window.width, height=self._window.height) self._window.flip() def close(self): """Close the window.""" if self.is_open: self._window.close() self._window = None
class ExpWindow(object): def __init__(self, background_color=dark_gray, clock=mono_clock.get_time): # lazy load, partially to avoid auto-formatter that wants to # do imports, *then* dict setting from pyglet import gl from pyglet.window import Window self._background_color = Vector4f(background_color) self.clock = clock self.current_time = 0 self.prev_time = 0 # can bump down `samples` if performance is hurting config = gl.Config(depth_size=0, double_buffer=True, alpha_size=8, sample_buffers=1, samples=4, vsync=False, major_version=3, minor_version=3) display = pyglet.canvas.get_display() screen = display.get_screens()[0] self._win = Window(resizable=False, fullscreen=True, screen=screen, config=config, style='borderless', vsync=True) self._win.event(self.on_key_press) atexit.register(self._on_close) self.context = mgl.create_context(require=int('%i%i0' % (config.major_version, config.minor_version))) self.context.viewport = (0, 0, self.width, self.height) self.context.enable(mgl.BLEND) self.frame_period # do this before we've drawn anything # in principle, should be disconnected from the window # but we're saving time & mental energy self.cam = Camera(projection=height_ortho(self.width, self.height)) def on_key_press(self, symbol, modifiers): if symbol == pyglet.window.key.ESCAPE: sys.exit(1) def _on_close(self): if self._win.context: self._win.close() def flip(self): self._win.switch_to() self._win.dispatch_events() self._win.flip() self.context.clear(*self._background_color) current_time = self.clock() self.prev_time = self.current_time self.current_time = current_time return self.current_time def close(self): self._win.close() @property def dt(self): return self.current_time - self.prev_time def set_mouse_visible(self, val): self._win.set_mouse_visible(val) @property def width(self): return self._win.width @property def height(self): return self._win.height @property def background_color(self): return self._background_color @background_color.setter def background_color(self, val): if len(val) != 4: raise ValueError('Background color must be RGBA.') self._background_color.xyzw = val @property def frame_period(self): # get a whole-number version of the frame period # very coarse and fragile, should get this from the # the video mode, e.g. glfw.get_video_mode if not hasattr(self, '_frame_period'): possible = [60.0, 144.0, 240.0] # TODO: infer from machine... vals = [] for _ in range(20): self.flip() vals.append(self.dt) # chop off the first few, which are not reflective of the # "real" FPS avg = 1/(sum(vals[5:])/float(len(vals[5:]))) dff = [abs(avg - p) for p in possible] fps = [v for v, d in zip(possible, dff) if d == min(dff)] if not len(fps): self._frame_period = 1/60.0 # default else: self._frame_period = 1/fps[0] return self._frame_period
class ImageViewer(object): """A simple class for viewing images using pyglet.""" def __init__(self, caption, height, width, monitor_keyboard=False, relevant_keys=None): """ Initialize a new image viewer. Args: caption (str): the caption/title for the window height (int): the height of the window width (int): the width of the window monitor_keyboard: whether to monitor events from the keyboard relevant_keys: the relevant keys to monitor events from Returns: None """ self.caption = caption self.height = height self.width = width self.monitor_keyboard = monitor_keyboard self.relevant_keys = relevant_keys self._window = None self._pressed_keys = [] self._is_escape_pressed = False @property def is_open(self): """Return a boolean determining if this window is open.""" return self._window is not None @property def is_escape_pressed(self): """Return True if the escape key is pressed.""" return self._is_escape_pressed @property def pressed_keys(self): """Return a sorted list of the pressed keys.""" return tuple(sorted(self._pressed_keys)) def _handle_key_event(self, symbol, is_press): """ Handle a key event. Args: symbol: the symbol in the event is_press: whether the event is a press or release Returns: None """ # remap the key to the expected domain symbol = KEY_MAP.get(symbol, symbol) # check if the symbol is the escape key if symbol == key.ESCAPE: self._is_escape_pressed = is_press return # make sure the symbol is relevant if self.relevant_keys is not None and symbol not in self.relevant_keys: return # handle the press / release by appending / removing the key to pressed if is_press: self._pressed_keys.append(symbol) else: self._pressed_keys.remove(symbol) def on_key_press(self, symbol, modifiers): """Respond to a key press on the keyboard.""" self._handle_key_event(symbol, True) def on_key_release(self, symbol, modifiers): """Respond to a key release on the keyboard.""" self._handle_key_event(symbol, False) def open(self): """Open the window.""" # create a window for this image viewer instance self._window = Window( caption=self.caption, height=self.height, width=self.width, vsync=False, resizable=True, ) # add keyboard event monitors if enabled if self.monitor_keyboard: self._window.event(self.on_key_press) self._window.event(self.on_key_release) self._window.set_exclusive_keyboard() def close(self): """Close the window.""" if self.is_open: self._window.close() self._window = None def show(self, frame): """ Show an array of pixels on the window. Args: frame (numpy.ndarray): the frame to show on the window Returns: None """ # check that the frame has the correct dimensions if len(frame.shape) != 3: raise ValueError('frame should have shape with only 3 dimensions') # open the window if it isn't open already if not self.is_open: self.open() # prepare the window for the next frame self._window.clear() self._window.switch_to() self._window.dispatch_events() # create an image data object image = ImageData(frame.shape[1], frame.shape[0], 'RGB', frame.tobytes(), pitch=frame.shape[1] * -3) # send the image to the window image.blit(0, 0, width=self._window.width, height=self._window.height) self._window.flip()
class ImageViewer(object): def __init__(self, width, height, display=None): from pyglet.window import Window self.sheet = SpriteSheet() self.display = display self.window = Window(width=width * self.sheet.BLOCK_WIDTH, height=height * self.sheet.BLOCK_WIDTH, display=self.display) self.isopen = True self.init_blend() def init_blend(self): from pyglet.gl import (GL_BLEND, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glEnable) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) def render_state(self, state, x_offset=0, flip=True): import pyglet darken = pyglet.image.SolidColorImagePattern(color=(0, 0, 0, 128)) if flip: self.begin_flip() for i, entity in enumerate(state.entities): if entity is None: continue y, x = divmod(i, state.width) neighbours = [None] * 4 neighbours[1] = state[x, y - 1] neighbours[0] = state[x, y + 1] neighbours[3] = state[x - 1, y] neighbours[2] = state[x + 1, y] if state.tsu_rules: if y == 0: neighbours = [None] * 4 elif y == 1: neighbours[1] = None sprite = self.sheet.get_sprite(entity, neighbours) sprite.blit( (x + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - y) * self.sheet.BLOCK_WIDTH, ) if state.tsu_rules and y == 0: mask = darken.create_image(self.sheet.BLOCK_WIDTH + 1, self.sheet.BLOCK_WIDTH) mask.blit( (x + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - y) * self.sheet.BLOCK_WIDTH, ) for i, deal in enumerate(state.deals): for j, entity in enumerate(deal): neighbours = [None] * 4 # Deals are usually not rendered "sticky" # neighbours[2 + j] = deal[1 - j] sprite = self.sheet.get_sprite(entity, neighbours) sprite.blit( (state.width + 2 + j + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - 2 * i) * self.sheet.BLOCK_WIDTH, ) if flip: self.end_flip() def begin_flip(self): self.window.clear() self.window.switch_to() self.window.dispatch_events() def end_flip(self): self.window.flip() def save_screenshot(self, filename): from pyglet.image import get_buffer_manager get_buffer_manager().get_color_buffer().save(filename) def close(self): if self.isopen: self.window.close() self.isopen = False def __del__(self): self.close()
class Renderer: def __init__(self, client, map_size, minimap_size): self._client = client self._window = None self._map_size = map_size self._map_image = None self._minimap_size = minimap_size self._minimap_image = None self._mouse_x, self._mouse_y = None, None self._text_supply = None self._text_vespene = None self._text_minerals = None self._text_score = None self._text_time = None async def render(self, observation): render_data = observation.observation.render_data map_size = render_data.map.size map_data = render_data.map.data minimap_size = render_data.minimap.size minimap_data = render_data.minimap.data map_width, map_height = map_size.x, map_size.y map_pitch = -map_width * 3 minimap_width, minimap_height = minimap_size.x, minimap_size.y minimap_pitch = -minimap_width * 3 if not self._window: # pylint: disable=C0415 from pyglet.image import ImageData from pyglet.text import Label from pyglet.window import Window self._window = Window(width=map_width, height=map_height) self._window.on_mouse_press = self._on_mouse_press self._window.on_mouse_release = self._on_mouse_release self._window.on_mouse_drag = self._on_mouse_drag self._map_image = ImageData(map_width, map_height, "RGB", map_data, map_pitch) self._minimap_image = ImageData(minimap_width, minimap_height, "RGB", minimap_data, minimap_pitch) self._text_supply = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 10, y=self._map_size[1] - 10, color=(200, 200, 200, 255), ) self._text_vespene = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 130, y=self._map_size[1] - 10, color=(28, 160, 16, 255), ) self._text_minerals = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 200, y=self._map_size[1] - 10, color=(68, 140, 255, 255), ) self._text_score = Label( "", font_name="Arial", font_size=16, anchor_x="left", anchor_y="top", x=10, y=self._map_size[1] - 10, color=(219, 30, 30, 255), ) self._text_time = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="bottom", x=self._minimap_size[0] - 10, y=self._minimap_size[1] + 10, color=(255, 255, 255, 255), ) else: self._map_image.set_data("RGB", map_pitch, map_data) self._minimap_image.set_data("RGB", minimap_pitch, minimap_data) self._text_time.text = str( datetime.timedelta( seconds=(observation.observation.game_loop * 0.725) // 16)) if observation.observation.HasField("player_common"): self._text_supply.text = f"{observation.observation.player_common.food_used} / {observation.observation.player_common.food_cap}" self._text_vespene.text = str( observation.observation.player_common.vespene) self._text_minerals.text = str( observation.observation.player_common.minerals) if observation.observation.HasField("score"): # pylint: disable=W0212 self._text_score.text = f"{score_pb._SCORE_SCORETYPE.values_by_number[observation.observation.score.score_type].name} score: {observation.observation.score.score}" await self._update_window() if self._client.in_game and (not observation.player_result ) and self._mouse_x and self._mouse_y: await self._client.move_camera_spatial( Point2((self._mouse_x, self._minimap_size[0] - self._mouse_y))) self._mouse_x, self._mouse_y = None, None async def _update_window(self): self._window.switch_to() self._window.dispatch_events() self._window.clear() self._map_image.blit(0, 0) self._minimap_image.blit(0, 0) self._text_time.draw() self._text_score.draw() self._text_minerals.draw() self._text_vespene.draw() self._text_supply.draw() self._window.flip() def _on_mouse_press(self, x, y, button, _modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_release(self, x, y, button, _modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_drag(self, x, y, _dx, _dy, buttons, _modifiers): if not buttons & 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y