Пример #1
0
class GraphicButton(BaseButton):


    stylesheet = dictUnion(BaseButton.stylesheet, {DEFAULT_GRAPHIC: None, #default to none
                                                  DEFAULT_PRESSED_GRAPHIC: None})

    def __init__(self, *args, central_graphic = None, **kwargs):
        super().__init__(*args, **kwargs)
        self.pressed_graphic = None #overwrite these
        self.unpressed_graphic = None #overwrite these

        self.setCentralWidget(ScreenElement(parent_stylesheet=self.stylesheet))
        if central_graphic:
            self.setButtonGraphic(central_graphic)

        self.setWidth(self.getOrderedStylesheetData(DEFAULT_BUTTON_WIDTH, DEFAULT_WIDTH, default=self.getCentralWidget().getSpriteWidth()))
        self.setHeight(self.getOrderedStylesheetData(DEFAULT_BUTTON_HEIGHT, DEFAULT_HEIGHT, default=self.getCentralWidget().getSpriteHeight()))

    def setButtonGraphic(self, val):
        cw = self.getCentralWidget()
        if cw:
            cw.setSprite(val)

    #overwritten stuff

    def setSprite(self, *args, **kwargs):
        pass #disallow this
Пример #2
0
    def __init__(self, sprite_path = None, children = (), stylesheet = None, parent_stylesheet = None, **kwargs):
        super().__init__(**kwargs)
        self._children = {}
        self._funcs = {}
        self._focus_listeners = set()
        self._focused_child_id = None
        self._parent = None
        self._layer = 0
        self._mouse_over = False
        self._element_position = (0,0)
        self._lock_input = set()
        self._hide_lock = set()
        for string in list(self.keybind_map.keys()) + list(self.other_event_keys):
            try:
                self._funcs[string] = getattr(self, string)
            except AttributeError:
                pass
            try:
                newfunc = kwargs[string]
                try:
                    oldfunc = self._funcs[string]
                    def combinedfunc(*args, **kwargs): #create a pseudo super
                        rv1 = oldfunc()
                        rv2 = newfunc()
                        return rv1 or rv2
                    self._funcs[string] = combinedfunc
                except KeyError:
                    self._funcs[string] = newfunc
            except KeyError:
                pass
        section_bounds_query_key = QUERY_MOUSE_MOVE_SECTION_BOUNDS + self.id
        if self._funcs.keys() & (MOUSEENTER_KEY, MOUSELEAVE_KEY, MOUSEOVER_KEY): #if we have any of these
            self.addSectionalMouseMoveListener(self._mouseMove, priority = self.getEventListenerPriority, query_key = section_bounds_query_key)
        self.addQueryListener(section_bounds_query_key, self.getExtents)

        if parent_stylesheet:
            self.stylesheet = dictUnion(parent_stylesheet, self.stylesheet)
        if stylesheet:
            self.updateStyleSheet(stylesheet)

        width = self.stylesheet.get(DEFAULT_WIDTH, None)
        if width is not None:
            self.setWidth(width)
        height = self.stylesheet.get(DEFAULT_HEIGHT, None)
        if height is not None:
            self.setHeight(height)
        self.setSprite(sprite_path or self.stylesheet.get(DEFAULT_GRAPHIC, None))

        for child in children: #add starting children
            self.addChild(child)
Пример #3
0
 def addChildApplyStylesheet(self, newchildtype, *args, parent_stylesheet = {},update_layers = True, **kwargs):
     return self.addChild(newchildtype(*args, parent_stylesheet=dictUnion(self.stylesheet, parent_stylesheet), **kwargs), update_layers)
Пример #4
0
 def updateStyleSheet(self, sheet):
     self.stylesheet = dictUnion(self.stylesheet, sheet) #merge them. sheet's keys will be used preferentially
Пример #5
0
class BaseButton(Container):

    stylesheet = dictUnion(Container.stylesheet, {})

    def __init__(self, sprite_path = None, width = None, height = None, *args, **kwargs):
        super().__init__(sprite_path, **kwargs)

        #defaults
        self._central_widget_id = None

        self._highlight_id = self.addChildApplyStylesheet(ScreenElement, self.stylesheet.get(DEFAULT_HIGHLIGHT_GRAPHIC, tuple(FULL_MISC_PATH + ["menugraphics", "hover.png"])))
        highlight = self.getHighlight()
        highlight.setSpriteShow(False)
        highlight.setSpriteCenter(True,True)
        highlight.setSpriteFollowCamera(True)
        sprite_path = sprite_path or self.getOrderedStylesheetData(DEFAULT_BUTTON_GRAPHIC, DEFAULT_GRAPHIC, default=tuple(FULL_MISC_PATH + ["menugraphics", "brown_button.bordered"]))
        if sprite_path is not None:
            self.setSprite(sprite_path)
        if width is None:
            width = self.getOrderedStylesheetData(DEFAULT_BUTTON_WIDTH, DEFAULT_WIDTH, default=80)
        if width is not None:
            self.setWidth(width)
        if height is None:
            height = height or self.getOrderedStylesheetData(DEFAULT_BUTTON_HEIGHT, DEFAULT_HEIGHT, default=24)
        if height is not None:
            self.setHeight(height)
        self.setBorder(*self.getOrderedStylesheetData(DEFAULT_BUTTON_BORDER, DEFAULT_BORDER, default=(4,4)))

        self.unpressed_graphic = sprite_path
        self.pressed_graphic = self.stylesheet.get(DEFAULT_PRESSED_GRAPHIC, tuple(FULL_MISC_PATH + ["menugraphics", "brown_button_pressed.bordered"]))

        self.setSpriteFollowCamera(True)

    def getHighlight(self):
        try:
            return self.getChild(self._highlight_id)
        except AttributeError: #not fully initialized yet
            return None

    def addHighlight(self):
        highlight = self.getHighlight()
        if highlight:
            highlight.setSpriteShow(True)

    def removeHighlight(self):
        highlight = self.getHighlight()
        if highlight:
            highlight.setSpriteShow(False)

    def setPressedDown(self):
        if self.pressed_graphic:
            self.setSprite(self.pressed_graphic)

    def setUnpressed(self):
        if self.pressed_graphic and self.unpressed_graphic:
            self.setSprite(self.unpressed_graphic)

    def _updateHighlight(self):
        highlight = self.getHighlight()
        if highlight:
            highlight.setDimensions(*self.getDimensions())

    def setCentralWidget(self, widget):
        self._central_widget_id = self.addChild(widget)
        cw = self.getCentralWidget()
        cw.setSpriteCenter(True, True)
        cw.setSpriteFollowCamera(True)
        return self._central_widget_id

    def getCentralWidget(self):
        try:
            return self.getChild(self._central_widget_id)
        except KeyError:
            return None

    def showElement(self, key = None):
        super().showElement(key=key)
        if not self.focus:
            self.removeHighlight()

    #event stuff

    def mouseenter(self):
        self.setSelfFocused()

    def mouseover(self, *args, **kwargs):
        if not self.isFocused():
            self.setSelfFocused()

    def mouseleave(self):
        self.setUnpressed()

    def confirmhold(self):
        self.setPressedDown()

    def confirm(self):
        self.setUnpressed()

    def gainfocus(self):
        self.addHighlight()

    def losefocus(self):
        self.setUnpressed()
        self.removeHighlight()

    #overwritten stuff

    def _updateContainerPositions(self):
        super()._updateContainerPositions()
        central_widget = self.getCentralWidget()
        if central_widget:
            self.setDimensions(*map(max, self.getDimensions(), map(operator.add, central_widget.getDimensions(), map(operator.mul, self.getBorder(), (2,2)))))
        self._updateHighlight()

    def getAnchorPoint(self):
        extents = self.getExtents() #set to middle of button
        return (extents[0] + extents[1])/2, (extents[2] + extents[3])/2

    def setSpriteCenter(self, *args, **kwargs):
        super().setSpriteCenter(*args, **kwargs)
        self._applyChildrenPositions()
        self.tellParentToUpdate()

    def _applyChildrenPositions(self):
        super()._applyChildrenPositions()
        self._updateHighlight()
        self.tellParentToUpdate()

    def setWidth(self, *args, **kwargs):
        super().setWidth(*args, **kwargs)
        self._updateHighlight()
        self.tellParentToUpdate()

    def setHeight(self, *args, **kwargs):
        super().setHeight(*args, **kwargs)
        self._updateHighlight()
        self.tellParentToUpdate()

    def updateChildrenLayers(self, lastlayer = None):
        base_layer = lastlayer or self.getLayer()
        for child in self.getAllChildren():
            child.setLayer(base_layer)
        highlight = self.getHighlight()
        if highlight:
            self.getHighlight().setLayer(base_layer + 1)
        return base_layer + 1
Пример #6
0
class Container(ScreenElement):

    stylesheet = dictUnion(ScreenElement.stylesheet, {DEFAULT_BORDER: (0,0)})

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.border = self.stylesheet.get(DEFAULT_BORDER, (0,0))
        self.spacing = None
        self.strict_spacing = False
        self._update_positions = False
        self._currently_updating = False

    def setBorder(self, x = None, y = None):
        if x is None: x = self.border[0]
        if y is None: y = self.border[1]
        self.border = (x,y)
        self.updateContainerPositions()

    def getBorder(self):
        return self.border

    def getSpacing(self):
        return self.spacing

    def setStrictSpacing(self, val):
        if val != self.strict_spacing:
            self.strict_spacing = val
            self.delayUpdatePositions()

    def getStrictSpacing(self):
        return self.strict_spacing

    def delayUpdatePositions(self):
        if not self._update_positions and not self._currently_updating:
            try:
                self._update_positions = self.delay(self.updateContainerPositions, self.getLayer)
            except DelayedEventException:
                pass

    def updateContainerPositions(self):
        if not self._currently_updating: #prevent infinite loops
            self.undelay(self._update_positions)
            self._update_positions = False
            self._currently_updating = True
            self._updateContainerPositions()
            self._currently_updating = False

    def _updateContainerPositions(self):
        pass

    def containerPositionsUpdated(self):
        return not bool(self._update_positions)

    #template functions

    def setSpacing(self, *args, **kwargs):
        pass

    def getChildKey(self, *args, **kwargs):
        return None

    def getChildByKey(self, *args, **kwargs):
        return None


    #overwritten stuff

    def getWidth(self):
        if not self.containerPositionsUpdated():
            self.updateContainerPositions()
        return super().getWidth()

    def getHeight(self):
        if not self.containerPositionsUpdated():
            self.updateContainerPositions()
        return super().getHeight()

    def getExtents(self):
        if not self.containerPositionsUpdated():
            self.updateContainerPositions()
        return super().getExtents()

    def getAnchorPoint(self):
        #return bottom left corner
        extents = self.getExtents()
        return extents[0], extents[2]

    def removeAllChildren(self):
        super().removeAllChildren()
        self.delayUpdatePositions()

    def setDimensions(self, *args, **kwargs):
        super().setDimensions(*args, **kwargs)
        self._applyChildrenPositions()

    def updateElement(self):
        super().updateElement()
        self.delayUpdatePositions()
Пример #7
0
class MenuTemplate(ScreenElement):
    #not to be used without a container

    #update event list
    other_event_keys = ScreenElement.other_event_keys + (INTERLINK_EVENT_LEFT, INTERLINK_EVENT_RIGHT, INTERLINK_EVENT_UP, INTERLINK_EVENT_DOWN)

    button_type = LabelButton
    focus_first_button = True

    stylesheet = dictUnion(ScreenElement.stylesheet, {})

    def __init__(self, sprite_path = None, button_type = None, **kwargs):
        super().__init__(**kwargs)
        sprite_path = sprite_path or self.getOrderedStylesheetData(DEFAULT_MENU_GRAPHIC, DEFAULT_GRAPHIC, default=tuple(FULL_MISC_PATH + ["menugraphics", "menu0.bordered"]))
        if sprite_path:
            self.setSprite(sprite_path)
        if button_type is not None:
            self.button_type = button_type
        self._first_button = True
        self._buttons = set()
        self._menu_interlinks = {}

        #overwrites
        self.border = self.stylesheet.get(DEFAULT_BORDER, None) or self.stylesheet.get(DEFAULT_MENU_BORDER, None) or (8,8)

        #defaults
        self.setSpriteCenter(True, True)
        self.setSpriteFollowCamera(True)
        self.setPos(*map(operator.truediv, getWindowDimensionsScaled(), (2,2)))

        self.addQueryListener(self.getEventID(MENU_LOOKUP_KEY), lambda: self)

    def setButtonType(self, newtype):
        #will NOT regenerate old buttons!
        self.button_type = newtype

    def addButton(self, *args, **kwargs):
        ID = self.addChildApplyStylesheet(self.button_type, *args, **kwargs)
        self._updateFirstButton(ID)
        self._buttons.add(ID)
        return ID

    def getButton(self, *args, **kwargs):
        #alias for getChildByKey
        return self.getChildByKey(*args, **kwargs)

    def getAllButtons(self):
        return [self.getChild(ID) for ID in self._buttons]

    def _updateFirstButton(self, ID):
        if self._first_button:
            if self.focus_first_button:
                self.setFocus(ID)
            self._first_button = False

    def interlinkMenu(self, direction, othermenuid):
        othermenu = self.queryMenuByID(othermenuid)
        if othermenu:
            self._interlinkMenu(direction, othermenu.id)
            othermenu._interlinkMenu(DIRECTION_FLIP_LOOKUP[direction], self.id)

    def _interlinkMenu(self, direction, othermenuid):
        try:
            self._menu_interlinks[direction].add(othermenuid)
        except KeyError:
            self._menu_interlinks[direction] = set()
            self._menu_interlinks[direction].add(othermenuid)

    def clearInterlink(self, direction, othermenuid):
        othermenu = self.queryMenuByID(othermenuid)
        if othermenu:
            self._clearInterlink(direction, othermenu.id)
            othermenu._clearInterlink(DIRECTION_FLIP_LOOKUP[direction], self.id)

    def _clearInterlink(self, direction, othermenuid):
        try:
            self._menu_interlinks[direction].discard(othermenuid)
        except KeyError:
            pass

    def clearAllInterlinks(self):
        for direction, menuref in self.getAllInterlinkedMenus():
            menuref._clearInterlink(DIRECTION_FLIP_LOOKUP[direction], self.id)
        self._menu_interlinks.clear()


    def _interlinkActivate(self, direction):
        if direction in self._menu_interlinks:
            pos = self.getFocusedChild().getCenterPosition()
            mindistance = math.inf
            mindistance_menu_ref = None
            mindistance_button_id = None
            for menu_id in self._menu_interlinks[direction]:
                menu_ref = self.queryMenuByID(menu_id)
                if menu_ref:
                    for button in menu_ref.getAllButtons():
                        other_pos = button.getCenterPosition()
                        distance = math.hypot(pos[0] - other_pos[0], pos[1] - other_pos[1])
                        if distance < mindistance:
                            mindistance = distance
                            mindistance_menu_ref = menu_ref
                            mindistance_button_id = button.id
            if mindistance_menu_ref: #TODO: make this suck less
                self.clearFocus()
                self.getParent().clearFocus()
                mindistance_menu_ref.setFocus(mindistance_button_id)
                mindistance_menu_ref.setSelfFullyFocused()
                return True
        return False

    def getAllInterlinkedMenus(self):
        menulist = []
        for direction, menuset in self._menu_interlinks.items():
            for menuid in menuset:
                menuref = self.queryMenuByID(menuid)
                if menuref:
                    menulist.append((direction, menuref))
        return menulist

    def queryMenuByID(self, menu_id):
        try:
            menu_id.id
        except AttributeError:
            return callQuery(self._getEventID(menu_id, MENU_LOOKUP_KEY))
        else:
            return menu_id #is a reference

    #input stuff

    def mouseover(self, *args, **kwargs):
        if not self.isInputLocked():
            self.setSelfFullyFocused()

    #overwritten stuff

    def setFocus(self, *args, **kwargs):
        super().setFocus(*args, **kwargs)
        if self.hasFocusedChild():
            for direction, menuref in self.getAllInterlinkedMenus():
                menuref.clearFocus()


    def removeChild(self, *args, **kwargs):
        ID = super().removeChild(*args, **kwargs)
        self._buttons.discard(ID)
        return ID

    def removeAllChildren(self, *args, **kwargs):
        super().removeAllChildren(*args, **kwargs)
        self._buttons.clear()

    def setSpriteCenter(self, *args, **kwargs):
        super().setSpriteCenter(*args, **kwargs)
        self._applyChildrenPositions()

    def _updateContainerPositions(self, *args, **kwargs):
        maxwidth = 0
        maxheight = 0
        for button in self.getAllButtons():
            try:
                button.updateContainerPositions
            except:
                pass
            else:
                button.updateContainerPositions()
            maxwidth = max(maxwidth, button.getWidth())
            maxheight = max(maxheight, button.getHeight())
        for button in self.getAllButtons():
            button.setDimensions(maxwidth, maxheight)
        super()._updateContainerPositions(*args, **kwargs)