def on_activate(self): super().on_activate() if not self.document: self.document = FormattedDocument(text=self.license_text) self.document.set_style( 0, len(self.document.text), { 'font_name': 'Arial', 'font_size': get_bottom_bar_height(self.screen_resolution) // 5, 'bold': False, 'italic': False, 'color': (*WHITE_RGB, self.opacity), 'align': 'center' }) if not self.license_layout: self.license_layout = IncrementalTextLayout( document=self.document, width=self.viewport.x2 - self.viewport.x1, height=self.viewport.y2 - self.viewport.y1, multiline=True, batch=BATCHES['ui_batch'], group=GROUPS['button_text']) self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1
def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap=True, id=None, **kwargs): """ An editable text box. When clicked, it has the focus and can receive keyboard events. With wrap=True, several lines of text will wrap around the width. Optional parameters can include fill, font, fontsize, fontweight. """ txt = Text(value or " ", **{ "fill" : _popdefault(kwargs, "fill", Color(0,0.9)), "font" : _popdefault(kwargs, "font", theme["fontname"]), "fontsize" : _popdefault(kwargs, "fontsize", theme["fontsize"]), "fontweight" : _popdefault(kwargs, "fontweight", theme["fontweight"]), "lineheight" : _popdefault(kwargs, "lineheight", 1), "align" : LEFT }) kwargs["width"] = width kwargs["height"] = height Control.__init__(self, x=x, y=y, id=id, **kwargs) self.reserved = kwargs.get("reserved", [ENTER, TAB]) self._padding = padding self._i = 0 # Index of character on which the mouse is pressed. self._empty = value == "" and True or False self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap) self._editor.content_valign = wrap and "top" or "center" self._editor.selection_background_color = (170, 200, 230, 255) self._editor.selection_color = txt._label.color self._editor.caret = Caret(self._editor) self._editor.caret.visible = False self._editing = False # When True, cursor is blinking and text can be edited. Editable._pack(self) # On init, call Editable._pack(), not the derived Field._pack().
def __init__(self): win_width, win_height = get_size() self.batch = Batch() self._doc = pyglet.text.document.UnformattedDocument('') self._doc.set_style(0, len(self._doc.text), dict(color=(255, 255, 255, 255))) font = self._doc.get_font() self.text_height = font.ascent - font.descent self.pad = 2 self._outline = Rectangle(5, 5 + self.pad, get_size()[0] - self.pad - 10, self.text_height + self.pad, color=(0, 0, 0)) self._outline.opacity = 150 self._layout = IncrementalTextLayout(self._doc, get_size()[0] - 14, self.text_height, multiline=False, batch=self.batch) self._caret = Caret(self._layout, color=(255, 255, 255)) self._caret.visible = False self._layout.x = 5 self._layout.y = 5 + self.pad self._focus = False self._press = False self.last_press = [0, 0] super().__init__(5, 5 + self.pad, get_size()[0] - self.pad - 10, self.text_height + self.pad)
def __init__(self, text, color, x, y, width, pad=3): win_width, win_height = get_size() self.batch = Batch() self._doc = pyglet.text.document.UnformattedDocument(text) self._doc.set_style(0, len(self._doc.text), dict(color=(255, 255, 255, 255))) font = self._doc.get_font() self.text_height = font.ascent - font.descent self.pad = pad self._outline = BorderedRectangle(x - self.pad, win_height - y - self.pad, width + self.pad, self.text_height + self.pad, color=color[:3], border_color=(100, 100, 100)) self._outline.opacity = color[-1] self._layout = IncrementalTextLayout(width, self.text_height, multiline=False, batch=self.batch) self._caret = Caret(self._layout, color=(255, 255, 255)) self._caret.visible = False self._layout.x = x self._layout.y = win_height - y self._focus = False self._press = False super().__init__(x, win_height - y, width, height)
def init_bar(self, weapons): try: if self.ammolayout._document: self.ammolayout.delete() for tri in self.tris: tri.remove() except AttributeError: pass ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems() if key != 'w0') self.ammos = ammotext.split('\t') self.ammodoc = FormattedDocument(ammotext) self.ammodoc.set_style(0, len(ammotext), dict(color=[255]*4, tab_stops=[120*(i+1) for i in range(6)], font_size=24, align='center', wrap=False)) self.ammolayout = IncrementalTextLayout(self.ammodoc, width=600, height=50, batch=self.batch, multiline=True) self.ammolayout.x = (1280 / 2) * self.scale.x self.ammolayout.y = 20 * self.scale.y self.ammolayout.anchor_x = 'center' self.ammolayout.anchor_y = 'bottom' w = self.ammolayout.content_width colorlist = [weaponcolors[key] for key in weapons if key != 'w0'] self.tris = [Triangle(640*self.scale.x-w/2-52+120*i, 35*self.scale.y, 50, 50, col, self.batch, 0, 0) for i, col in enumerate(colorlist)]
def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0, 0), wrap=True, id=None, **kwargs): """ An editable text box. When clicked, it has the focus and can receive keyboard events. With wrap=True, several lines of text will wrap around the width. Optional parameters can include fill, font, fontsize, fontweight. """ txt = Text( value or " ", **{ "fill": _popdefault(kwargs, "fill", Color(0, 0.9)), "font": _popdefault(kwargs, "font", theme["fontname"]), "fontsize": _popdefault(kwargs, "fontsize", theme["fontsize"]), "fontweight": _popdefault(kwargs, "fontweight", theme["fontweight"]), "lineheight": _popdefault(kwargs, "lineheight", 1), "align": LEFT, } ) kwargs["width"] = width kwargs["height"] = height Control.__init__(self, x=x, y=y, id=id, **kwargs) self.reserved = kwargs.get("reserved", [ENTER, TAB]) self._padding = padding self._i = 0 # Index of character on which the mouse is pressed. self._empty = value == "" and True or False self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap) self._editor.content_valign = wrap and "top" or "center" self._editor.selection_background_color = (170, 200, 230, 255) self._editor.selection_color = txt._label.color self._editor.caret = Caret(self._editor) self._editor.caret.visible = False self._editing = False # When True, cursor is blinking and text can be edited. Editable._pack(self) # On init, call Editable._pack(), not the derived Field._pack().
def __init__(self, text, color, x, y, width): win_width, win_height = get_size() self.batch = Batch() self._doc = pyglet.text.document.UnformattedDocument(text) self._doc.set_style( 0, len(self._doc.text), dict(color=(255, 255, 255, 255), font_name='minecraftia')) font = self._doc.get_font() height = font.ascent - font.descent pad = 2 self._outline = Rectangle(x - pad, y - pad, width + pad, height + pad, color=color[:3]) self._outline.opacity = color[-1] self._layout = IncrementalTextLayout(self._doc, width, height, multiline=False, batch=self.batch) self._caret = Caret(self._layout, color=(255, 255, 255)) self._caret.visible = False self._layout.x = x self._layout.y = y self._focus = False self._press = False super().__init__(x, y, width, height) self.last_char = ''
def __init__(self, batch, groups, on_click, on_enter, on_motion, on_search): # create document self.document = FormattedDocument(' ') self.document.set_style( 0, 1, dict(font_name=FONT_NAME, font_size=FONT_SIZE, color=FONT_COLOR)) # calculate font height and margin font = self.document.get_font(0) self.font_height = font.ascent - font.descent self.margin = self.font_height * TEXT_INPUT_MARGIN # create text input self.input = IncrementalTextLayout(self.document, 100, self.font_height, batch=batch, group=groups[1]) self.input.x = 100 self.input.y = 100 # creating a caret and push it to window handlers self.caret = Caret(self.input, FONT_COLOR[:3], on_click, on_enter, on_motion, on_search) self.clear_text() # create background rectangle self.rect = Rectangle(0, 0, 100, self.font_height + 2 * self.margin, color=TEXT_INPUT_COLOR, batch=batch, group=groups[0])
def __init__(self, width: int, height: int = 0, multiline: bool = False, dpi: object = None, batch: Batch = None, group: Group = None, wrap_lines: bool = True, x: int = 0, y: int = 0, underlined: bool = True, caret_color: tuple = (0, 0, 0), numbers_only: bool = False, font_name=None, font_size=None, font_color=(255, 255, 255, 2555), max_chars=0) -> None: self.document = FormattedDocument() self.layout = IncrementalTextLayout(self.document, width, height, multiline, dpi, batch, group, wrap_lines) self.numbers_only = numbers_only self.style['color'] = font_color self.max_chars = max_chars if font_name: self.style['font_name'] = font_name if font_size: self.style['font_size'] = font_size self.reset_style() if not height: # If the dev didn't specify a height, make the height equal to the height of the font font = pyglet.font.load( font_name or self.document.get_style('font'), font_size or self.document.get_style('font_size')) self.height = font.ascent - font.descent self._hover_cursor = self.get_window().CURSOR_TEXT super().__init__(self.layout, color=caret_color) # TODO: Allow the dev to specify how x and y are treated self.x = x - self.width // 2 self.y = y - self.height // 2 if underlined: self.underline = Rectangle( x=self.x, y=self.y, width=self.width, height=1, )
def __init__(self, *args, **kwargs): super(TestWindow, self).__init__(*args, **kwargs) self.batch = pyglet.graphics.Batch() self.document = pyglet.text.decode_attributed(doctext) for i in range(0, len(doctext), 300): self.document.insert_element(i, TestElement(60, -10, 70)) self.margin = 2 self.layout = IncrementalTextLayout(self.document, self.width - self.margin * 2, self.height - self.margin * 2, multiline=True, batch=self.batch) self.caret = caret.Caret(self.layout) self.push_handlers(self.caret) self.set_mouse_cursor(self.get_system_mouse_cursor('text'))
class TestWindow(pyglet.window.Window): def __init__(self, *args, **kwargs): super(TestWindow, self).__init__(*args, **kwargs) self.batch = pyglet.graphics.Batch() self.document = pyglet.text.decode_attributed(doctext) for i in range(0, len(doctext), 300): self.document.insert_element(i, TestElement(60, -10, 70)) self.margin = 2 self.layout = IncrementalTextLayout(self.document, self.width - self.margin * 2, self.height - self.margin * 2, multiline=True, batch=self.batch) self.caret = caret.Caret(self.layout) self.push_handlers(self.caret) self.set_mouse_cursor(self.get_system_mouse_cursor('text')) def on_resize(self, width, height): super(TestWindow, self).on_resize(width, height) self.layout.begin_update() self.layout.x = self.margin self.layout.y = self.margin self.layout.width = width - self.margin * 2 self.layout.height = height - self.margin * 2 self.layout.end_update() def on_mouse_scroll(self, x, y, scroll_x, scroll_y): self.layout.view_x -= scroll_x self.layout.view_y += scroll_y * 16 def on_draw(self): pyglet.gl.glClearColor(0, 0, 0, 1) self.clear() self.batch.draw() def on_key_press(self, symbol, modifiers): super(TestWindow, self).on_key_press(symbol, modifiers) if symbol == pyglet.window.key.TAB: self.caret.on_text('\t')
def __init__(self, text, x, y, width, color=(255, 255, 255, 255), batch=None, group=None): self._doc = pyglet.text.document.UnformattedDocument(text) self._doc.set_style(0, len(self._doc.text), dict(color=(0, 0, 0, 255))) font = self._doc.get_font() height = font.ascent - font.descent self._user_group = group bg_group = OrderedGroup(0, parent=group) fg_group = OrderedGroup(1, parent=group) # Rectangular outline: pad = 2 x1 = x - pad y1 = y - pad x2 = x + width + pad y2 = y + height + pad self._outline = batch.add(4, pyglet.gl.GL_QUADS, bg_group, ('v2i', [x1, y1, x2, y1, x2, y2, x1, y2]), ('c4B', color * 4)) # Text and Caret: self._layout = IncrementalTextLayout(self._doc, width, height, multiline=False, batch=batch, group=fg_group) self._caret = Caret(self._layout) self._caret.visible = False self._layout.x = x self._layout.y = y self._focus = False super().__init__(x, y, width, height)
def __init__(self, text, x, y, width, color=(255, 255, 255, 255), batch=None, group=None): self._doc = pyglet.text.document.UnformattedDocument(text) self._doc.set_style(0, len(self._doc.text), dict(color=(0, 0, 0, 255))) font = self._doc.get_font() height = font.ascent - font.descent self._user_group = group bg_group = Group(order=0, parent=group) fg_group = Group(order=1, parent=group) # Rectangular outline with 2-pixel pad: p = 2 self._outline = pyglet.shapes.Rectangle(x - p, y - p, width + p + p, height + p + p, color[:3], batch, bg_group) self._outline.opacity = color[3] # Text and Caret: self._layout = IncrementalTextLayout(self._doc, width, height, multiline=False, batch=batch, group=fg_group) self._layout.x = x self._layout.y = y self._caret = Caret(self._layout) self._caret.visible = False self._focus = False super().__init__(x, y, width, height)
class LicensePageV2(UIObject, ABC): def __init__(self, logger, parent_viewport): super().__init__(logger, parent_viewport) self.license_text = '' self.document = None self.license_layout = None @final def on_activate(self): super().on_activate() if not self.document: self.document = FormattedDocument(text=self.license_text) self.document.set_style( 0, len(self.document.text), { 'font_name': 'Arial', 'font_size': get_bottom_bar_height(self.screen_resolution) // 5, 'bold': False, 'italic': False, 'color': (*WHITE_RGB, self.opacity), 'align': 'center' }) if not self.license_layout: self.license_layout = IncrementalTextLayout( document=self.document, width=self.viewport.x2 - self.viewport.x1, height=self.viewport.y2 - self.viewport.y1, multiline=True, batch=BATCHES['ui_batch'], group=GROUPS['button_text']) self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 @final @window_size_has_changed def on_window_resize(self, width, height): super().on_window_resize(width, height) self.viewport.x1, self.viewport.x2 = self.parent_viewport.x1, self.parent_viewport.x2 self.viewport.y1 = self.parent_viewport.y1 + get_bottom_bar_height( self.screen_resolution) self.viewport.y2 = self.parent_viewport.y2 if self.is_activated: self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 self.license_layout.width = self.viewport.x2 - self.viewport.x1 self.license_layout.height = self.viewport.y2 - self.viewport.y1 self.document.set_style(0, len(self.document.text), { 'font_size': get_bottom_bar_height(self.screen_resolution) // 5 }) @final @is_active @cursor_is_inside_the_text_box def on_mouse_scroll(self, x, y, scroll_x, scroll_y): self.license_layout.view_y += scroll_y * self.document.get_style( 'font_size') @final def on_update_opacity(self, new_opacity): super().on_update_opacity(new_opacity) if self.opacity <= 0: self.license_layout.delete() self.license_layout = None elif self.document: self.document.set_style(0, len(self.document.text), {'color': (*WHITE_RGB, self.opacity)})
class Editable(Control): def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0, 0), wrap=True, id=None, **kwargs): """ An editable text box. When clicked, it has the focus and can receive keyboard events. With wrap=True, several lines of text will wrap around the width. Optional parameters can include fill, font, fontsize, fontweight. """ txt = Text( value or " ", **{ "fill": _popdefault(kwargs, "fill", Color(0, 0.9)), "font": _popdefault(kwargs, "font", theme["fontname"]), "fontsize": _popdefault(kwargs, "fontsize", theme["fontsize"]), "fontweight": _popdefault(kwargs, "fontweight", theme["fontweight"]), "lineheight": _popdefault(kwargs, "lineheight", 1), "align": LEFT, } ) kwargs["width"] = width kwargs["height"] = height Control.__init__(self, x=x, y=y, id=id, **kwargs) self.reserved = kwargs.get("reserved", [ENTER, TAB]) self._padding = padding self._i = 0 # Index of character on which the mouse is pressed. self._empty = value == "" and True or False self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap) self._editor.content_valign = wrap and "top" or "center" self._editor.selection_background_color = (170, 200, 230, 255) self._editor.selection_color = txt._label.color self._editor.caret = Caret(self._editor) self._editor.caret.visible = False self._editing = False # When True, cursor is blinking and text can be edited. Editable._pack(self) # On init, call Editable._pack(), not the derived Field._pack(). def _pack(self): self._editor.x = self._padding[0] self._editor.y = self._padding[1] self._editor.width = max(0, self.width - self._padding[0] * 2) self._editor.height = max(0, self.height - self._padding[1] * 2) def _get_value(self): # IncrementalTextLayout in Pyglet 1.1.4 has a bug with empty strings. # We keep track of empty strings with Editable._empty to avoid this. return not self._empty and self._editor.document.text or u"" def _set_value(self, string): self._editor.begin_update() self._editor.document.text = string or " " self._editor.end_update() self._empty = string == "" and True or False value = property(_get_value, _set_value) def _get_editing(self): return self._editing def _set_editing(self, b): self._editing = b self._editor.caret.visible = b global EDITING if b is False and EDITING == self: EDITING = None if b is True: EDITING = self # Cursor is blinking and text can be edited. # Visit all layers on the canvas. # Remove the caret from all other Editable controls. for layer in self.root.canvas and self.root.canvas.layers or []: layer.traverse( visit=lambda layer: isinstance(layer, Editable) and layer != self and setattr(layer, "editing", False) ) editing = property(_get_editing, _set_editing) @property def selection(self): # Yields a (start, stop)-tuple with the indices of the current selected text. return (self._editor.selection_start, self._editor.selection_end) @property def selected(self): # Yields True when text is currently selected. return self.selection[0] != self.selection[1] @property def cursor(self): # Yields the index at the text cursor (caret). return self._editor.caret.position def index(self, x, y): """ Returns the index of the character in the text at position x, y. """ x0, y0 = self.absolute_position() i = self._editor.get_position_from_point(x - x0, y - y0) if self._editor.get_point_from_position(0)[0] > x - x0: # Pyglet bug? i = 0 if self._empty: i = 0 return i def on_mouse_enter(self, mouse): mouse.cursor = TEXT def on_mouse_press(self, mouse): i = self._i = self.index(mouse.x, mouse.y) self._editor.set_selection(0, 0) self.editing = True self._editor.caret.position = i Control.on_mouse_press(self, mouse) def on_mouse_release(self, mouse): if not self.dragged: self._editor.caret.position = self.index(mouse.x, mouse.y) Control.on_mouse_release(self, mouse) def on_mouse_drag(self, mouse): i = self.index(mouse.x, mouse.y) self._editor.selection_start = max(min(self._i, i), 0) self._editor.selection_end = min(max(self._i, i), len(self.value)) self._editor.caret.visible = False Control.on_mouse_drag(self, mouse) def on_mouse_doubleclick(self, mouse): # Select the word at the mouse position. # Words are delimited by non-alphanumeric characters. i = self.index(mouse.x, mouse.y) delimiter = lambda ch: not (ch.isalpha() or ch.isdigit()) if i < len(self.value) and delimiter(self.value[i]): self._editor.set_selection(i, i + 1) if i == len(self.value) and self.value != "" and delimiter(self.value[i - 1]): self._editor.set_selection(i - 1, i) a = _find(lambda (i, ch): delimiter(ch), enumerate(reversed(self.value[:i]))) b = _find(lambda (i, ch): delimiter(ch), enumerate(self.value[i:])) a = a and i - a[0] or 0 b = b and i + b[0] or len(self.value) self._editor.set_selection(a, b) def on_key_press(self, keys): if self._editing: self._editor.caret.visible = True i = self._editor.caret.position if keys.code == LEFT: # The left arrow moves the text cursor to the left. self._editor.caret.position = max(i - 1, 0) elif keys.code == RIGHT: # The right arrow moves the text cursor to the right. self._editor.caret.position = min(i + 1, len(self.value)) elif keys.code in (UP, DOWN): # The up arrows moves the text cursor to the previous line. # The down arrows moves the text cursor to the next line. y = keys.code == UP and -1 or +1 n = self._editor.get_line_count() i = self._editor.get_position_on_line( max(self._editor.get_line_from_position(i) + y, 0), self._editor.get_point_from_position(i)[0] ) self._editor.caret.position = i elif keys.code == TAB and TAB in self.reserved: # The tab key navigates away from the control. self._editor.caret.position = 0 self.editing = False elif keys.code == ENTER and ENTER in self.reserved: # The enter key executes on_action() and navigates away from the control. self._editor.caret.position = 0 self.editing = False self.on_action() elif keys.code == BACKSPACE and self.selected: # The backspace key removes the current text selection. self.value = self.value[: self.selection[0]] + self.value[self.selection[1] :] self._editor.caret.position = max(self.selection[0], 0) elif keys.code == BACKSPACE and i > 0: # The backspace key removes the character at the text cursor. self.value = self.value[: i - 1] + self.value[i:] self._editor.caret.position = max(i - 1, 0) elif keys.char: if self.selected: # Typing replaces any text currently selected. self.value = self.value[: self.selection[0]] + self.value[self.selection[1] :] self._editor.caret.position = i = max(self.selection[0], 0) ch = keys.char ch = ch.replace("\r", "\n\r") self.value = self.value[:i] + ch + self.value[i:] self._editor.caret.position = min(i + 1, len(self.value)) self._editor.set_selection(0, 0) def draw(self): self._editor.draw()
def __init__(self, *, highscores, ui_batch, cb_start_game=None, cb_add_highscore=None, add_score=None): super().__init__() # Make sure we can handle events self.event_handlers = [self] # Store callbacks, the ui batch and our optional score3 self.cb_start_game = cb_start_game self.cb_add_highscore = cb_add_highscore self.ui_batch = ui_batch self.add_score = add_score # We need to keep track of our children so we can remove them in self.delete() self.children = [] # Show title self.children.append( Label('WELCOME TO', font_name='m5x7', font_size=128, x=WIDTH / 2, y=HEIGHT - 16, anchor_x='center', anchor_y='top', batch=self.ui_batch)) self.children.append( Label('HELL', font_name='m5x7', font_size=512, x=WIDTH / 2 + 50, y=HEIGHT, anchor_x='center', anchor_y='top', batch=self.ui_batch)) # If we need to add a score if add_score is not None: # Make sure that self.continue_label exists so we don't crash in self.tick() self.continue_label = None # Show some text self.children.append( Label('Your score was:', font_name='m5x7', font_size=48, x=WIDTH / 2, y=400, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch)) self.children.append( Label(f'{add_score}', font_name='m5x7', font_size=128, x=WIDTH / 2, y=280, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch)) self.children.append( Label('Enter name for highscore:', font_name='m5x7', font_size=32, x=WIDTH / 2, y=200, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch)) # Prepare a document with styling self.document = UnformattedDocument() self.document.set_style( 0, 1, { 'font_name': 'm5x7', 'font_size': 64, 'color': (255, 255, 255, 255), 'align': 'center' }) # Find the height of the font font = self.document.get_font() height = font.ascent - font.descent # Make a TextLayout that handles dynamically adding text # Make it multiline even though we don't want multiple lines because otherwise align=center doesn't work self.layout = IncrementalTextLayout(self.document, WIDTH / 3, height, multiline=True, batch=self.ui_batch) self.layout.anchor_y = 'top' self.layout.anchor_x = 'center' self.layout.x = WIDTH / 2 self.layout.y = 200 # Add a carat (cursor) self.caret = Caret(self.layout, batch=self.ui_batch, color=(255, 255, 255)) # Type q and then backspace # This ensures that the carat is visible as it only shows up after something has been typed self.caret.on_text('q') self.caret.on_text_motion(key.MOTION_BACKSPACE) # Make sure we can delete layout and carat in self.delete() self.children.append(self.layout) self.children.append(self.caret) else: # If we have some highscores to show if highscores: # Show a title self.children.append( Label('Highscores:', font_name='m5x7', font_size=48, x=WIDTH / 2, y=420, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch)) # ... followed by each highscore for i, highscore in enumerate(highscores): self.children.append( Label(f'{highscore.name} - {highscore.score}', font_name='m5x7', font_size=32, x=WIDTH / 2, y=380 - i * 32, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch)) # Show continue label, and make sure to have it below highscores if any self.continue_label = Label('Press SPACE to start game...', font_name='m5x7', font_size=48, x=WIDTH / 2, y=32 if highscores else HEIGHT / 4, align='center', anchor_x='center', anchor_y='bottom', batch=self.ui_batch) # Timer for blinking self.continue_timer = 0 self.children.append(self.continue_label)
class WeaponBar(object): """docstring for WeaponBar""" def __init__(self, batch, scale): super(WeaponBar, self).__init__() self.batch = batch self.weapons = {} self.ammos = [] self.tris = [] self.scale = scale def __len__(self): return len(self.weapons) def init_bar(self, weapons): try: if self.ammolayout._document: self.ammolayout.delete() for tri in self.tris: tri.remove() except AttributeError: pass ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems() if key != 'w0') self.ammos = ammotext.split('\t') self.ammodoc = FormattedDocument(ammotext) self.ammodoc.set_style(0, len(ammotext), dict(color=[255]*4, tab_stops=[120*(i+1) for i in range(6)], font_size=24, align='center', wrap=False)) self.ammolayout = IncrementalTextLayout(self.ammodoc, width=600, height=50, batch=self.batch, multiline=True) self.ammolayout.x = (1280 / 2) * self.scale.x self.ammolayout.y = 20 * self.scale.y self.ammolayout.anchor_x = 'center' self.ammolayout.anchor_y = 'bottom' w = self.ammolayout.content_width colorlist = [weaponcolors[key] for key in weapons if key != 'w0'] self.tris = [Triangle(640*self.scale.x-w/2-52+120*i, 35*self.scale.y, 50, 50, col, self.batch, 0, 0) for i, col in enumerate(colorlist)] def update(self, weapons): if len(weapons) != len(self.weapons): self.init_bar(weapons) self.weapons = weapons.copy() else: ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems() if key != 'w0') ammos = ammotext.split('\t') self.ammolayout.begin_update() for i, a in enumerate(ammos): if a != self.ammos[i]: ln = sum(len(self.ammos[j]) for j in range(i)) + i self.ammodoc.delete_text(ln, ln + len(self.ammos[i])) self.ammodoc.insert_text(ln, a) self.ammolayout.end_update() self.ammos = ammos def remove(self): try: self.weapons = {} self.ammolayout.delete() for tri in self.tris: tri.remove() except AttributeError: pass
def __init__(self, window, x=0, y=0, width=100, height=100, anchor_x='left', anchor_y='bottom', style = Default['terminal'], prompt = '> ', banner = ''): '''Create a new console. :Parameters: `window` : pyglet.window.Window Window this console will be embedded in. `x` : int X coordinate of the console. `y` : int Y coordinate of the console. `width` : int Width of the console in pixels, or None `height` : int Height of the console in pixels, or None `anchor_x` : str Anchor point of the X coordinate: one of ``"left"``, ``"center"`` or ``"right"``. `anchor_y` : str Anchor point of the Y coordinate: one of ``"bottom"``, ``"center"`` or ``"top"``. `style` : dict Style dictionnary describing element styles `prompt` : str Console prompt `banner` : str Text to be displayed prior to any input. ''' super(Console, self).__init__() self._window = window self._style = style self._prompt = prompt self._prompt_start, self._prompt_end = 0, 0 batch = pyglet.graphics.Batch() document = Document() margin = self._style['margin'] layout = Layout(document, width=width-2*margin, height=height-2*margin, multiline=True, batch=batch) layout.anchor_x = anchor_x layout.anchor_y = anchor_y layout.x = int(margin) layout.y = int(margin) layout.view_y = 0 layout.selection_color = self._style['selection_fg'] layout.selection_background_color = self._style['selection_bg'] caret = Caret(layout) caret.position = 0 caret.visible = True r,g,b,a = self._style['text_fg'] caret.color = (r,g,b) self._batch = batch self._document = document self._layout = layout self._caret = caret x,y,z = int(layout.x-margin), int(layout.y-margin), -.5 w,h = layout.width+2*margin, layout.height+2*margin self._background = batch.add( 4, pyglet.gl.GL_QUADS, None, ('v3f', (x,y,z, x+w,y,z, x+w,y+h,z, x,y+h,z)), ('c4B', self._style['text_bg']*4)) z += .1 self._border = batch.add( 4, pyglet.gl.GL_LINE_LOOP, None, ('v3f', (x,y,z, x+w,y,z, x+w,y+h,z, x,y+h,z)), ('c4B', self._style['border_fg']*4)) if banner: self.write(banner) if window: self._cursor = window.get_system_mouse_cursor('text') else: self._cursor = None self.resize(width,height)
def __init__(self, text, x, y, width, color=(255, 255, 255, 255), text_color=(0, 0, 0, 255), caret_color=(0, 0, 0), batch=None, group=None): """Create a text entry widget. :Parameters: `text` : str Initial text to display. `x` : int X coordinate of the text entry widget. `y` : int Y coordinate of the text entry widget. `width` : int The width of the text entry widget. `color` : (int, int, int, int) The color of the outline box in RGBA format. `text_color` : (int, int, int, int) The color of the text in RGBA format. `text_color` : (int, int, int) The color of the caret in RGB format. `batch` : `~pyglet.graphics.Batch` Optional batch to add the text entry widget to. `group` : `~pyglet.graphics.Group` Optional parent group of text entry widget. """ self._doc = pyglet.text.document.UnformattedDocument(text) self._doc.set_style(0, len(self._doc.text), dict(color=text_color)) font = self._doc.get_font() height = font.ascent - font.descent self._user_group = group bg_group = Group(order=0, parent=group) fg_group = Group(order=1, parent=group) # Rectangular outline with 2-pixel pad: self._pad = p = 2 self._outline = pyglet.shapes.Rectangle(x - p, y - p, width + p + p, height + p + p, color[:3], batch, bg_group) self._outline.opacity = color[3] # Text and Caret: self._layout = IncrementalTextLayout(self._doc, width, height, multiline=False, batch=batch, group=fg_group) self._layout.x = x self._layout.y = y self._caret = Caret(self._layout, color=caret_color) self._caret.visible = False self._focus = False super().__init__(x, y, width, height)
class TextBox(Focusable, Caret, Hoverable): underline: Rectangle = None _on_enter: Callable = None ignore_enter: bool = False style: dict = {} def __init__(self, width: int, height: int = 0, multiline: bool = False, dpi: object = None, batch: Batch = None, group: Group = None, wrap_lines: bool = True, x: int = 0, y: int = 0, underlined: bool = True, caret_color: tuple = (0, 0, 0), numbers_only: bool = False, font_name=None, font_size=None, font_color=(255, 255, 255, 2555), max_chars=0) -> None: self.document = FormattedDocument() self.layout = IncrementalTextLayout(self.document, width, height, multiline, dpi, batch, group, wrap_lines) self.numbers_only = numbers_only self.style['color'] = font_color self.max_chars = max_chars if font_name: self.style['font_name'] = font_name if font_size: self.style['font_size'] = font_size self.reset_style() if not height: # If the dev didn't specify a height, make the height equal to the height of the font font = pyglet.font.load( font_name or self.document.get_style('font'), font_size or self.document.get_style('font_size')) self.height = font.ascent - font.descent self._hover_cursor = self.get_window().CURSOR_TEXT super().__init__(self.layout, color=caret_color) # TODO: Allow the dev to specify how x and y are treated self.x = x - self.width // 2 self.y = y - self.height // 2 if underlined: self.underline = Rectangle( x=self.x, y=self.y, width=self.width, height=1, ) def reset_style(self): self.document.set_style(0, len(self.document.text), self.style) @property def x(self): return self.layout.x @x.setter def x(self, value): if self.underline: self.underline.x = value self.layout.x = value @property def y(self): return self.layout.y @y.setter def y(self, value): print(value) if self.underline: self.underline.y = value self.layout.y = value @property def width(self): return self.layout.width @width.setter def width(self, value): if self.underline: self.underline.width = value self.layout.width = value @property def height(self): return self.layout.height @height.setter def height(self, value): print(value) self.layout.height = value def draw(self): if self.focused: self.on_activate() else: self.on_deactivate() self.layout.draw() if self.underline: self.underline.draw() def on_text(self, text: str): # Only type inside when the user is focused on the textbox # print(text) if not self.focused: return if ord(text) == 13: if self.ignore_enter: # Enter self.ignore_enter = False return else: return self.on_enter() # if self.max_chars and len(self.value) >= self.max_chars: # return # if self.numbers_only and not text.isnumeric(): # return res = super().on_text(text) print('res', res, 'text', text) self.reset_style() return res def _on_enter_base(self) -> None: """ The event handler that will be called by default if none are defined """ pass @property def value(self): return self.document.text @value.setter def value(self, val): self.document.text = val self.reset_style() @property def on_enter(self): if self._on_enter: return self._on_enter return self._on_enter_base @on_enter.setter def on_enter(self, func): def new_on_enter(): if self.focused: func() self._on_enter = new_on_enter
class Editable(Control): def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap=True, id=None, **kwargs): """ An editable text box. When clicked, it has the focus and can receive keyboard events. With wrap=True, several lines of text will wrap around the width. Optional parameters can include fill, font, fontsize, fontweight. """ txt = Text(value or " ", **{ "fill" : _popdefault(kwargs, "fill", Color(0,0.9)), "font" : _popdefault(kwargs, "font", theme["fontname"]), "fontsize" : _popdefault(kwargs, "fontsize", theme["fontsize"]), "fontweight" : _popdefault(kwargs, "fontweight", theme["fontweight"]), "lineheight" : _popdefault(kwargs, "lineheight", 1), "align" : LEFT }) kwargs["width"] = width kwargs["height"] = height Control.__init__(self, x=x, y=y, id=id, **kwargs) self.reserved = kwargs.get("reserved", [ENTER, TAB]) self._padding = padding self._i = 0 # Index of character on which the mouse is pressed. self._empty = value == "" and True or False self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap) self._editor.content_valign = wrap and "top" or "center" self._editor.selection_background_color = (170, 200, 230, 255) self._editor.selection_color = txt._label.color self._editor.caret = Caret(self._editor) self._editor.caret.visible = False self._editing = False # When True, cursor is blinking and text can be edited. Editable._pack(self) # On init, call Editable._pack(), not the derived Field._pack(). def _pack(self): self._editor.x = self._padding[0] self._editor.y = self._padding[1] self._editor.width = max(0, self.width - self._padding[0] * 2) self._editor.height = max(0, self.height - self._padding[1] * 2) def _get_value(self): # IncrementalTextLayout in Pyglet 1.1.4 has a bug with empty strings. # We keep track of empty strings with Editable._empty to avoid this. return not self._empty and self._editor.document.text or u"" def _set_value(self, string): self._editor.begin_update() self._editor.document.text = string or " " self._editor.end_update() self._empty = string == "" and True or False value = property(_get_value, _set_value) def _get_editing(self): return self._editing def _set_editing(self, b): self._editing = b self._editor.caret.visible = b global EDITING if b is False and EDITING == self: EDITING = None if b is True: EDITING = self # Cursor is blinking and text can be edited. # Visit all layers on the canvas. # Remove the caret from all other Editable controls. for layer in (self.root.canvas and self.root.canvas.layers or []): layer.traverse(visit=lambda layer: \ isinstance(layer, Editable) and layer != self and \ setattr(layer, "editing", False)) editing = property(_get_editing, _set_editing) @property def selection(self): # Yields a (start, stop)-tuple with the indices of the current selected text. return (self._editor.selection_start, self._editor.selection_end) @property def selected(self): # Yields True when text is currently selected. return self.selection[0] != self.selection[1] @property def cursor(self): # Yields the index at the text cursor (caret). return self._editor.caret.position def index(self, x, y): """ Returns the index of the character in the text at position x, y. """ x0, y0 = self.absolute_position() i = self._editor.get_position_from_point(x-x0, y-y0) if self._editor.get_point_from_position(0)[0] > x-x0: # Pyglet bug? i = 0 if self._empty: i = 0 return i def on_mouse_enter(self, mouse): mouse.cursor = TEXT def on_mouse_press(self, mouse): i = self._i = self.index(mouse.x, mouse.y) self._editor.set_selection(0, 0) self.editing = True self._editor.caret.position = i Control.on_mouse_press(self, mouse) def on_mouse_release(self, mouse): if not self.dragged: self._editor.caret.position = self.index(mouse.x, mouse.y) Control.on_mouse_release(self, mouse) def on_mouse_drag(self, mouse): i = self.index(mouse.x, mouse.y) self._editor.selection_start = max(min(self._i, i), 0) self._editor.selection_end = min(max(self._i, i), len(self.value)) self._editor.caret.visible = False Control.on_mouse_drag(self, mouse) def on_mouse_doubleclick(self, mouse): # Select the word at the mouse position. # Words are delimited by non-alphanumeric characters. i = self.index(mouse.x, mouse.y) delimiter = lambda ch: not (ch.isalpha() or ch.isdigit()) if i < len(self.value) and delimiter(self.value[i]): self._editor.set_selection(i, i+1) if i == len(self.value) and self.value != "" and delimiter(self.value[i-1]): self._editor.set_selection(i-1, i) a = _find(lambda (i,ch): delimiter(ch), enumerate(reversed(self.value[:i]))) b = _find(lambda (i,ch): delimiter(ch), enumerate(self.value[i:])) a = a and i-a[0] or 0 b = b and i+b[0] or len(self.value) self._editor.set_selection(a, b) def on_key_press(self, key): if self._editing: self._editor.caret.visible = True i = self._editor.caret.position if key.code == LEFT: # The left arrow moves the text cursor to the left. self._editor.caret.position = max(i-1, 0) elif key.code == RIGHT: # The right arrow moves the text cursor to the right. self._editor.caret.position = min(i+1, len(self.value)) elif key.code in (UP, DOWN): # The up arrows moves the text cursor to the previous line. # The down arrows moves the text cursor to the next line. y = key.code == UP and -1 or +1 n = self._editor.get_line_count() i = self._editor.get_position_on_line( max(self._editor.get_line_from_position(i)+y, 0), self._editor.get_point_from_position(i)[0]) self._editor.caret.position = i elif key.code == TAB and TAB in self.reserved: # The tab key navigates away from the control. self._editor.caret.position = 0 self.editing = False elif key.code == ENTER and ENTER in self.reserved: # The enter key executes on_action() and navigates away from the control. self._editor.caret.position = 0 self.editing = False self.on_action() elif key.code == BACKSPACE and self.selected: # The backspace key removes the current text selection. self.value = self.value[:self.selection[0]] + self.value[self.selection[1]:] self._editor.caret.position = max(self.selection[0], 0) elif key.code == BACKSPACE and i > 0: # The backspace key removes the character at the text cursor. self.value = self.value[:i-1] + self.value[i:] self._editor.caret.position = max(i-1, 0) elif key.char: if self.selected: # Typing replaces any text currently selected. self.value = self.value[:self.selection[0]] + self.value[self.selection[1]:] self._editor.caret.position = i = max(self.selection[0], 0) ch = key.char ch = ch.replace("\r", "\n\r") self.value = self.value[:i] + ch + self.value[i:] self._editor.caret.position = min(i+1, len(self.value)) self._editor.set_selection(0, 0) def draw(self): self._editor.draw()