예제 #1
0
 def reset_art(self):
     if not self.ui.active_art:
         return
     self.charset_swatch.reset_art()
     self.palette_swatch.reset_art()
     # set panel size based on charset size
     margin = self.swatch_margin * 2
     charset = self.ui.active_art.charset
     cqw, cqh = self.charset_swatch.art.quad_width, self.charset_swatch.art.quad_height
     old_width, old_height = self.tile_width, self.tile_height
     # min width in case of tiny charsets
     charset_tile_width = max(charset.map_width, MIN_CHARSET_WIDTH)
     self.tile_width = (cqw * charset_tile_width +
                        margin) / UIArt.quad_width
     # tile height = height of charset + distance from top of popup
     self.tile_height = (cqh *
                         charset.map_height) / UIArt.quad_height + margin
     # account for popup info lines etc: charset name + palette name + 1 padding each
     extra_lines = 7
     # account for size of palette + bottom margin
     palette_height = ((self.palette_swatch.art.height *
                        self.palette_swatch.art.quad_height) +
                       self.swatch_margin) / UIArt.quad_height
     self.tile_height += self.tab_height + palette_height + extra_lines
     if old_width != self.tile_width or old_height != self.tile_height:
         self.art.resize(int(self.tile_width), int(self.tile_height))
     # panel text - position different elements based on selected tab
     if self.active_tab == TAB_CHAR_COLOR:
         self.draw_char_color_tab()
     elif self.active_tab == TAB_TOOLS:
         self.draw_tool_tab()
     self.update_xform_buttons()
     # draw button captions
     UIElement.reset_art(self)
예제 #2
0
 def __init__(self, ui):
     self.ui = ui
     self.world = self.ui.app.gw
     UIElement.__init__(self, ui)
     self.buttons = []
     self.create_buttons()
     self.keyboard_nav_index = 0
예제 #3
0
 def update(self):
     if not self.ui.active_art:
         return
     # update buttons
     UIElement.update(self)
     # set color swatches
     for i in range(self.swatch_width):
         self.char_art.set_color_at(0, 0, i, 0, self.ui.selected_bg_color,
                                    False)
         self.fg_art.set_color_at(0, 0, i, 0, self.ui.selected_fg_color,
                                  False)
         self.bg_art.set_color_at(0, 0, i, 0, self.ui.selected_bg_color,
                                  False)
     # set char w/ correct FG color and xform
     self.char_art.set_char_index_at(0, 0, 1, 0, self.ui.selected_char)
     self.char_art.set_color_at(0, 0, 1, 0, self.ui.selected_fg_color, True)
     self.char_art.set_char_transform_at(0, 0, 1, 0, self.ui.selected_xform)
     # position elements
     self.position_swatch(self.char_renderable, self.char_swatch_x)
     self.position_swatch(self.fg_renderable, self.fg_swatch_x)
     self.position_swatch(self.bg_renderable, self.bg_swatch_x)
     # update buttons before redrawing art (ie non-interactive bits)
     self.update_button_captions()
     for art in [self.char_art, self.fg_art, self.bg_art]:
         art.update()
     self.rewrite_art()
     self.draw_buttons()
예제 #4
0
 def __init__(self, ui):
     # bitmap icon for about menu button
     self.playscii_sprite = UISpriteRenderable(ui.app)
     self.mode_button = None
     UIElement.__init__(self, ui)
     self.active_menu_name = None
     # list of menu buttons that can be navigated etc
     self.menu_buttons = []
     x = PlaysciiMenuButton.width + self.button_padding
     for button_class in self.button_classes:
         button = button_class(self)
         button.width = len(button.caption) + 2
         button.x = x
         x += button.width + self.button_padding
         setattr(self, '%s_button' % button.name, button)
         # NOTE: callback already defined in MenuButton class,
         # menu data for pulldown with set in MenuButton subclass
         button.pulldown = self.ui.pulldown
         self.menu_buttons.append(button)
     playscii_button = PlaysciiMenuButton(self)
     playscii_button.callback = self.open_about
     # implement Playscii logo menu as a normal UIButton that opens
     # the About screen directly
     self.menu_buttons.append(playscii_button)
     self.reset_icon()
     # copy from menu buttons, any buttons past this point are not menus
     self.buttons = self.menu_buttons[:]
     # toggle mode button at far right
     if not self.mode_button_class:
         return
     self.mode_button = self.mode_button_class(self)
     self.mode_button.x = int(
         self.ui.width_tiles * self.ui.scale) - self.mode_button.width
     self.mode_button.callback = self.toggle_game_mode
     self.buttons.append(self.mode_button)
예제 #5
0
 def __init__(self, ui):
     self.bg_color_index = ui.colors.darkgrey
     self.highlight_color = 8  # yellow
     UIElement.__init__(self, ui)
     # state stuff for console move/fade
     self.alpha = 0
     self.target_alpha = 0
     self.target_y = 2
     # start off top of screen
     self.renderable.y = self.y = 2
     # user input and log
     self.last_lines = []
     self.history_filename = self.ui.app.config_dir + CONSOLE_HISTORY_FILENAME
     if os.path.exists(self.history_filename):
         self.history_file = open(self.history_filename, 'r')
         try:
             self.command_history = self.history_file.readlines()
         except:
             self.command_history = []
         self.history_file = open(self.history_filename, 'a')
     else:
         self.history_file = open(self.history_filename, 'w+')
         self.command_history = []
     self.history_index = 0
     # junk data in last user line so it changes on first update
     self.last_user_line = 'test'
     # max line length = width of console minus prompt + _
     self.max_line_length = int(self.art.width) - self.right_margin
예제 #6
0
    def __init__(self, ui, options):
        self.ui = ui
        # apply options, eg passed in from UI.open_dialog
        for k, v in options.items():
            setattr(self, k, v)
        self.confirm_button = ConfirmButton(self)
        self.other_button = OtherButton(self)
        self.cancel_button = CancelButton(self)

        # handle caption overrides
        def caption_override(button, alt_caption):
            if alt_caption and button.caption != alt_caption:
                button.caption = alt_caption
                button.width = len(alt_caption) + 2

        caption_override(self.confirm_button, self.confirm_caption)
        caption_override(self.other_button, self.other_caption)
        caption_override(self.cancel_button, self.cancel_caption)
        self.confirm_button.callback = self.confirm_pressed
        self.other_button.callback = self.other_pressed
        self.cancel_button.callback = self.cancel_pressed
        self.buttons = [
            self.confirm_button, self.other_button, self.cancel_button
        ]
        # populate fields with text
        self.field_texts = []
        for i, field in enumerate(self.fields):
            self.field_texts.append(self.get_initial_field_text(i))
        # field cursor starts on
        self.active_field = 0
        UIElement.__init__(self, ui)
        if self.ui.menu_bar and self.ui.menu_bar.active_menu_name:
            self.ui.menu_bar.close_active_menu()
예제 #7
0
 def reset_art(self, resize=True, clear_buttons=True):
     # get_message splits into >1 line if too long
     msg_lines = self.get_message() if self.message else []
     if resize:
         self.tile_height = self.get_height(msg_lines)
         self.art.resize(self.tile_width, self.tile_height)
         if self.center_in_window:
             qw, qh = self.art.quad_width, self.art.quad_height
             self.x = -(self.tile_width * qw) / 2
             self.y = (self.tile_height * qh) / 2
     # draw window
     self.art.clear_frame_layer(0, 0, self.bg_color, self.fg_color)
     s = ' ' + self.title.ljust(self.tile_width - 1)
     # invert titlebar (if kb focus)
     fg = self.titlebar_fg_color
     bg = self.titlebar_bg_color
     if not self is self.ui.keyboard_focus_element and \
        self is self.ui.active_dialog:
         fg = self.fg_color
         bg = self.bg_color
     self.art.write_string(0, 0, 0, 0, s, fg, bg)
     # message
     if self.message:
         y = 2
         for i, line in enumerate(msg_lines):
             self.art.write_string(0, 0, 2, y + i, line)
     # field caption(s)
     self.draw_fields()
     # position buttons
     self.confirm_button.x = self.tile_width - self.confirm_button.width - 2
     self.confirm_button.y = self.tile_height - 2
     if self.other_button_visible:
         self.other_button.x = self.confirm_button.x
         self.other_button.x -= self.other_button.width + 2
         self.other_button.y = self.confirm_button.y
         self.other_button.visible = True
     self.cancel_button.x = 2
     self.cancel_button.y = self.tile_height - 2
     # create field buttons so you can click em
     if clear_buttons:
         self.buttons = [
             self.confirm_button, self.other_button, self.cancel_button
         ]
     for i, field in enumerate(self.fields):
         # None-type field = just a label
         if field.type is None:
             continue
         field_button = DialogFieldButton(self)
         field_button.field_number = i
         # field settings mean button can be in a variety of places
         field_button.width = 1 if field.type is bool else field.width
         field_button.x = 2 if not field.oneline or field.type is bool else len(
             field.label) + 1
         field_button.y = self.get_field_y(i)
         if not field.oneline:
             field_button.y += 1
         self.buttons.append(field_button)
     # draw buttons
     UIElement.reset_art(self)
예제 #8
0
 def render(self):
     if not self.visible:
         return
     UIElement.render(self)
     if self.active_tab == TAB_CHAR_COLOR:
         self.charset_swatch.render()
         self.palette_swatch.render()
         if self.cursor_char != -1 or self.cursor_color != -1:
             self.cursor_box.render()
예제 #9
0
 def __init__(self, ui):
     art = ui.active_art
     self.ui = ui
     # create 3 custom Arts w/ source charset and palette, renderables for each
     art_name = '%s_%s' % (int(time.time()), self.__class__.__name__)
     self.char_art = UIArt(art_name, ui.app, art.charset, art.palette,
                           self.swatch_width, 1)
     self.char_renderable = UIRenderable(ui.app, self.char_art)
     self.fg_art = UIArt(art_name, ui.app, art.charset, art.palette,
                         self.swatch_width, 1)
     self.fg_renderable = UIRenderable(ui.app, self.fg_art)
     self.bg_art = UIArt(art_name, ui.app, art.charset, art.palette,
                         self.swatch_width, 1)
     self.bg_renderable = UIRenderable(ui.app, self.bg_art)
     # "dimmed out" box
     self.dim_art = UIArt(art_name, ui.app, ui.charset, ui.palette,
                          self.swatch_width + self.char_swatch_x, 1)
     self.dim_renderable = UIRenderable(ui.app, self.dim_art)
     self.dim_renderable.alpha = 0.75
     # separate dimmed out box for xform, easier this way
     xform_width = XformToggleButton.width + XformCycleButton.width
     self.dim_xform_art = UIArt(art_name, ui.app, ui.charset, ui.palette,
                                xform_width, 1)
     self.dim_xform_renderable = UIRenderable(ui.app, self.dim_xform_art)
     self.dim_xform_renderable.alpha = 0.75
     # create clickable buttons
     self.buttons = []
     for button_class, button_name in self.button_names.items():
         button = button_class(self)
         setattr(self, button_name + '_button', button)
         cb_name = '%s_button_pressed' % button_name
         button.callback = getattr(self, cb_name)
         self.buttons.append(button)
         # some button captions, widths, locations will be set in reset_art
     # determine total width of left-justified items
     self.left_items_width = self.tool_cycle_button.x + self.tool_cycle_button.width + 15
     # set some properties in bulk
     self.renderables = []
     for r in [
             self.char_renderable, self.fg_renderable, self.bg_renderable,
             self.dim_renderable, self.dim_xform_renderable
     ]:
         r.ui = ui
         r.grain_strength = 0
         # add to list of renderables to manage eg destroyed on quit
         self.renderables.append(r)
     # red X for transparent colors
     self.x_renderable = UIRenderableX(ui.app, self.char_art)
     # give it a special reference to this element
     self.x_renderable.status_bar = self
     self.renderables.append(self.x_renderable)
     UIElement.__init__(self, ui)
예제 #10
0
 def reset_art(self):
     self.tile_width = ceil(self.ui.width_tiles * self.ui.scale)
     # must resize here, as window width will vary
     self.art.resize(self.tile_width, self.tile_height)
     # repaint bar contents
     bg = self.ui.colors.white
     fg = self.ui.colors.black
     self.art.clear_frame_layer(0, 0, bg, fg)
     # reposition right-justified mode switch button
     if self.mode_button:
         self.mode_button.x = int(
             self.ui.width_tiles * self.ui.scale) - self.mode_button.width
     # draw buttons, etc
     UIElement.reset_art(self)
     self.reset_icon()
예제 #11
0
 def update(self):
     # disable prev/next buttons if we're at either end of the page list
     if self.page == 0:
         self.other_button.can_hover = False
         self.other_button.set_state('dimmed')
     elif self.page == len(self.message) - 1:
         self.confirm_button.can_hover = False
         self.confirm_button.set_state('dimmed')
     else:
         for button in [self.confirm_button, self.other_button]:
             button.can_hover = True
             button.dimmed = False
             if button.state != 'normal':
                 button.set_state('normal')
     UIElement.update(self)
예제 #12
0
 def update(self):
     # redraw fields every update for cursor blink
     # (seems a waste, no real perf impact tho)
     self.draw_fields(False)
     # don't allow confirmation if all field input isn't valid
     valid, reason = self.is_input_valid()
     # if input invalid, show reason in red along button of window
     bottom_y = self.tile_height - 1
     # first clear any previous warnings
     self.art.clear_line(0, 0, bottom_y)
     self.confirm_button.set_state('normal')
     # some dialogs use reason for warning + valid input
     if reason:
         fg = self.ui.error_color_index
         self.art.write_string(0, 0, 1, bottom_y, reason, fg)
     if not valid:
         self.confirm_button.set_state('dimmed')
     UIElement.update(self)
예제 #13
0
 def reset_art(self):
     UIElement.reset_art(self)
     self.tile_width = ceil(self.ui.width_tiles * self.ui.scale)
     # must resize here, as window width will vary
     self.art.resize(self.tile_width, self.tile_height)
     # write chars/colors to the art
     self.rewrite_art()
     self.x_renderable.scale_x = self.char_art.width
     self.x_renderable.scale_y = -self.char_art.height
     # dim box
     self.dim_art.clear_frame_layer(0, 0, self.ui.colors.white)
     self.dim_art.update()
     self.dim_xform_art.clear_frame_layer(0, 0, self.ui.colors.white)
     self.dim_xform_art.update()
     # rebuild geo, elements may be new dimensions
     self.dim_art.geo_changed = True
     self.dim_xform_art.geo_changed = True
     self.char_art.geo_changed = True
     self.fg_art.geo_changed = True
     self.bg_art.geo_changed = True
예제 #14
0
 def render(self):
     if not self.ui.active_art:
         return
     UIElement.render(self)
     # draw wireframe red X /behind/ char if BG transparent
     if self.ui.selected_bg_color == 0:
         self.x_renderable.x = self.char_renderable.x
         self.x_renderable.y = self.char_renderable.y
         self.x_renderable.render()
     self.char_renderable.render()
     self.fg_renderable.render()
     self.bg_renderable.render()
     # draw red X for transparent FG or BG
     if self.ui.selected_fg_color == 0:
         self.x_renderable.x = self.fg_renderable.x
         self.x_renderable.y = self.fg_renderable.y
         self.x_renderable.render()
     if self.ui.selected_bg_color == 0:
         self.x_renderable.x = self.bg_renderable.x
         self.x_renderable.y = self.bg_renderable.y
         self.x_renderable.render()
     # dim out items if brush is set to not affect them
     self.dim_renderable.y = self.char_renderable.y
     swatch_width = self.art.quad_width * StatusBarCycleButton.width
     if not self.ui.selected_tool.affects_char:
         self.dim_renderable.x = self.char_renderable.x - swatch_width
         self.dim_renderable.render()
     if not self.ui.selected_tool.affects_fg_color:
         self.dim_renderable.x = self.fg_renderable.x - swatch_width
         self.dim_renderable.render()
     if not self.ui.selected_tool.affects_bg_color:
         self.dim_renderable.x = self.bg_renderable.x - swatch_width
         self.dim_renderable.render()
     if not self.ui.selected_tool.affects_xform:
         # separate dimmer renderable for xform's wider size
         self.dim_xform_renderable.y = self.char_renderable.y
         self.dim_xform_renderable.x = XformToggleButton.x * self.art.quad_width - 1
         self.dim_xform_renderable.render()
예제 #15
0
 def __init__(self, ui):
     self.ui = ui
     self.charset_swatch = CharacterSetSwatch(ui, self)
     self.palette_swatch = PaletteSwatch(ui, self)
     self.cursor_box = SwatchSelectionBoxRenderable(ui.app,
                                                    self.charset_swatch.art)
     self.renderables = [self.cursor_box]
     # set by swatch.set_cursor_loc based on selection validity
     self.cursor_char = -1
     self.cursor_color = -1
     self.active_tab = TAB_CHAR_COLOR
     # create buttons from button:name map, button & callback names generated
     # group these into lists that can be combined into self.buttons
     self.common_buttons = self.create_buttons_from_map(self.button_names)
     self.char_color_tab_buttons = self.create_buttons_from_map(
         self.char_color_tab_button_names)
     self.tool_tab_buttons = self.create_buttons_from_map(
         self.tool_tab_button_names)
     # populate more tool tab buttons from UI's list of tools
     # similar to create_buttons_from_map, but class name isn't known
     # MAYBE-TODO: is there a way to unify this?
     for tool in self.ui.tools:
         tool_button = ToolButton(self)
         # caption: 1-space padding from left
         tool_button.caption = ' %s' % tool.button_caption
         tool_button_name = '%s_tool_button' % tool.name
         setattr(self, tool_button_name, tool_button)
         cb_name = '%s_pressed' % tool_button_name
         tool_button.callback = getattr(self, cb_name)
         # set a special property UI can refer to
         tool_button.tool_name = tool.name
         self.tool_tab_buttons.append(tool_button)
     UIElement.__init__(self, ui)
     # set initial tab state
     self.char_color_tab_button_pressed()
     self.xform_0_button.normal_bg_color = self.xform_normal_button.normal_bg_color = self.highlight_color
예제 #16
0
 def update(self):
     UIElement.update(self)
     if not self.ui.active_art:
         return
     if self.active_tab == TAB_CHAR_COLOR:
         # bail if mouse didn't move, but also respect keyboard editing
         mouse_moved = self.ui.app.mouse_dx != 0 or self.ui.app.mouse_dy != 0
         if self.ui.app.keyboard_editing:
             self.cursor_box.visible = True
         elif mouse_moved and self in self.ui.hovered_elements:
             self.cursor_box.visible = False
             x, y = self.ui.get_screen_coords(self.ui.app.mouse_x,
                                              self.ui.app.mouse_y)
             for e in [self.charset_swatch, self.palette_swatch]:
                 if e.is_inside(x, y):
                     self.cursor_box.visible = True
                     e.set_cursor_loc_from_mouse(self.cursor_box, x, y)
                     break
         # note: self.cursor_box updates in charset_swatch.update
         self.charset_swatch.update()
         self.palette_swatch.update()
     elif self.active_tab == TAB_TOOLS and self.ui.tool_settings_changed:
         self.draw_tool_tab()
         self.draw_buttons()
예제 #17
0
 def clicked(self, mouse_button):
     handled = UIElement.clicked(self, mouse_button)
     if handled:
         return
     # if cursor is over a char or color, make it the ui's selected one
     if self.cursor_char != -1:
         self.ui.selected_char = self.cursor_char
         # update cursor, eg keyboard select when cursor isn't beneath popup
         self.ui.app.cursor.undo_preview_edits()
         self.ui.app.cursor.update_cursor_preview()
     elif self.cursor_color != -1:
         if mouse_button == 1:
             self.ui.selected_fg_color = self.cursor_color
         elif mouse_button == 3:
             self.ui.selected_bg_color = self.cursor_color
     return True
예제 #18
0
 def destroy(self):
     UIElement.destroy(self)
     self.playscii_sprite.destroy()
예제 #19
0
 def render(self):
     UIElement.render(self)
     self.playscii_sprite.render()
예제 #20
0
 def reset_loc(self):
     UIElement.reset_loc(self)
예제 #21
0
 def reset_art(self):
     self.art.clear_frame_layer(0, 0, self.bg_color, self.fg_color)
     self.draw_titlebar()
     self.refresh_items()
     UIElement.reset_art(self)
예제 #22
0
 def clicked(self, mouse_button):
     # always handle input, even if we didn't hit a button
     UIElement.clicked(self, mouse_button)
     return True