Example #1
0
    def __init__(self, parent, **kwargs):
        Widget.__init__(self, parent)
        self.searchDlg = SearchDlg(self.app)
        self.searchDlg.mapWidget = self
        # data
        self.control_modes = {
        }  # mutable, thus updating here will update StarMap
        self.updateConfigModes()
        self.control_modes['systems'] = 1
        self.control_modes['planets'] = 1
        self.control_modes['fleets'] = 1
        self.control_modes['civilian_fleets'] = 1
        self.control_modes['pirate_areas'] = 1
        self.control_modes['hotbuttons'] = 1
        self.control_modes['minimap'] = 1
        self.control_modes['redirects'] = 1
        self.control_modes['map_grid_coords'] = 1
        self.control_modes['map_grid'] = 1
        self.control_modes['scanners'] = 1
        self.control_modes['fleet_lines'] = 1
        self.control_modes['gate_systems'] = 1
        self.control_modes['alternative_view'] = 1
        self.control_modes['control_areas'] = 0
        self.control_modes['pirate_dialogs'] = 0  # only for pirate, obv.
        # more data
        self.highlightPos = None
        self.alwaysShowRangeFor = None
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        self.pressedObjIDs = []
        self._newCurrXY = 0
        self.activePos = (0, 0)

        # the map itself!
        self.star_map = StarMap(self.control_modes)
        self.action = None
        self.callEventHandler = None
        self.showBuoyDlg = ShowBuoyDlg(self.app)
        self.KeyModHelp = KeyModHelp(self.app)
        self._miniMapRect = pygame.Rect(0, 20, 175, 175)
        self._hotbuttonsZone = pygame.Rect(0, 0, 0, 0)
        self.initHotbuttons()
        self.miniMap = MiniMap(self._miniMapRect.width,
                               self._miniMapRect.height)
        # flags
        self.processKWArguments(kwargs)
        parent.registerWidget(self)
        # popup menu
        self.popup = ui.Menu(self.app, title=_("Select object"))
        self.popup.subscribeAction("*", self)
        # overlay system
        self._overlayZone = False
        # key setting system
        self.selectobject = False
        self.setKey = False
        # commands
        self.keyPress = False
        # map - produced by StarMap draw method
        self._mapSurf = None
        self._actAreas = {}
        self._actBuoyAreas = {}
        # dirty flag
        self.repaint_map = True
Example #2
0
class StarMapWidget(Widget):
    def __init__(self, parent, **kwargs):
        Widget.__init__(self, parent)
        self.searchDlg = SearchDlg(self.app)
        self.searchDlg.mapWidget = self
        # data
        self.control_modes = {
        }  # mutable, thus updating here will update StarMap
        self.updateConfigModes()
        self.control_modes['systems'] = 1
        self.control_modes['planets'] = 1
        self.control_modes['fleets'] = 1
        self.control_modes['civilian_fleets'] = 1
        self.control_modes['pirate_areas'] = 1
        self.control_modes['hotbuttons'] = 1
        self.control_modes['minimap'] = 1
        self.control_modes['redirects'] = 1
        self.control_modes['map_grid_coords'] = 1
        self.control_modes['map_grid'] = 1
        self.control_modes['scanners'] = 1
        self.control_modes['fleet_lines'] = 1
        self.control_modes['gate_systems'] = 1
        self.control_modes['alternative_view'] = 1
        self.control_modes['control_areas'] = 0
        self.control_modes['pirate_dialogs'] = 0  # only for pirate, obv.
        # more data
        self.highlightPos = None
        self.alwaysShowRangeFor = None
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        self.pressedObjIDs = []
        self._newCurrXY = 0
        self.activePos = (0, 0)

        # the map itself!
        self.star_map = StarMap(self.control_modes)
        self.action = None
        self.callEventHandler = None
        self.showBuoyDlg = ShowBuoyDlg(self.app)
        self.KeyModHelp = KeyModHelp(self.app)
        self._miniMapRect = pygame.Rect(0, 20, 175, 175)
        self._hotbuttonsZone = pygame.Rect(0, 0, 0, 0)
        self.initHotbuttons()
        self.miniMap = MiniMap(self._miniMapRect.width,
                               self._miniMapRect.height)
        # flags
        self.processKWArguments(kwargs)
        parent.registerWidget(self)
        # popup menu
        self.popup = ui.Menu(self.app, title=_("Select object"))
        self.popup.subscribeAction("*", self)
        # overlay system
        self._overlayZone = False
        # key setting system
        self.selectobject = False
        self.setKey = False
        # commands
        self.keyPress = False
        # map - produced by StarMap draw method
        self._mapSurf = None
        self._actAreas = {}
        self._actBuoyAreas = {}
        # dirty flag
        self.repaint_map = True

    def updateConfigModes(self):
        self.control_modes[
            'redirects'] = gdata.config.defaults.showredirects is not 'no'
        self.control_modes[
            'coords'] = gdata.config.defaults.showcoords is not 'no'
        self.control_modes[
            'map_grid'] = gdata.config.defaults.showmapgrid is not 'no'
        self.control_modes[
            'scanners'] = gdata.config.defaults.showmapscanners is not 'no'
        self.control_modes[
            'fleet_lines'] = gdata.config.defaults.showfleetlines is not 'no'
        self.control_modes[
            'gate_systems'] = gdata.config.defaults.showgatesystems is not 'no'
        self.control_modes[
            'alternative_mode'] = gdata.config.defaults.alternateviewmode is not 'no'
        self.control_modes[
            'control_areas'] = gdata.config.defaults.showplayerzones is not 'no'
        self.control_modes[
            'minimap'] = gdata.config.defaults.showminimap is not 'yes'

    def precompute(self):
        self.star_map.rect = self.rect
        self.star_map.precompute()
        player = client.getPlayer()
        if (player.type == Const.T_PIRPLAYER or\
            player.type == Const.T_AIPIRPLAYER) and not self.control_modes['pirate_dialogs']:
            self.control_modes['pirate_dialogs'] = True
            if self.control_modes['hotbuttons']:
                self.initHotbuttons()  #reinit to add the pirate button
        self.miniMap.precompute()
        # self dirty flag
        self.repaint_map = 1

    def save(self, append='', chronicle_shot=False):
        name = ("%s.png" % append)
        if chronicle_shot:
            # print whole galaxy, centered over black hole
            # star_map has much more information about the galaxy, thus handling this request
            new_surf = self.star_map.chronicle_draw()
            pygame.image.save(new_surf, name)
        else:
            # print current player view
            new_surf, empty, empty = self.star_map.draw(
                pygame.Surface(
                    (self.star_map.rect.width, self.star_map.rect.height)))
            pygame.image.save(new_surf, name)
        return name

    def draw(self, surface):
        self._miniMapRect.left = self.rect.width - self._miniMapRect.width
        self._miniMapRect.top = self.rect.top
        if not self._mapSurf:
            mapSurf = pygame.Surface(self.rect.size, pygame.SWSURFACE, surface)
        else:
            mapSurf = self._mapSurf

        if self.repaint_map:
            mapSurf, self._actAreas, self._actBuoyAreas = self.star_map.draw(
                mapSurf)
            # For some reason, this is not just optimization, it's mandatory for proper
            # function. BUG?!
            self.repaint_map = 0
            self.repaintHotbuttons = 1
        if self.repaintHotbuttons and self.control_modes['hotbuttons']:
            self.drawHotbuttons(mapSurf)
            self.repaintHotbuttons = 0
        # blit cached map
        surface.blit(mapSurf, self.rect)
        self._mapSurf = mapSurf

        if self.control_modes['minimap']:
            self.miniMap.draw(surface, self._miniMapRect.left,
                              self._miniMapRect.top)
            if self.miniMap.needRect():
                self.processMiniMapRect()
                self.miniMap.draw(surface, self._miniMapRect.left,
                                  self._miniMapRect.top)
        # additional information (ranges, fleet lines, selected system sign)
        self.drawAdditions(surface)

        self.drawPopups(surface)
        return self.rect

    def drawHotbuttons(self, mapSurf):
        rect = mapSurf.get_rect()
        bottom = rect.bottom
        right = rect.right
        dx = 137
        dy = 46
        top = bottom - dy - 1
        left = right - dx - 1
        self._hotbuttonsZone.top = top + self.rect.top
        self._hotbuttonsZone.left = left
        self._hotbuttonsZone.width = dx
        self._hotbuttonsZone.height = dy

        pygame.draw.rect(mapSurf, (0x00, 0x00, 0x90),
                         (left - 1, top - 1, dx + 2, dy + 2))
        pygame.draw.rect(mapSurf, (0x33, 0x33, 0x66), (left, top, dx, dy))

        for buttonkey in self._hotbuttons:
            button = self._hotbuttons[buttonkey]
            self._hotbuttonRects[button[0]] = [
                button[0],
                pygame.Rect(button[2] + self._hotbuttonsZone.left,
                            button[3] + self._hotbuttonsZone.top + 15,
                            button[4], button[5])
            ]
            img = res.getButton(button[0], button[1])
            if (button[1] and not (self._tempOverlayHotbutton
                                   and self._tempOverlayHotbutton == button[0])
                ) or (not button[1] and self._tempOverlayHotbutton
                      and self._tempOverlayHotbutton == button[0]):
                pygame.draw.rect(mapSurf, (0x90, 0x90, 0x90),
                                 (left + button[2] - 1, top + 15 + button[3] -
                                  1, button[4] + 2, button[5] + 2), 1)
            mapSurf.blit(img, (left + button[2], top + 15 + button[3]))
        if self._tempOverlayHotbutton:
            text = self._hotbuttons[self._tempOverlayHotbutton][7]
            textSrfc = Fonts.renderText(self.star_map.textSize, text, 1,
                                        (0xEF, 0xEF, 0xEF))
            mapSurf.blit(textSrfc, (left + 2, top + 1))

    def drawPopups(self, surface):
        # draw popups
        moreIDs = len(self.activeObjIDs) > 1
        if not moreIDs:
            x, y = self.activePos
            x += 20
        else:
            x = self.rect.left + 2
            y = self.rect.top
        if not pygame.key.get_mods() & pygame.KMOD_SHIFT:
            for activeObjID in self.activeObjIDs:
                index = 0
                if self.star_map._popupInfo.has_key(activeObjID):
                    # put pop up info on the screen
                    info = self.star_map._popupInfo[activeObjID]
                    # x1, y1 = self._actAreas[self.activeObjID].center
                    fg = self.theme.themeForeground  #(0x30, 0xe0, 0x30, 0xff)
                    bg = self.theme.themeBackground  #(0x20, 0x40, 0x20, 0x99)
                    width = 0
                    height = 0
                    # pygame.draw.line(surface, fg, (x1, y1), (x, y), 1)
                    for item in info:
                        w, h = Fonts.getTextSize('normal', item)
                        width = max(width, w)
                        height += h
                    if not moreIDs:
                        if x + width >= self.rect.width:
                            x -= width + 40
                        if y + 1 + height >= self.rect.height:
                            y -= height
                    surface.fill(bg, (x, y, width + 2, height + 2))
                    x += 1
                    tmpY = y + 1
                    for item in info:
                        textSrfc = Fonts.renderText('normal', item, 1, fg)
                        surface.blit(textSrfc, (x, tmpY))
                        tmpY += textSrfc.get_height()
                    x += width + 2

    def _drawApproachingFleetLine(self, surface, activeObjID):
        maxY = self._mapSurf.get_rect().height
        centerX, centerY = self._mapSurf.get_rect().center
        x, y, x1, y1 = self.star_map._fleetTarget[activeObjID]
        sx = int((x - self.star_map.currX) *
                 self.star_map.scale) + centerX + self.rect.left
        sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) +
                     centerY) + self.rect.top
        dx = int((x1 - self.star_map.currX) *
                 self.star_map.scale) + centerX + self.rect.left
        dy = maxY - (int((y1 - self.star_map.currY) * self.star_map.scale) +
                     centerY) + self.rect.top
        pygame.draw.line(surface, (0xff, 0xff, 0x00), (sx, sy), (dx, dy), 2)

    def _drawThickeningFleetOrderLines(self, surface, activeObjID):
        maxY = self._mapSurf.get_rect().height
        centerX, centerY = self._mapSurf.get_rect().center
        for x, y, x1, y1, color in self.star_map._fordersTarget[activeObjID]:
            sx = int((x - self.star_map.currX) *
                     self.star_map.scale) + centerX + self.rect.left
            sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) +
                         centerY) + self.rect.top
            dx = int((x1 - self.star_map.currX) *
                     self.star_map.scale) + centerX + self.rect.left
            dy = maxY - (int(
                (y1 - self.star_map.currY) * self.star_map.scale) +
                         centerY) + self.rect.top
            pygame.draw.line(surface, color, (sx, sy), (dx, dy), 2)

    def _drawFleetRangesTime(self, surface, activeObjID):
        maxY = self._mapSurf.get_rect().height
        centerX, centerY = self._mapSurf.get_rect().center
        x, y, maxRange, operRange, halfRange, speed, turns = self.star_map._fleetRanges[
            activeObjID]
        sx = int((x - self.star_map.currX) *
                 self.star_map.scale) + centerX + self.rect.left
        sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) +
                     centerY) + self.rect.top

        for i in xrange(1, turns / 6):
            rng = int(i * speed * self.star_map.scale)
            if rng > 1:
                pygame.draw.circle(surface, (0x70, 0x70, 0x80), (sx, sy), rng,
                                   1)
                textSrfc = Fonts.renderText(self.star_map.textSize,
                                            res.formatTime(i * 6), 1,
                                            (0x70, 0x70, 0x80),
                                            (0x00, 0x00, 0x00))
                surface.blit(textSrfc,
                             (sx - rng, sy - textSrfc.get_height() / 2))
                surface.blit(textSrfc,
                             (sx + rng, sy - textSrfc.get_height() / 2))
                surface.blit(textSrfc,
                             (sx - textSrfc.get_width() / 2, sy - rng))
                surface.blit(textSrfc, (sx - textSrfc.get_width() / 2,
                                        sy + rng - textSrfc.get_height()))
        rng = int(
            max(maxRange * self.star_map.scale, 0.2 * self.star_map.scale))
        if rng > 1:
            pygame.draw.circle(surface, (0xc0, 0x20, 0x20), (sx, sy), rng, 1)

    def _drawFleetRangesFuel(self, surface, activeObjID):
        maxY = self._mapSurf.get_rect().height
        centerX, centerY = self._mapSurf.get_rect().center
        x, y, maxRange, operRange, halfRange, speed, turns = self.star_map._fleetRanges[
            activeObjID]
        sx = int((x - self.star_map.currX) *
                 self.star_map.scale) + centerX + self.rect.left
        sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) +
                     centerY) + self.rect.top

        # fleet range based on fuel
        rng = int(
            max(maxRange * self.star_map.scale, 0.2 * self.star_map.scale))
        if rng > 1:
            pygame.draw.circle(surface, (0xc0, 0x20, 0x20), (sx, sy), rng, 1)
        rng = int(operRange * self.star_map.scale)
        if rng > 1:
            pygame.draw.circle(surface, (0x20, 0x80, 0x20), (sx, sy), rng, 1)
        rng = int(halfRange * self.star_map.scale)
        if rng > 1:
            pygame.draw.circle(surface, (0x20, 0x20, 0x80), (sx, sy), rng, 1)

    def _drawFleetRanges(self, surface, activeObjID):
        if pygame.key.get_mods() & pygame.KMOD_SHIFT:
            self._drawFleetRangesTime(surface, activeObjID)
        else:
            self._drawFleetRangesFuel(surface, activeObjID)

    def drawAdditions(self, surface):
        oldClip = surface.get_clip()
        surface.set_clip(self.rect)
        centerX, centerY = self._mapSurf.get_rect().center
        maxY = self._mapSurf.get_rect().height
        # highlight position circle
        if self.highlightPos:
            sx = int((self.highlightPos[0] - self.star_map.currX) *
                     self.star_map.scale) + centerX + self.rect.left
            sy = maxY - (int((self.highlightPos[1] - self.star_map.currY) *
                             self.star_map.scale) + centerY) + self.rect.top
            pygame.draw.circle(surface, (0xff, 0xff, 0xff), (sx, sy), 13, 2)
        # fleet range in case of selecting fleet orders
        if self.alwaysShowRangeFor and self.star_map._fleetRanges.has_key(
                self.alwaysShowRangeFor):
            self._drawFleetRangesFuel(surface, self.alwaysShowRangeFor)
        for activeObjID in self.activeObjIDs:
            if activeObjID and activeObjID in self.star_map._fleetTarget:
                self._drawApproachingFleetLine(surface, activeObjID)
            if activeObjID and activeObjID in self.star_map._fordersTarget:
                self._drawThickeningFleetOrderLines(surface, activeObjID)
            if activeObjID and activeObjID in self.star_map._fleetRanges:
                self._drawFleetRanges(surface, activeObjID)
        # restore clipping
        surface.set_clip(oldClip)

    def initHotbuttons(self):
        # key : [ key , state , x , y , dx, dy, value, tooltip ]
        # 'value' is "active state' gdata value or true
        self._hotbuttons = {
            'pzone': [
                'pzone', self.control_modes['control_areas'], 2, 2, 17, 13, 1,
                _('Player Zones (CTRL-P)')
            ],
            'civ': [
                'civ', self.control_modes['civilian_fleets'], 21, 2, 18, 13, 1,
                _('Civilian Ships (CTRL-H)')
            ],
            'lines': [
                'lines', self.control_modes['fleet_lines'], 41, 2, 18, 13, 1,
                _('Fleet Lines (CTRL-L)')
            ],
            'redir': [
                'redir', self.control_modes['redirects'], 61, 2, 18, 13, 1,
                _('Redirect Arrows (CTRL-R)')
            ],
            'scanner': [
                'scanner', self.control_modes['scanners'], 81, 2, 17, 13, 1,
                _('Scanners (CTRL-S)')
            ],
            'grid': [
                'grid', self.control_modes['map_grid'], 100, 2, 17, 13, 1,
                _('Grid (CTRL-G)')
            ],
            'alternate': [
                'alternate', self.control_modes['alternative_mode'], 119, 2,
                17, 13, 2,
                _('Alternate View (CTRL-A)')
            ],
            'ov_diplo': [
                'ov_diplo', False, 2, 17, 13, 13, gdata.OVERLAY_DIPLO,
                _('Overlay: Diplomacy')
            ],
            'ov_min': [
                'ov_min', False, 17, 17, 13, 13, gdata.OVERLAY_MIN,
                _('Overlay: Minerals')
            ],
            'ov_env': [
                'ov_env', False, 32, 17, 13, 13, gdata.OVERLAY_BIO,
                _('Overlay: Environment')
            ],
            'ov_slot': [
                'ov_slot', False, 47, 17, 13, 13, gdata.OVERLAY_SLOT,
                _('Overlay: Slots')
            ],
            'ov_morale': [
                'ov_morale', False, 62, 17, 13, 13, gdata.OVERLAY_MORALE,
                _('Overlay: Morale')
            ],
            'ov_fuel': [
                'ov_fuel', False, 77, 17, 13, 13, gdata.OVERLAY_DOCK,
                _('Overlay: Fuel and Repair')
            ],
            'ov_gate': [
                'ov_gate', False, 92, 17, 13, 13, gdata.OVERLAY_STARGATE,
                _('Overlay: Star Gate Speed')
            ],
            'ov_pirate': [
                'ov_pirate', False, 107, 17, 13, 13, gdata.OVERLAY_FAME,
                _('Overlay: Pirate Fame')
            ],
        }
        if self.control_modes['pirate_dialogs']:
            self._hotbuttons['ov_piratecolony'] = [
                'ov_piratecolony', False, 122, 17, 13, 13,
                gdata.OVERLAY_PIRATECOLONYCOST, 'Overlay: Pirate Colony Cost'
            ]
        self._oldOverlayHotbutton = False
        self._tempOverlayHotbutton = False
        self._hotbuttonRects = {}

    def toggleHotButtons(self, button):
        self.toggleTempButton(False)
        if (button[:3] == 'ov_'):  #overlay
            if self._oldOverlayHotbutton == button:
                self.star_map.overlayMode = gdata.OVERLAY_OWNER
                self._hotbuttons[button][1] = False
                self._oldOverlayHotbutton = False
            else:
                if self._oldOverlayHotbutton:
                    self._hotbuttons[self._oldOverlayHotbutton][1] = False
                self._hotbuttons[button][1] = True
                self.star_map.overlayMode = self._hotbuttons[button][6]
                self._oldOverlayHotbutton = button
        else:  #normal toggle
            if self._hotbuttons[button][1]:
                self._hotbuttons[button][1] = 0
            else:
                self._hotbuttons[button][1] = self._hotbuttons[button][
                    6]  # set standard value
            translation = {
                'pzone': 'control_areas',
                'civ': 'civilian_fleets',
                'lines': 'fleet_lines',
                'redir': 'redirects',
                'scanner': 'scanners',
                'grid': 'map_grid',
                'alternate': 'alternative_mode'
            }
            if button in translation:
                self.control_modes[
                    translation[button]] = self._hotbuttons[button][1]
        self.repaintHotbuttons = 1
        self.repaint_map = 1

    def toggleTempButton(self, pos=False):
        if pos:  # true unless we are no longer in the box, in which case we are resetting
            currentButton = self.detectButtonOverpass(pos)
            if currentButton == self._tempOverlayHotbutton: return
            if self._tempOverlayHotbutton:
                self._hotbuttons[self._tempOverlayHotbutton][
                    1] = not self._hotbuttons[self._tempOverlayHotbutton][1]
            if not currentButton:
                self.repaintHotbuttons = 1
                self._tempOverlayHotbutton = False
                return
            self._hotbuttons[currentButton][
                1] = not self._hotbuttons[currentButton][1]
            self._tempOverlayHotbutton = currentButton
        elif self._tempOverlayHotbutton:
            self._hotbuttons[self._tempOverlayHotbutton][
                1] = not self._hotbuttons[self._tempOverlayHotbutton][1]
            self._tempOverlayHotbutton = False
        self.repaintHotbuttons = 1

    def detectButtonOverpass(self, pos):
        for buttonkey in self._hotbuttonRects:
            #log.debug(self._hotbuttonRects[buttonkey][1],pos)
            if self._hotbuttonRects[buttonkey][1].collidepoint(pos):
                return buttonkey
        return False

    def processMB1Down(self, evt):
        # handle SHIFT click as MB3
        mods = pygame.key.get_mods()
        if mods & pygame.KMOD_SHIFT:
            return self.processMB3Down(evt)
        pos = evt.pos
        # show current position for debugging
        # log.debug(pos)
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                return ui.NoEvent
        if self.control_modes[
                'hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            return ui.NoEvent
        self.pressedObjIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                self.pressedObjIDs.append(objID)

        self.pressedBuoyObjIDs = []
        for objID in self._actBuoyAreas.keys():
            rect = self._actBuoyAreas[objID]
            if rect.collidepoint(pos):
                self.pressedBuoyObjIDs.append(objID)

        if self.pressedObjIDs or self.pressedBuoyObjIDs:
            return ui.NoEvent
        else:
            self.activeObjID = Const.OID_NONE
            return ui.NoEvent

    def processMB1Up(self, evt):
        # handle SHIFT click as MB3
        mods = pygame.key.get_mods()
        if mods & pygame.KMOD_SHIFT:
            return self.processMB3Up(evt)
        pos = evt.pos
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                self.star_map.currX, self.star_map.currY = self.miniMap.processMB1Up(
                    (pos[0] - self._miniMapRect.left,
                     self._miniMapRect.height - pos[1] +
                     self._miniMapRect.top))
                self.processMiniMapRect()
                self.repaint_map = 1
                return ui.NoEvent
        if self.control_modes[
                'hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            button = self.detectButtonOverpass(pos)
            if button:
                self.toggleHotButtons(button)
            return ui.NoEvent
        objIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                objIDs.append(objID)

        bObjIDs = []
        for objID in self._actBuoyAreas.keys():
            rect = self._actBuoyAreas[objID]
            if rect.collidepoint(pos):
                bObjIDs.append(objID)

        if (objIDs or bObjIDs) and (self.pressedObjIDs == objIDs
                                    or self.pressedBuoyObjIDs
                                    == bObjIDs) and self.action:
            if self.selectobject:
                self.setKeyObject(objIDs, bObjIDs)
                return ui.NoEvent
            self.gotoObject(objIDs, bObjIDs)
            return ui.NoEvent
        else:
            self.activeObjID = Const.OID_NONE
            return ui.NoEvent

    def gotoObject(self, objIDs, bObjIDs):
        if len(objIDs) + len(bObjIDs) == 1:
            if len(objIDs) == 1:
                if self.selectobject:
                    return objIDs[0]
                self.processAction(self.action, objIDs[0])
                self.pressedObjIDs = []
            else:
                if self.selectobject:
                    return Const.OID_NONE
                self.showBuoyDlg.display(bObjIDs[0])
                self.pressedBuoyObjIDs = []
        else:
            # multiple objects -> post pop-up menu
            items = []
            for objID in objIDs:
                obj = client.get(objID)
                if obj.type == Const.T_SYSTEM:
                    name = getattr(obj, "name", None)
                    name = _("System: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_WORMHOLE:
                    name = getattr(obj, "name", None)
                    name = _("Worm hole: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_PLANET:
                    name = getattr(obj, "name", None)
                    name = _("Planet: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_FLEET:
                    if hasattr(obj, 'customname') and obj.customname:
                        name = obj.customname
                    else:
                        name = getattr(obj, "name", None)
                    name = _("Fleet: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                else:
                    name = _("Unknown object [ID: %d]") % obj.oid
                item = ui.Item(name, action="onObjectSelected", data=objID)
                items.append(item)
            for objID in bObjIDs:
                obj = client.get(objID)
                if obj.type == Const.T_SYSTEM:
                    name = getattr(obj, "name", None)
                    name = _("Buoy on system: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_WORMHOLE:
                    name = getattr(obj, "name", None)
                    name = _("Buoy on worm hole: %s [ID: %d]") % (
                        name or res.getUnknownName(), obj.oid)
                else:
                    name = _("Buoy on unknown object [ID: %d]") % obj.oid
                item = ui.Item(name, action="onBuoySelected", data=objID)
                items.append(item)
            self.popup.items = items
            self.popup.show()
        if self.selectobject:
            return Const.OID_NONE

    def onObjectSelected(self, widget, action, data):
        self.processAction(self.action, data)

    def onBuoySelected(self, widget, action, data):
        self.showBuoyDlg.display(data)

    def processMB3Down(self, evt):
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(evt.pos):
                return ui.NoEvent
        self._newCurrXY = 1
        return ui.NoEvent

    def processMB3Up(self, evt):
        if self._newCurrXY:
            x, y = evt.pos
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX -= float(centerX - x) / self.star_map.scale
            self.star_map.currY += float(centerY - y) / self.star_map.scale
            self.processMiniMapRect()
            self.repaint_map = 1
            self._newCurrXY = 0
        return ui.NoEvent

    def processMiniMapRect(self):
        if self.control_modes['minimap']:
            rect = self._mapSurf.get_rect()
            self.miniMap.moveRect(self.star_map.currX, self.star_map.currY,
                                  rect.width / self.star_map.scale,
                                  rect.height / self.star_map.scale)

    def _rescaleMap(self, evt, delta):
        if not 10 < self.star_map.scale + delta < 80:
            return ui.NoEvent
        try:
            x, y = evt.pos
        except AttributeError:
            # keyboard rescale
            x, y = pygame.mouse.get_pos()
        centerX, centerY = self._mapSurf.get_rect().center
        sign = cmp(delta, 0)
        self.star_map.currX -= sign * float(centerX - x) * (
            1 / self.star_map.scale - 1 / (self.star_map.scale + delta))
        self.star_map.currY += sign * float(centerY - y) * (
            1 / self.star_map.scale - 1 / (self.star_map.scale + delta))
        self.star_map.scale += delta
        self.star_map.textSize = ['small', 'normal',
                                  'large'][bisect.bisect([40, 60],
                                                         self.star_map.scale)]
        self.repaint_map = 1
        self.processMiniMapRect()

    def processMWUp(self, evt):
        return self._rescaleMap(evt, 5)

    def processMWDown(self, evt):
        return self._rescaleMap(evt, -5)

    def processMMotion(self, evt):
        pos = evt.pos
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                #log.debug('Minimap Rect Position');
                return ui.NoEvent
        if self.control_modes[
                'hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            #should give hotkey tooltips for this eventually
            self.toggleTempButton(pos)
            return ui.NoEvent
        elif self._tempOverlayHotbutton:  # cleanup if cursor not in zone
            self.toggleTempButton(False)
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                self.activeObjID = objID
                self.activeObjIDs.append(objID)
                self.activePos = pos
        return ui.NoEvent

    # put actually processing of key in "processKeyUp" using key pressed during "processKeyDown" to prevent erroneous double press detection when holding down CTRL, SHIFT, or ALT keys
    def processKeyDown(self, evt):
        self.keyPress = evt
        if self.callEventHandler:
            self.callEventHandler.processKeyDown(evt)
        return ui.NoEvent

    def _processObjectHotkeys(self, evt):
        if pygame.key.get_mods() & pygame.KMOD_CTRL:
            log.debug('Set Key:', evt.key)
            if gdata.config.defaults.displayhelp != 'no':
                self.KeyModHelp.show()
            self.selectobject = True
            self.setKey = evt.key
            self.app.setStatus(_("Select object to hotkey. ESC to cancel."))
        elif pygame.key.get_mods() & pygame.KMOD_SHIFT:
            log.debug('Focus Key:', evt.key)
            self.focusOnKeyObject(evt.key)
        else:
            log.debug('Goto Key:', evt.key)
            self.gotoKeyObject(evt.key)
        return ui.NoEvent

    def processKeyUp(self, evt2):
        if self.callEventHandler:
            self.callEventHandler.processKeyUp(evt2)
        evt = self.keyPress
        if not self.keyPress: return ui.NoEvent
        self.keyPress = False
        # ==== Object Hotkeys ====
        #I have not found unicode escape characters for Ctrl-0 through Ctrl-9, so using direct key reference (less preferred due to international keyboards)
        if evt.key in [49, 50, 51, 52, 53, 54, 55, 56, 57, 48]:
            self._processObjectHotkeys(evt)
        # ==== Map and Dialog Hotkeys ====
        elif evt.key == pygame.K_ESCAPE and self.selectobject:
            log.debug('Canceled Key')
            if self.selectobject:
                self.app.setStatus(_("Ready."))
                self.selectobject = False
            return ui.NoEvent
        if not evt.unicode:
            # force update
            self.star_map.scale += 1
            self.star_map.scale -= 1
            return ui.NoEvent
        if evt.unicode in u'+=':
            self._rescaleMap(evt, 5)
        elif evt.unicode == u'-':
            self._rescaleMap(evt, -5)
        # Space Bar - Recenter
        elif evt.unicode == u' ':
            x, y = pygame.mouse.get_pos()
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX -= float(centerX - x) / self.star_map.scale
            self.star_map.currY += float(centerY - y) / self.star_map.scale
            self.repaint_map = 1
            self._newCurrXY = 0
        # ==== Standard Hotkeys ====
        # Reserve CTRL-C for copy (future editor support)
        # Ctrl+F
        toggleMapping = {
            u'\x01': 'alternate',  # Alternative system info
            u'\x07': 'grid',  # Grid
            u'\x08': 'civ',  # Civilian ships
            u'\x0C': 'lines',  # Fleet lines
            u'\x10': 'pzone',  # Control areas
            u'\x12': 'redir',  # Redirections
            u'\x13': 'scanner'
        }  # Scanner circles
        if evt.unicode in toggleMapping and pygame.key.get_mods(
        ) & pygame.KMOD_CTRL:
            self.toggleHotButtons(toggleMapping[evt.unicode])
        # Ctrl+F to open the search (find) dialog
        elif evt.unicode == u'\x06' and pygame.key.get_mods(
        ) & pygame.KMOD_CTRL:
            self.searchDlg.display()
        # Reserve CTRL-V,X,and Z for paste, cut, and undo (future editor support)
        # ==== Else ====
        else:
            # force update
            self.star_map.scale += 1
            self.star_map.scale -= 1
        return ui.NoEvent

    def setKeyObject(self, objIDs, bObjIDs):
        objID = self.gotoObject(objIDs, bObjIDs)
        log.debug('Setting Key Object To:', objID)
        self.app.setStatus(_("Ready."))
        self.selectobject = False
        if (objID == Const.OID_NONE):
            return
        obj = client.get(objID)
        if obj.type in (Const.T_SYSTEM, Const.T_PLANET, Const.T_FLEET):
            gdata.objectFocus[self.setKey] = objID

    def gotoKeyObject(self, evtkey):
        if evtkey in gdata.objectFocus:
            objID = gdata.objectFocus[evtkey]
            self.processAction(self.action, objID)
            self.pressedObjIDs = []

    def focusOnKeyObject(self, evtkey):
        if evtkey in gdata.objectFocus:
            objID = gdata.objectFocus[evtkey]
            obj = client.get(objID, noUpdate=1)
            if hasattr(obj, "x"):
                gdata.mainGameDlg.win.vStarMap.highlightPos = (obj.x, obj.y)
                gdata.mainGameDlg.win.vStarMap.setPos(obj.x, obj.y)

    def onMouseOver(self):
        self.mouseOver = 1
        try:
            self.parent.parent.setFocus(self)
        except:
            log.debug('Cannot refocus on starmap')

    def setPos(self, x, y):
        self.star_map.currX = x
        self.star_map.currY = y
        self.repaint_map = 1
        self.processMiniMapRect()
Example #3
0
    def __init__(self, parent, **kwargs):
        Widget.__init__(self, parent)
        self.searchDlg = SearchDlg(self.app)
        self.searchDlg.mapWidget = self
        # data
        self.control_modes = {}  # mutable, thus updating here will update StarMap
        self.updateConfigModes()
        self.control_modes['systems'] = 1
        self.control_modes['planets'] = 1
        self.control_modes['fleets'] = 1
        self.control_modes['civilian_fleets'] = 1
        self.control_modes['pirate_areas'] = 1
        self.control_modes['hotbuttons'] = 1
        self.control_modes['minimap'] = 1
        self.control_modes['redirects'] = 1
        self.control_modes['map_grid_coords'] = 1
        self.control_modes['map_grid'] = 1
        self.control_modes['scanners'] = 1
        self.control_modes['fleet_lines'] = 1
        self.control_modes['gate_systems'] = 1
        self.control_modes['alternative_view'] = 1
        self.control_modes['control_areas'] = 0
        self.control_modes['pirate_dialogs'] = 0  # only for pirate, obv.
        # more data
        self.highlightPos = None
        self.alwaysShowRangeFor = None
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        self.pressedObjIDs = []
        self._newCurrXY = 0
        self.activePos = (0, 0)

        # the map itself!
        self.star_map = StarMap(self.control_modes)
        self.action = None
        self.callEventHandler = None
        self.showBuoyDlg = ShowBuoyDlg(self.app)
        self.KeyModHelp = KeyModHelp(self.app)
        self._miniMapRect = pygame.Rect(0, 20, 175, 175)
        self._hotbuttonsZone = pygame.Rect(0,0,0,0)
        self.initHotbuttons()
        self.miniMap = MiniMap(self._miniMapRect.width, self._miniMapRect.height)
        # flags
        self.processKWArguments(kwargs)
        parent.registerWidget(self)
        # popup menu
        self.popup = ui.Menu(self.app, title = _("Select object"))
        self.popup.subscribeAction("*", self)
        # overlay system
        self._overlayZone = False
        # key setting system
        self.selectobject = False
        self.setKey = False
        # commands
        self.keyPress = False
        # map - produced by StarMap draw method
        self._mapSurf = None
        self._actAreas = {}
        self._actBuoyAreas = {}
        # dirty flag
        self.repaint_map = True
Example #4
0
class StarMapWidget(Widget):

    def __init__(self, parent, **kwargs):
        Widget.__init__(self, parent)
        self.searchDlg = SearchDlg(self.app)
        self.searchDlg.mapWidget = self
        # data
        self.control_modes = {}  # mutable, thus updating here will update StarMap
        self.updateConfigModes()
        self.control_modes['systems'] = 1
        self.control_modes['planets'] = 1
        self.control_modes['fleets'] = 1
        self.control_modes['civilian_fleets'] = 1
        self.control_modes['pirate_areas'] = 1
        self.control_modes['hotbuttons'] = 1
        self.control_modes['minimap'] = 1
        self.control_modes['redirects'] = 1
        self.control_modes['map_grid_coords'] = 1
        self.control_modes['map_grid'] = 1
        self.control_modes['scanners'] = 1
        self.control_modes['fleet_lines'] = 1
        self.control_modes['gate_systems'] = 1
        self.control_modes['alternative_view'] = 1
        self.control_modes['control_areas'] = 0
        self.control_modes['pirate_dialogs'] = 0  # only for pirate, obv.
        # more data
        self.highlightPos = None
        self.alwaysShowRangeFor = None
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        self.pressedObjIDs = []
        self._newCurrXY = 0
        self.activePos = (0, 0)

        # the map itself!
        self.star_map = StarMap(self.control_modes)
        self.action = None
        self.callEventHandler = None
        self.showBuoyDlg = ShowBuoyDlg(self.app)
        self.KeyModHelp = KeyModHelp(self.app)
        self._miniMapRect = pygame.Rect(0, 20, 175, 175)
        self._hotbuttonsZone = pygame.Rect(0,0,0,0)
        self.initHotbuttons()
        self.miniMap = MiniMap(self._miniMapRect.width, self._miniMapRect.height)
        # flags
        self.processKWArguments(kwargs)
        parent.registerWidget(self)
        # popup menu
        self.popup = ui.Menu(self.app, title = _("Select object"))
        self.popup.subscribeAction("*", self)
        # overlay system
        self._overlayZone = False
        # key setting system
        self.selectobject = False
        self.setKey = False
        # commands
        self.keyPress = False
        # map - produced by StarMap draw method
        self._mapSurf = None
        self._actAreas = {}
        self._actBuoyAreas = {}
        # dirty flag
        self.repaint_map = True


    def updateConfigModes(self):
        self.control_modes['redirects'] = gdata.config.defaults.showredirects is not 'no'
        self.control_modes['coords'] = gdata.config.defaults.showcoords is not 'no'
        self.control_modes['map_grid'] = gdata.config.defaults.showmapgrid is not 'no'
        self.control_modes['scanners'] = gdata.config.defaults.showmapscanners is not 'no'
        self.control_modes['fleet_lines'] = gdata.config.defaults.showfleetlines is not 'no'
        self.control_modes['gate_systems'] = gdata.config.defaults.showgatesystems is not 'no'
        self.control_modes['alternative_mode'] = gdata.config.defaults.alternateviewmode is not 'no'
        self.control_modes['control_areas'] = gdata.config.defaults.showplayerzones is not 'no'
        self.control_modes['minimap'] = gdata.config.defaults.showminimap is not 'yes'

    def precompute(self):
        self.star_map.rect = self.rect
        self.star_map.precompute()
        player = client.getPlayer()
        if (player.type == Const.T_PIRPLAYER or\
            player.type == Const.T_AIPIRPLAYER) and not self.control_modes['pirate_dialogs']:
            self.control_modes['pirate_dialogs'] = True
            if self.control_modes['hotbuttons']:
                self.initHotbuttons() #reinit to add the pirate button
        self.miniMap.precompute()
        # self dirty flag
        self.repaint_map = 1

    def save(self, append='', chronicle_shot=False):
        name = ("%s.png" % append)
        if chronicle_shot:
            # print whole galaxy, centered over black hole
            # star_map has much more information about the galaxy, thus handling this request
            new_surf = self.star_map.chronicle_draw()
            pygame.image.save(new_surf, name)
        else:
            # print current player view
            new_surf, empty, empty = self.star_map.draw(pygame.Surface((self.star_map.rect.width,
                                                                        self.star_map.rect.height)))
            pygame.image.save(new_surf, name)
        return name


    def draw(self, surface):
        self._miniMapRect.left = self.rect.width - self._miniMapRect.width
        self._miniMapRect.top = self.rect.top
        if not self._mapSurf:
            mapSurf = pygame.Surface(self.rect.size, pygame.SWSURFACE, surface)
        else:
            mapSurf = self._mapSurf

        if self.repaint_map:
            mapSurf, self._actAreas, self._actBuoyAreas  = self.star_map.draw(mapSurf)
            # For some reason, this is not just optimization, it's mandatory for proper
            # function. BUG?!
            self.repaint_map = 0
            self.repaintHotbuttons = 1
        if self.repaintHotbuttons and self.control_modes['hotbuttons']:
            self.drawHotbuttons(mapSurf)
            self.repaintHotbuttons = 0
        # blit cached map
        surface.blit(mapSurf, self.rect)
        self._mapSurf = mapSurf

        if self.control_modes['minimap']:
            self.miniMap.draw(surface, self._miniMapRect.left, self._miniMapRect.top)
            if self.miniMap.needRect():
                self.processMiniMapRect()
                self.miniMap.draw(surface, self._miniMapRect.left, self._miniMapRect.top)
        # additional information (ranges, fleet lines, selected system sign)
        self.drawAdditions(surface)

        self.drawPopups(surface)
        return self.rect

    def drawHotbuttons(self, mapSurf):
        rect = mapSurf.get_rect()
        bottom = rect.bottom
        right = rect.right
        dx = 137
        dy = 46
        top = bottom - dy - 1
        left = right - dx - 1
        self._hotbuttonsZone.top = top + self.rect.top
        self._hotbuttonsZone.left = left
        self._hotbuttonsZone.width = dx
        self._hotbuttonsZone.height = dy

        pygame.draw.rect(mapSurf,(0x00, 0x00, 0x90),(left-1,top-1,dx+2,dy+2))
        pygame.draw.rect(mapSurf,(0x33, 0x33, 0x66),(left,top,dx,dy))

        for buttonkey in self._hotbuttons:
            button = self._hotbuttons[buttonkey]
            self._hotbuttonRects[button[0]] = [button[0],pygame.Rect(button[2]+self._hotbuttonsZone.left,button[3]+self._hotbuttonsZone.top+15,button[4],button[5])]
            img = res.getButton(button[0],button[1])
            if (button[1] and not (self._tempOverlayHotbutton and self._tempOverlayHotbutton == button[0])) or (not button[1] and self._tempOverlayHotbutton and self._tempOverlayHotbutton == button[0]):
                pygame.draw.rect(mapSurf,(0x90, 0x90, 0x90),(left+button[2]-1,top+15+button[3]-1,button[4]+2,button[5]+2),1)
            mapSurf.blit(img,(left+button[2],top+15+button[3]))
        if self._tempOverlayHotbutton:
            text = self._hotbuttons[self._tempOverlayHotbutton][7]
            textSrfc = Fonts.renderText(self.star_map.textSize, text, 1, (0xEF, 0xEF, 0xEF))
            mapSurf.blit(textSrfc, (left+2,top+1))

    def drawPopups(self, surface):
        # draw popups
        moreIDs = len(self.activeObjIDs) > 1
        if not moreIDs:
            x, y = self.activePos
            x += 20
        else:
            x = self.rect.left + 2
            y = self.rect.top
        if not pygame.key.get_mods() & pygame.KMOD_SHIFT:
            for activeObjID in self.activeObjIDs:
                index = 0
                if self.star_map._popupInfo.has_key(activeObjID):
                    # put pop up info on the screen
                    info = self.star_map._popupInfo[activeObjID]
                    # x1, y1 = self._actAreas[self.activeObjID].center
                    fg = self.theme.themeForeground #(0x30, 0xe0, 0x30, 0xff)
                    bg = self.theme.themeBackground #(0x20, 0x40, 0x20, 0x99)
                    width = 0
                    height = 0
                    # pygame.draw.line(surface, fg, (x1, y1), (x, y), 1)
                    for item in info:
                        w, h = Fonts.getTextSize('normal', item)
                        width = max(width, w)
                        height += h
                    if not moreIDs:
                        if x + width >= self.rect.width:
                            x -= width + 40
                        if y + 1 + height >= self.rect.height:
                            y -= height
                    surface.fill(bg, (x, y, width + 2, height + 2))
                    x += 1
                    tmpY = y + 1
                    for item in info:
                        textSrfc = Fonts.renderText('normal', item, 1, fg)
                        surface.blit(textSrfc, (x, tmpY))
                        tmpY += textSrfc.get_height()
                    x += width + 2

    def drawAdditions(self, surface):
        oldClip = surface.get_clip()
        surface.set_clip(self.rect)
        centerX, centerY = self._mapSurf.get_rect().center
        maxY = self._mapSurf.get_rect().height
        # highlight position circle
        if self.highlightPos:
            sx = int((self.highlightPos[0] - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
            sy = maxY - (int((self.highlightPos[1] - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
            pygame.draw.circle(surface, (0xff, 0xff, 0xff), (sx, sy), 13, 2)
        # fleet range in case of selecting fleet orders
        if self.alwaysShowRangeFor and self.star_map._fleetRanges.has_key(self.alwaysShowRangeFor):
            x, y, maxRange, operRange, halfRange, speed, turns = self.star_map._fleetRanges[self.alwaysShowRangeFor]
            sx = int((x - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
            sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
            rng = max(maxRange * self.star_map.scale, 0.2 * self.star_map.scale)
            if rng > 1:
                pygame.draw.circle(surface, (0xc0, 0x20, 0x20), (sx, sy), int(rng), 1)
            rng = operRange * self.star_map.scale
            if rng > 1:
                pygame.draw.circle(surface, (0x20, 0x80, 0x20), (sx, sy), int(rng), 1)
            rng = halfRange * self.star_map.scale
            if rng > 1:
                pygame.draw.circle(surface, (0x20, 0x20, 0x80), (sx, sy), int(rng), 1)
        for activeObjID in self.activeObjIDs:
            if activeObjID and activeObjID in self.star_map._fleetTarget:
                # approaching fleet line
                x, y, x1, y1 = self.star_map._fleetTarget[activeObjID]
                sx = int((x - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
                sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
                dx = int((x1 - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
                dy = maxY - (int((y1 - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
                pygame.draw.line(surface, (0xff, 0xff, 0x00), (sx, sy), (dx, dy), 2)
            if activeObjID and activeObjID in self.star_map._fordersTarget:
                # thickening fleet order lines
                for x, y, x1, y1, color in self.star_map._fordersTarget[activeObjID]:
                    sx = int((x - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
                    sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
                    dx = int((x1 - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
                    dy = maxY - (int((y1 - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
                    pygame.draw.line(surface, color, (sx, sy), (dx, dy), 2)
            if activeObjID and activeObjID in self.star_map._fleetRanges:
                x, y, maxRange, operRange, halfRange, speed, turns = self.star_map._fleetRanges[activeObjID]
                sx = int((x - self.star_map.currX) * self.star_map.scale) + centerX + self.rect.left
                sy = maxY - (int((y - self.star_map.currY) * self.star_map.scale) + centerY) + self.rect.top
                if pygame.key.get_mods() & pygame.KMOD_SHIFT:
                    # fleet ranges stepped by 6 turns
                    for i in xrange(1, turns / 6):
                        rng = int(i * speed * self.star_map.scale)
                        if rng > 1:
                            pygame.draw.circle(surface, (0x70, 0x70, 0x80), (sx, sy), rng, 1)
                            textSrfc = Fonts.renderText(self.star_map.textSize, res.formatTime(i * 6), 1, (0x70, 0x70, 0x80), (0x00, 0x00, 0x00))
                            surface.blit(textSrfc, (sx - rng, sy - textSrfc.get_height() / 2))
                            surface.blit(textSrfc, (sx + rng, sy - textSrfc.get_height() / 2))
                            surface.blit(textSrfc, (sx - textSrfc.get_width() / 2, sy - rng))
                            surface.blit(textSrfc, (sx - textSrfc.get_width() / 2, sy + rng - textSrfc.get_height()))
                    rng = int(max(maxRange * self.star_map.scale, 0.2 * self.star_map.scale))
                    if rng > 1:
                        pygame.draw.circle(surface, (0xc0, 0x20, 0x20), (sx, sy), rng, 1)
                else:
                    # fleet range based on fuel
                    rng = int(max(maxRange * self.star_map.scale, 0.2 * self.star_map.scale))
                    if rng > 1:
                        pygame.draw.circle(surface, (0xc0, 0x20, 0x20), (sx, sy), rng, 1)
                    rng = int(operRange * self.star_map.scale)
                    if rng > 1:
                        pygame.draw.circle(surface, (0x20, 0x80, 0x20), (sx, sy), rng, 1)
                    rng = int(halfRange * self.star_map.scale)
                    if rng > 1:
                        pygame.draw.circle(surface, (0x20, 0x20, 0x80), (sx, sy), rng, 1)
        # restore clipping
        surface.set_clip(oldClip)

    def initHotbuttons(self):
        # key : [ key , state , x , y , dx, dy, value, tooltip ]
        # 'value' is "active state' gdata value or true
        self._hotbuttons = {
            'pzone': ['pzone',self.control_modes['control_areas'],2,2,17,13, 1,_('Player Zones (CTRL-P)')],
            'civ': ['civ',self.control_modes['civilian_fleets'],21,2,18,13, 1,_('Civilian Ships (CTRL-H)')],
            'lines': ['lines',self.control_modes['fleet_lines'],41,2,18,13, 1,_('Fleet Lines (CTRL-L)')],
            'redir': ['redir',self.control_modes['redirects'],61,2,18,13, 1,_('Redirect Arrows (CTRL-R)')],
            'scanner': ['scanner',self.control_modes['scanners'],81,2,17,13, 1,_('Scanners (CTRL-S)')],
            'grid': ['grid',self.control_modes['map_grid'],100,2,17,13, 1,_('Grid (CTRL-G)')],
            'alternate': ['alternate',self.control_modes['alternative_mode'],119,2,17,13, 2,_('Alternate View (CTRL-A)')],
            'ov_diplo': ['ov_diplo',False,2,17,13,13, gdata.OVERLAY_DIPLO,_('Overlay: Diplomacy')],
            'ov_min': ['ov_min',False,17,17,13,13, gdata.OVERLAY_MIN,_('Overlay: Minerals')],
            'ov_env': ['ov_env',False,32,17,13,13, gdata.OVERLAY_BIO,_('Overlay: Environment')],
            'ov_slot': ['ov_slot',False,47,17,13,13, gdata.OVERLAY_SLOT,_('Overlay: Slots')],
            'ov_morale': ['ov_morale',False,62,17,13,13, gdata.OVERLAY_MORALE,_('Overlay: Morale')],
            'ov_fuel': ['ov_fuel',False,77,17,13,13, gdata.OVERLAY_DOCK,_('Overlay: Fuel and Repair')],
            'ov_gate': ['ov_gate',False,92,17,13,13, gdata.OVERLAY_STARGATE,_('Overlay: Star Gate Speed')],
            'ov_pirate': ['ov_pirate',False,107,17,13,13, gdata.OVERLAY_FAME,_('Overlay: Pirate Fame')],
        }
        if self.control_modes['pirate_dialogs']:
            self._hotbuttons['ov_piratecolony'] = ['ov_piratecolony',False,122,17,13,13, gdata.OVERLAY_PIRATECOLONYCOST,'Overlay: Pirate Colony Cost']
        self._oldOverlayHotbutton = False;
        self._tempOverlayHotbutton = False;
        self._hotbuttonRects = {}

    def toggleHotbuttons(self,button):
        self.toggleTempButton(False)
        if (button[:3] == 'ov_'): #overlay
            if self._oldOverlayHotbutton == button:
                self.star_map.overlayMode = gdata.OVERLAY_OWNER
                self._hotbuttons[button][1] = False
                self._oldOverlayHotbutton = False
            else:
                if self._oldOverlayHotbutton:
                    self._hotbuttons[self._oldOverlayHotbutton][1] = False
                self._hotbuttons[button][1] = True
                self.star_map.overlayMode = self._hotbuttons[button][6]
                self._oldOverlayHotbutton = button
        else: #normal toggle
            if self._hotbuttons[button][1]:
                self._hotbuttons[button][1] = 0
            else:
                self._hotbuttons[button][1] = self._hotbuttons[button][6] # set standard value
            if button == 'pzone':
                self.control_modes['control_areas'] = self._hotbuttons[button][1]
            elif button == 'civ':
                self.control_modes['civilian_fleets'] = self._hotbuttons[button][1]
            elif button == 'lines':
                self.control_modes['fleet_lines'] = self._hotbuttons[button][1]
            elif button == 'redir':
                self.control_modes['redirects'] = self._hotbuttons[button][1]
            elif button == 'scanner':
                self.control_modes['scanners'] = self._hotbuttons[button][1]
            elif button == 'grid':
                self.control_modes['map_grid'] = self._hotbuttons[button][1]
            elif button == 'alternate':
                self.control_modes['alternative_mode'] = self._hotbuttons[button][1]
        self.repaintHotbuttons = 1
        self.repaint_map = 1

    def toggleTempButton(self,pos=False):
        if pos: # true unless we are no longer in the box, in which case we are resetting
            currentButton = self.detectButtonOverpass(pos)
            if currentButton == self._tempOverlayHotbutton: return
            if self._tempOverlayHotbutton:
                self._hotbuttons[self._tempOverlayHotbutton][1] = not self._hotbuttons[self._tempOverlayHotbutton][1]
            if not currentButton:
                self.repaintHotbuttons = 1
                self._tempOverlayHotbutton = False
                return
            self._hotbuttons[currentButton][1] = not self._hotbuttons[currentButton][1]
            self._tempOverlayHotbutton = currentButton
        elif self._tempOverlayHotbutton:
            self._hotbuttons[self._tempOverlayHotbutton][1] = not self._hotbuttons[self._tempOverlayHotbutton][1]
            self._tempOverlayHotbutton = False
        self.repaintHotbuttons = 1

    def detectButtonOverpass(self,pos):
        for buttonkey in self._hotbuttonRects:
            #log.debug(self._hotbuttonRects[buttonkey][1],pos)
            if self._hotbuttonRects[buttonkey][1].collidepoint(pos): return buttonkey
        return False

    def processMB1Down(self, evt):
        # handle SHIFT click as MB3
        mods = pygame.key.get_mods()
        if mods & pygame.KMOD_SHIFT:
            return self.processMB3Down(evt)
        pos = evt.pos
        # show current position for debugging
        # log.debug(pos)
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                return ui.NoEvent
        if self.control_modes['hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            return ui.NoEvent
        self.pressedObjIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                self.pressedObjIDs.append(objID)

        self.pressedBuoyObjIDs = []
        for objID in self._actBuoyAreas.keys():
            rect = self._actBuoyAreas[objID]
            if rect.collidepoint(pos):
                self.pressedBuoyObjIDs.append(objID)

        if self.pressedObjIDs or self.pressedBuoyObjIDs:
            return ui.NoEvent
        else:
            self.activeObjID = Const.OID_NONE
            return ui.NoEvent

    def processMB1Up(self, evt):
        # handle SHIFT click as MB3
        mods = pygame.key.get_mods()
        if mods & pygame.KMOD_SHIFT:
            return self.processMB3Up(evt)
        pos = evt.pos
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                self.star_map.currX, self.star_map.currY = self.miniMap.processMB1Up((pos[0] - self._miniMapRect.left, self._miniMapRect.height - pos[1] + self._miniMapRect.top))
                self.processMiniMapRect()
                self.repaint_map = 1
                return ui.NoEvent
        if self.control_modes['hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            button = self.detectButtonOverpass(pos)
            if button:
                self.toggleHotbuttons(button)
            return ui.NoEvent
        objIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                objIDs.append(objID)

        bObjIDs = []
        for objID in self._actBuoyAreas.keys():
            rect = self._actBuoyAreas[objID]
            if rect.collidepoint(pos):
                bObjIDs.append(objID)

        if (objIDs or bObjIDs) and (self.pressedObjIDs == objIDs or self.pressedBuoyObjIDs == bObjIDs) and self.action:
            if self.selectobject:
                self.setKeyObject(objIDs,bObjIDs)
                return ui.NoEvent
            self.gotoObject(objIDs,bObjIDs)
            return ui.NoEvent
        else:
            self.activeObjID = Const.OID_NONE
            return ui.NoEvent

    def gotoObject(self,objIDs,bObjIDs):
        if len(objIDs) + len(bObjIDs) == 1:
            if len(objIDs) == 1:
                if self.selectobject:
                    return objIDs[0]
                self.processAction(self.action, objIDs[0])
                self.pressedObjIDs = []
            else:
                if self.selectobject:
                    return Const.OID_NONE
                self.showBuoyDlg.display(bObjIDs[0])
                self.pressedBuoyObjIDs = []
        else:
            # multiple objects -> post pop-up menu
            items = []
            for objID in objIDs:
                obj = client.get(objID)
                if obj.type == Const.T_SYSTEM:
                    name = getattr(obj, "name", None)
                    name = _("System: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_WORMHOLE:
                    name = getattr(obj, "name", None)
                    name = _("Worm hole: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_PLANET:
                    name = getattr(obj, "name", None)
                    name = _("Planet: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_FLEET:
                    if hasattr(obj,'customname') and obj.customname:
                        name = obj.customname
                    else:
                        name = getattr(obj, "name", None)
                    name = _("Fleet: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_ASTEROID:
                    name = getattr(obj, "name", None)
                    name = _("Asteroid: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                else:
                    name = _("Unknown object [ID: %d]") % obj.oid
                item = ui.Item(name, action = "onObjectSelected", data = objID)
                items.append(item)
            for objID in bObjIDs:
                obj = client.get(objID)
                if obj.type == Const.T_SYSTEM:
                    name = getattr(obj, "name", None)
                    name = _("Buoy on system: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                elif obj.type == Const.T_WORMHOLE:
                    name = getattr(obj, "name", None)
                    name = _("Buoy on worm hole: %s [ID: %d]") % (name or res.getUnknownName(), obj.oid)
                else:
                    name = _("Buoy on unknown object [ID: %d]") % obj.oid
                item = ui.Item(name, action = "onBuoySelected", data = objID)
                items.append(item)
            self.popup.items = items
            self.popup.show()
        if self.selectobject:
            return Const.OID_NONE

    def onObjectSelected(self, widget, action, data):
        self.processAction(self.action, data)

    def onBuoySelected(self, widget, action, data):
        self.showBuoyDlg.display(data)

    def processMB3Down(self, evt):
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(evt.pos):
                return ui.NoEvent
        self._newCurrXY = 1
        return ui.NoEvent

    def processMB3Up(self, evt):
        if self._newCurrXY:
            x, y = evt.pos
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX -= float(centerX - x) / self.star_map.scale
            self.star_map.currY += float(centerY - y) / self.star_map.scale
            self.processMiniMapRect()
            self.repaint_map = 1
            self._newCurrXY = 0
        return ui.NoEvent

    def processMiniMapRect(self):
        if self.control_modes['minimap']:
            rect = self._mapSurf.get_rect()
            self.miniMap.moveRect(self.star_map.currX, self.star_map.currY, rect.width / self.star_map.scale, rect.height / self.star_map.scale)

    def processMWUp(self, evt):
        if self.star_map.scale < 80:
            x, y = evt.pos
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX -= float(centerX - x) * (1/ self.star_map.scale - 1 / (self.star_map.scale+5))
            self.star_map.currY += float(centerY - y) * (1/ self.star_map.scale - 1 / (self.star_map.scale+5))
            self.star_map.scale += 5
            if self.star_map.scale > 60:
                self.star_map.textSize = 'large'
            elif self.star_map.scale > 40:
                self.star_map.textSize = 'normal'
            else:
                self.star_map.textSize = 'small'
            self.repaint_map = 1
            self.processMiniMapRect()
        return ui.NoEvent

    def processMWDown(self, evt):
        if self.star_map.scale > 10:
            x, y = evt.pos
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX += float(centerX - x) * (1/ self.star_map.scale - 1 / (self.star_map.scale+5))
            self.star_map.currY -= float(centerY - y) * (1/ self.star_map.scale - 1 / (self.star_map.scale+5))
            self.star_map.scale -= 5
            if self.star_map.scale > 60:
                self.star_map.textSize = 'large'
            elif self.star_map.scale > 40:
                self.star_map.textSize = 'normal'
            else:
                self.star_map.textSize = 'small'
            self.repaint_map = 1
            self.processMiniMapRect()
        return ui.NoEvent

    def processMMotion(self, evt):
        pos = evt.pos
        if self.control_modes['minimap']:
            if self._miniMapRect.collidepoint(pos):
                #log.debug('Minimap Rect Position');
                return ui.NoEvent
        if self.control_modes['hotbuttons'] and self._hotbuttonsZone.collidepoint(pos):
            #should give hotkey tooltips for this eventually
            self.toggleTempButton(pos)
            return ui.NoEvent
        elif self._tempOverlayHotbutton: # cleanup if cursor not in zone
            self.toggleTempButton(False)
        self.activeObjID = Const.OID_NONE
        self.activeObjIDs = []
        for objID in self._actAreas.keys():
            rect = self._actAreas[objID]
            if rect.collidepoint(pos):
                self.activeObjID = objID
                self.activeObjIDs.append(objID)
                self.activePos = pos
        return ui.NoEvent

    # put actually processing of key in "processKeyUp" using key pressed during "processKeyDown" to prevent erroneous double press detection when holding down CTRL, SHIFT, or ALT keys
    def processKeyDown(self, evt):
        self.keyPress = evt
        if self.callEventHandler:
            self.callEventHandler.processKeyDown(evt)
        return ui.NoEvent

    def processKeyUp(self,evt2):
        if self.callEventHandler:
            self.callEventHandler.processKeyUp(evt2)
        evt = self.keyPress
        if not self.keyPress: return ui.NoEvent
        self.keyPress = False
        # ==== Object Hotkeys ====
        #I have not found unicode escape characters for Ctrl-0 through Ctrl-9, so using direct key reference (less preferred due to international keyboards)
        if evt.key in [49,50,51,52,53,54,55,56,57,48]:
            if pygame.key.get_mods() & pygame.KMOD_CTRL:
                log.debug('Set Key:',evt.key)
                if gdata.config.defaults.displayhelp != 'no':
                    self.KeyModHelp.show()
                self.selectobject = True
                self.setKey = evt.key
                self.app.setStatus(_("Select object to hotkey. ESC to cancel."))
            elif pygame.key.get_mods() & pygame.KMOD_SHIFT:
                log.debug('Focus Key:',evt.key)
                self.focusOnKeyObject(evt.key)
            else:
                log.debug('Goto Key:',evt.key)
                self.gotoKeyObject(evt.key)
            return ui.NoEvent
        # ==== Map and Dialog Hotkeys ====
        elif evt.key == pygame.K_ESCAPE and self.selectobject:
            log.debug('Canceled Key')
            if self.selectobject:
                self.app.setStatus(_("Ready."))
                self.selectobject = False
            return ui.NoEvent
        if not evt.unicode:
            # force update
            self.star_map.scale += 1
            self.star_map.scale -= 1
            return ui.NoEvent
        if evt.unicode in u'+=':
            self.star_map.scale += 5
            self.repaint_map = 1
        elif evt.unicode == u'-':
            if self.star_map.scale > 10:
                self.star_map.scale -= 5
                self.repaint_map = 1
        # Space Bar - Recenter
        elif evt.unicode == u' ':
            x, y = pygame.mouse.get_pos()
            centerX, centerY = self._mapSurf.get_rect().center
            self.star_map.currX -= float(centerX - x) / self.star_map.scale
            self.star_map.currY += float(centerY - y) / self.star_map.scale
            self.repaint_map = 1
            self._newCurrXY = 0
        # ==== Standard Hotkeys ====
        # Ctrl+A - Alternative system info [production instead of buoys]
        elif evt.unicode == u'\x01':
            self.toggleHotbuttons('alternate')
        # Reserve CTRL-C for copy (future editor support)
        # Ctrl+F
        elif evt.unicode == u'\x06' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.searchDlg.display()
        # Ctrl+G - Toggle grid
        elif evt.unicode == u'\x07' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('grid')
        # Ctrl-H - Toggle visibility of civilian ships
        elif evt.unicode == u'\x08' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('civ')
        # Ctrl+L - Toggle drawing fleet lines
        elif evt.unicode == u'\x0C' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('lines')
        # Ctrl+P - Toggle viewing of control areas (turns off scanner circles)
        elif evt.unicode == u'\x10' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('pzone')
        # Ctrl+R - Toggle drawing redirects
        elif evt.unicode == u'\x12' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('redir')
        # Ctrl+S - Toggle drawing scanners
        elif evt.unicode == u'\x13' and pygame.key.get_mods() & pygame.KMOD_CTRL:
            self.toggleHotbuttons('scanner')
        # Reserve CTRL-V,X,and Z for paste, cut, and undo (future editor support)
        # ==== Else ====
        else:
            # force update
            self.star_map.scale += 1
            self.star_map.scale -= 1
        return ui.NoEvent

    def setKeyObject(self,objIDs,bObjIDs):
        objID = self.gotoObject(objIDs,bObjIDs)
        log.debug('Setting Key Object To:',objID)
        self.app.setStatus(_("Ready."))
        self.selectobject = False
        if (objID == Const.OID_NONE):
            return
        obj = client.get(objID)
        if obj.type in (Const.T_SYSTEM, Const.T_PLANET, Const.T_FLEET):
            gdata.objectFocus[self.setKey]=objID

    def gotoKeyObject(self,evtkey):
        if evtkey in gdata.objectFocus:
            objID = gdata.objectFocus[evtkey]
            self.processAction(self.action, objID)
            self.pressedObjIDs = []

    def focusOnKeyObject(self,evtkey):
        if evtkey in gdata.objectFocus:
            objID = gdata.objectFocus[evtkey]
            obj = client.get(objID, noUpdate = 1)
            if hasattr(obj, "x"):
                gdata.mainGameDlg.win.vStarMap.highlightPos = (obj.x, obj.y)
                gdata.mainGameDlg.win.vStarMap.setPos(obj.x, obj.y)

    def onMouseOver(self):
        self.mouseOver = 1
        try:
            self.parent.parent.setFocus(self)
        except:
            log.debug('Cannot refocus on starmap')

    def setPos(self, x, y):
        self.star_map.currX = x
        self.star_map.currY = y
        self.repaint_map = 1
        self.processMiniMapRect()
Example #5
0
    control_modes['pirate_dialogs'] = 0  # only for pirate, obv.

    # pick individual color for each player (needs to happen before precompute)
    gdata.config.defaults.highlights = 'yes'
    fleets_to_get = []
    players_ids = s.getInfo(OID_UNIVERSE).players
    for player in osci.client.cmdProxy.multiGetInfo(1, players_ids[:]):
        osci.client.db[player.oid] = player
        c_hash = hashlib.sha256(player.login.encode('utf-8')).hexdigest()[:6]
        color_code = (int(c_hash[:2], 16), int(c_hash[2:4], 16), int(c_hash[4:], 16))
        gdata.playersHighlightColors[player.oid] = color_code
        # we have to explicitly pick fleets, as they are invisible for admin
        fleets_to_get += player.fleets
    for obj in osci.client.cmdProxy.multiGetInfo(1, fleets_to_get[:]):
        osci.client.db[obj.oid] = obj
    painter = StarMap(control_modes)
    turn_string = osci.res.formatTime(osci.client.getTurn(), '_')
    painter.precompute()
    # we are not using default zoom - it's too much
    painter.scale = 30
    galaxies = s.getInfo(OID_UNIVERSE).galaxies
    for galaxy_id in galaxies:
        galaxy = s.getInfo(galaxy_id)
        #if galaxy.name.startswith("Single -"): continue
        painter.currX, painter.currY = galaxy.x, galaxy.y
        surface_side = (galaxy.radius + 0.5) * 2 * painter.scale
        surface = pygame.Surface((surface_side, surface_side))
        painter.rect = surface.get_rect()
        new_surf, empty, empty = painter.draw(surface)
        pic_name = galaxy.name + '.' + turn_string + '.png'
        pic_path = os.path.join(options.chronicler_dir, pic_name)
Example #6
0
    # pick individual color for each player (needs to happen before precompute)
    gdata.config.defaults.highlights = 'yes'
    fleets_to_get = []
    players_ids = s.getInfo(OID_UNIVERSE).players
    for player in osci.client.cmdProxy.multiGetInfo(1, players_ids[:]):
        osci.client.db[player.oid] = player
        c_hash = hashlib.sha256(player.login.encode('utf-8')).hexdigest()[:6]
        color_code = (int(c_hash[:2], 16), int(c_hash[2:4],
                                               16), int(c_hash[4:], 16))
        gdata.playersHighlightColors[player.oid] = color_code
        # we have to explicitly pick fleets, as they are invisible for admin
        fleets_to_get += player.fleets
    for obj in osci.client.cmdProxy.multiGetInfo(1, fleets_to_get[:]):
        osci.client.db[obj.oid] = obj
    painter = StarMap(control_modes)
    turn_string = osci.res.formatTime(osci.client.getTurn(), '_')
    painter.precompute()
    # we are not using default zoom - it's too much
    painter.scale = 30
    galaxies = s.getInfo(OID_UNIVERSE).galaxies
    for galaxy_id in galaxies:
        galaxy = s.getInfo(galaxy_id)
        #if galaxy.name.startswith("Single -"): continue
        painter.currX, painter.currY = galaxy.x, galaxy.y
        surface_side = (galaxy.radius + 0.5) * 2 * painter.scale
        surface = pygame.Surface((surface_side, surface_side))
        painter.rect = surface.get_rect()
        new_surf, empty, empty = painter.draw(surface)
        pic_name = galaxy.name + '.' + turn_string + '.png'
        pic_path = os.path.join(options.chronicler_dir, pic_name)