Exemplo n.º 1
0
class MultiFitWnd(Window):
    __guid__ = 'form.MultiFitWnd'
    __notifyevents__ = ['OnSessionChanged']
    default_topParentHeight = 70
    default_height = 400
    default_width = 320
    default_windowID = 'multiFitWnd'
    default_captionLabelPath = 'UI/Fitting/FittingWindow/FittingManagement/MultiFitHeader'
    layoutColumns = 3

    def ApplyAttributes(self, attributes):
        Window.ApplyAttributes(self, attributes)
        self.fitting = None
        self.MakeUnResizeable()
        self.MakeUnstackable()
        self.canFitNum = 0
        self.tryingToFitNum = 1
        self.currentProgress = 0
        self.ConstructUI()
        fitting = attributes.fitting
        self.tryingToFitNum = attributes.get('qty', 1)
        self.LoadWindow(fitting, self.tryingToFitNum)
        self.SetInventoryStatus()
        sm.RegisterNotify(self)

    def ConstructUI(self):
        self.BuildTopParentUI()
        self.AddButtons()
        numColumns = 2
        self.layoutGrid = layoutGrid = LayoutGrid(parent=self.sr.main,
                                                  columns=numColumns,
                                                  cellSpacing=(4, 10))
        spacer = Container(pos=(0, 0, 50, 0), align=uiconst.TOPLEFT)
        layoutGrid.AddCell(cellObject=spacer, colSpan=1)
        layoutGrid.FillRow()
        self.BuildNumToFitUI()
        self.BuildWarningUI()
        self.BuildRefreshInventory()
        self.missingLayoutGrid = LayoutGrid(parent=self.layoutGrid,
                                            columns=2,
                                            cellSpacing=(4, 10))
        self.BuildAvailableShipsUI()
        self.BuildEquipmentUI()
        self.BuildProgressUI()
        self.MakeRigCbUI()

    def BuildTopParentUI(self):
        self.sr.topParent.padding = (2 * const.defaultPadding, 0,
                                     2 * const.defaultPadding, 0)
        self.shipIcon = Icon(name='shipIcon',
                             parent=self.sr.topParent,
                             state=uiconst.UI_NORMAL,
                             size=64,
                             ignoreSize=True)
        self.shipIcon.GetDragData = self.GetFittingDragData
        self.shipIcon.OnClick = self.OpenFitting
        self.shipIcon.hint = GetByLabel('UI/Fitting/ShowFitting')
        self.techSprite = Sprite(name='techIcon',
                                 parent=self.sr.topParent,
                                 align=uiconst.RELATIVE,
                                 width=16,
                                 height=16,
                                 idx=0)
        self.fitNameEdit = SinglelineEdit(
            name='fitNameEdit',
            parent=self.sr.topParent,
            left=72,
            width=150,
            maxLength=20,
            hint=GetByLabel('UI/Common/ShipName'))
        top = self.fitNameEdit.top + self.fitNameEdit.height + 5
        self.shipNameLabel = EveLabelMedium(name='shipNameLabel',
                                            parent=self.sr.topParent,
                                            left=77,
                                            top=top,
                                            state=uiconst.UI_NORMAL)

    def AddButtons(self):
        btnCont = FlowContainer(name='buttonParent',
                                parent=self.sr.main,
                                align=uiconst.TOBOTTOM,
                                padding=6,
                                autoHeight=True,
                                centerContent=True,
                                contentSpacing=uiconst.BUTTONGROUPMARGIN,
                                idx=0)
        text = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/FitShips', numToFit=1)
        self.fitBtn = Button(parent=btnCont,
                             label=text,
                             func=self.DoFitShips,
                             align=uiconst.NOALIGN)
        self.cancelBtn = Button(parent=btnCont,
                                label=GetByLabel('UI/Commands/Cancel'),
                                func=self.Cancel,
                                align=uiconst.NOALIGN)

    def BuildNumToFitUI(self):
        maxShipsAllowed = int(
            sm.GetService('machoNet').GetGlobalConfig().get(
                'bulkFit_maxShips', 30))
        numCont = Container(name='numCont',
                            align=uiconst.TOTOP,
                            height=30,
                            padLeft=LEFT_EDGE)
        text = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/NumShipsToFit')
        self.numToFitLabel = EveLabelLarge(name='numToFitLabel',
                                           parent=numCont,
                                           text=text,
                                           width=250,
                                           autoFitToText=True)
        left = self.numToFitLabel.left + self.numToFitLabel.textwidth + 10
        self.numToFitEdit = SinglelineEdit(name='numToFitEdit',
                                           parent=numCont,
                                           ints=[1, maxShipsAllowed],
                                           OnChange=self.OnNumChanged,
                                           left=left,
                                           align=uiconst.CENTERLEFT)
        numCont.height = max(self.numToFitLabel.textheight,
                             self.numToFitEdit.height)
        self.layoutGrid.AddCell(cellObject=numCont,
                                colSpan=self.layoutGrid.columns)

    def BuildWarningUI(self):
        self.numWarningLabel = EveCaptionSmall(name='numWarningLabel',
                                               state=uiconst.UI_NORMAL,
                                               align=uiconst.CENTERTOP,
                                               width=MAX_TEXT_WIDTH,
                                               autoFitToText=True)
        self.numWarningLabel.SetRGBA(*WARNING_COLOR)
        self.numWarningLabel.LoadTooltipPanel = self.LoadMissingTooltip
        self.layoutGrid.AddCell(cellObject=self.numWarningLabel,
                                colSpan=self.layoutGrid.columns)
        self.layoutGrid.FillRow()

    def BuildRefreshInventory(self):
        self.refreshCont = Transform(parent=self.layoutGrid,
                                     pos=(0, 0, 32, 32),
                                     align=uiconst.CENTER)
        self.refreshIcon = ButtonIcon(name='refreshSprite',
                                      parent=self.refreshCont,
                                      width=32,
                                      height=32,
                                      align=uiconst.CENTER,
                                      texturePath=REFRESH_TEXTUREPATH,
                                      iconSize=32,
                                      func=self.OnRefreshClicked)
        self.refreshIcon.hint = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/RefreshInventoryStatusHint'
        )

    def OnRefreshClicked(self, *args):
        uthread.new(self.refreshCont.StartRotationCycle, cycles=1)
        self.SetInventoryStatus()

    def BuildAvailableShipsUI(self):
        self.shipCounter = EveCaptionMedium(name='shipCounter',
                                            parent=self.missingLayoutGrid,
                                            state=uiconst.UI_NORMAL,
                                            align=uiconst.CENTERRIGHT,
                                            left=4)
        self.shipCounter.LoadTooltipPanel = self.LoadShipCounterTooltipPanel
        self.shipCounter.missingDict = {}
        shipText = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/PackagedShipsInHangar')
        self.availableShipsLabel = EveLabelLarge(name='availableShipsLabel',
                                                 parent=self.missingLayoutGrid,
                                                 state=uiconst.UI_NORMAL,
                                                 text=shipText,
                                                 align=uiconst.CENTERLEFT,
                                                 width=MAX_TEXT_WIDTH,
                                                 autoFitToText=True)
        self.availableShipsLabel.hint = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/PackagedShipsInHangarHint'
        )
        self.layoutGrid.FillRow()

    def BuildEquipmentUI(self):
        self.equipmentCounter = EveCaptionMedium(name='equipmentCounter',
                                                 parent=self.missingLayoutGrid,
                                                 state=uiconst.UI_NORMAL,
                                                 align=uiconst.CENTERRIGHT,
                                                 left=4)
        self.equipmentCounter.LoadTooltipPanel = self.LoadEqCounterTooltipPanel
        self.equipmentCounter.missingDict = {}
        eqText = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/RoundsOfFittingsInHangar'
        )
        self.availableEquipmentLabel = EveLabelLarge(
            name='availableEquipmentLabel',
            parent=self.missingLayoutGrid,
            state=uiconst.UI_NORMAL,
            text=eqText,
            align=uiconst.CENTERLEFT,
            width=MAX_TEXT_WIDTH,
            autoFitToText=True)
        self.layoutGrid.FillRow()

    def BuildProgressUI(self):
        self.progressCont = Container(parent=self.sr.main,
                                      height=36,
                                      align=uiconst.TOBOTTOM,
                                      padding=(10, 0, 10, 10))
        self.progressCounter = EveCaptionMedium(name='progressCounter',
                                                parent=self.progressCont,
                                                state=uiconst.UI_NORMAL,
                                                align=uiconst.CENTERTOP)
        self.progressBar = ProgressBar(parent=self.progressCont,
                                       height=10,
                                       align=uiconst.TOBOTTOM)
        self.progressCont.display = False

    def MakeRigCbUI(self):
        checked = settings.user.ui.Get('fitting_rigCB', True)
        text = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/FitRigs')
        self.rigCB = Checkbox(name='rigCB',
                              text=text,
                              OnChange=self.OnCbChanged,
                              left=LEFT_EDGE,
                              checked=checked,
                              prefstype=('user', 'ui'),
                              configName='fitting_rigCB')
        self.rigCB.hint = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/FitRigsHint')
        self.layoutGrid.AddCell(cellObject=self.rigCB,
                                colSpan=self.layoutGrid.columns)

    def OnNumChanged(self, *args):
        self.onNumChangedTimer = AutoTimer(100, self.SetInventoryStatus)

    def OnCbChanged(self, *args):
        self.SetInventoryStatus()

    def OpenFitting(self, *args):
        sm.GetService('fittingSvc').DisplayFitting(self.fitting)

    def LoadWindow(self, fitting, qty=1):
        self.fitting = fitting
        self.shipCounter.missingDict = {}
        self.equipmentCounter.missingDict = {}
        shipTypeID = fitting.shipTypeID
        self.shipIcon.LoadIconByTypeID(shipTypeID)
        uix.GetTechLevelIcon(self.techSprite, typeID=shipTypeID)
        self.numToFitEdit.text = qty
        self.fitNameEdit.SetValue(fitting.name)
        self.shipNameLabel.text = GetShowInfoLink(shipTypeID,
                                                  evetypes.GetName(shipTypeID))
        self.SetInventoryStatus()
        self.missingLayoutGrid.RefreshGridLayout()
        self.layoutGrid.RefreshGridLayout()
        layoutWidth, layoutHeight = self.layoutGrid.GetSize()
        newHeight = layoutHeight + self.fitBtn.height + self.progressCont.height + self.sr.topParent.height + 20
        self.height = max(newHeight, self.default_height)
        self.width = max(layoutWidth + 20, self.default_width)

    def SetInventoryStatus(self):
        self.onNumChangedTimer = None
        fitting = self.fitting
        shipTypeID = fitting.shipTypeID
        fittingSvc = sm.GetService('fittingSvc')
        chargesByType, dronesByType, fightersByTypeID, iceByType, itemTypes, modulesByFlag, rigsToFit, subsystems = fittingSvc.GetTypesToFit(
            fitting, None)
        if rigsToFit:
            self.rigCB.display = True
        else:
            self.rigCB.display = False
        numToFit = self.numToFitEdit.GetValue()
        self.tryingToFitNum = numToFit
        maxAvailableFitting, missingForFullFit = self._GetMaxAvailabeAndMissingForFullFit(
            itemTypes, modulesByFlag, numToFit)
        nonSingletonShipsNumDict = fittingSvc.GetQt0yInHangarByTypeIDs(
            [shipTypeID], onlyGetNonSingletons=True)
        packagedShipsNum = nonSingletonShipsNumDict.get(shipTypeID, 0)
        self.canFitNum = min(packagedShipsNum, maxAvailableFitting, numToFit)
        btnText = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/FitShips',
            numToFit=self.canFitNum)
        self.fitBtn.SetLabel(btnText)
        if self.canFitNum < 1:
            self.fitBtn.Disable()
        else:
            self.fitBtn.Enable()
        missingNumShips = max(0, numToFit - packagedShipsNum)
        if missingNumShips:
            missingDict = {shipTypeID: missingNumShips}
        else:
            missingDict = {}
        self.shipCounter.missingDict = missingDict
        if missingForFullFit:
            missingDict = missingForFullFit
        else:
            missingDict = {}
        self.equipmentCounter.missingDict = missingDict
        if missingForFullFit or missingNumShips:
            missingText = GetByLabel(
                'UI/Fitting/FittingWindow/FittingManagement/MissingShipEquipment'
            )
            self.numWarningLabel.text = missingText
        else:
            self.numWarningLabel.text = ''
            self.numWarningLabel.height = 0
        self.SetAvailabilityShipOrEq(self.shipCounter, packagedShipsNum,
                                     numToFit)
        self.SetAvailabilityShipOrEq(self.equipmentCounter,
                                     maxAvailableFitting, numToFit)

    def _GetMaxAvailabeAndMissingForFullFit(self, itemTypes, modulesByFlag,
                                            numToFit):
        fittingSvc = sm.GetService('fittingSvc')
        qtyByTypeID = fittingSvc.GetQt0yInHangarByTypeIDs(itemTypes)
        rigTypeIDs = {
            t
            for f, t in modulesByFlag.iteritems() if f in const.rigSlotFlags
        }
        maxAvailableFitting, missingForFullFit = fittingSvc.GetMaxAvailabeAndMissingForFullFit(
            True, itemTypes, numToFit, qtyByTypeID, rigTypeIDs)
        return (maxAvailableFitting, missingForFullFit)

    def SetAvailabilityShipOrEq(self, label, available, numToFit):
        label.text = available
        if available < numToFit:
            label.SetRGB(*WARNING_COLOR)
        else:
            label.SetRGB(*NORMAL_COLOR)

    def DoFitShips(self, *args):
        fitting = self.fitting
        fitRigs = self.rigCB.GetValue()
        toActuallyFit = self.canFitNum
        fittingName = self.fitNameEdit.GetValue()
        fittingSvc = sm.GetService('fittingSvc')
        chargesByType, dronesByType, fightersByTypeID, iceByType, itemTypes, modulesByFlag, rigsToFit, subsystems = fittingSvc.GetTypesToFit(
            fitting, None)
        if fitRigs or not rigsToFit:
            cargoItemsByType = {}
        else:
            cargoItemsByType = defaultdict(int)
            for flagID, typeID in modulesByFlag.iteritems():
                if flagID in const.rigSlotFlags:
                    cargoItemsByType[typeID] += 1

            cargoItemsByType = dict(cargoItemsByType)
        lobby = GetLobbyClass().GetIfOpen()
        if lobby is None:
            return
        lobby.CheckCanAccessService('fitting')
        maxAvailableFitting, missingForFullFit = self._GetMaxAvailabeAndMissingForFullFit(
            itemTypes, modulesByFlag, toActuallyFit)
        if missingForFullFit:
            self.SetInventoryStatus()
            eve.Message('uiwarning03')
            return
        try:
            self.PrepareForMultiFitCall()
            fittingSvc.DoFitManyShips(chargesByType, dronesByType,
                                      fightersByTypeID, fitRigs, fitting,
                                      iceByType, cargoItemsByType,
                                      toActuallyFit, modulesByFlag,
                                      fittingName)
        finally:
            uthread.new(self.ResetUIAfterFitting)

    def PrepareForMultiFitCall(self):
        self.fitBtn.Disable()
        self.cancelBtn.Disable()
        self.currentProgress = 0
        self.progressCounter.text = self.currentProgress
        self.progressCont.display = True
        self.layoutGrid.Disable()
        self.layoutGrid.opacity = 0.2
        sm.RegisterForNotifyEvent(self, 'OnItemChange')

    def ResetUIAfterFitting(self):
        sm.UnregisterForNotifyEvent(self, 'OnItemChange')
        self.currentProgress = 0
        uicore.animations.BlinkOut(self.progressCont,
                                   startVal=0.0,
                                   endVal=1.0,
                                   duration=0.5,
                                   loops=3,
                                   sleep=True)
        self.progressCont.display = False
        self.progressCounter.text = self.currentProgress
        self.cancelBtn.Enable()
        self.layoutGrid.Enable()
        self.layoutGrid.opacity = 1.0
        self.SetInventoryStatus()

    def Cancel(self, *args):
        self.CloseByUser()

    def GetFittingDragData(self):
        entry = KeyVal()
        entry.fitting = self.fitting
        entry.label = self.fitting.name
        entry.displayText = self.fitting.name
        entry.__guid__ = 'listentry.FittingEntry'
        return [entry]

    def LoadMissingTooltip(self, tooltipPanel, *args):
        text = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/MissingItems',
            numToFit=self.tryingToFitNum,
            fittingName=self.fitting.name)
        tooltipPanel.AddLabelLarge(text=text, padBottom=8)
        self.LoadShipCounterTooltipPanel(tooltipPanel,
                                         singleGroupShowing=False)
        self.LoadEqCounterTooltipPanel(tooltipPanel, singleGroupShowing=False)
        missingDict = {}
        missingDict.update(self.shipCounter.missingDict)
        missingDict.update(self.equipmentCounter.missingDict)
        self.AddBuyAllBtn(tooltipPanel, missingDict)

    def LoadShipCounterTooltipPanel(self, tooltipPanel, *args, **kwargs):
        missingDict = self.shipCounter.missingDict
        if not missingDict:
            return
        singleGroupShowing = kwargs.get('singleGroupShowing', True)
        text = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/MissingShips',
            numToFit=self.tryingToFitNum,
            fittingName=self.fitting.name)
        return self.LoadCounterTooltip(tooltipPanel, missingDict, text,
                                       singleGroupShowing)

    def LoadEqCounterTooltipPanel(self, tooltipPanel, *args, **kwargs):
        missingDict = self.equipmentCounter.missingDict
        if not missingDict:
            return
        singleGroupShowing = kwargs.get('singleGroupShowing', True)
        text = GetByLabel(
            'UI/Fitting/FittingWindow/FittingManagement/MissingEquipment',
            numToFit=self.tryingToFitNum,
            fittingName=self.fitting.name)
        self.LoadCounterTooltip(tooltipPanel, missingDict, text,
                                singleGroupShowing)

    def LoadCounterTooltip(self,
                           tooltipPanel,
                           missingDict,
                           text,
                           singleGroupShowing=True):
        tooltipPanel.LoadGeneric1ColumnTemplate()
        tooltipPanel.state = uiconst.UI_NORMAL
        if singleGroupShowing:
            tooltipPanel.AddLabelLarge(text=text, padBottom=8)
        typeList = []
        for eachTypeID, eachQty in missingDict.iteritems():
            typeName = evetypes.GetName(eachTypeID)
            typeList.append((typeName.lower(), (eachTypeID, eachQty)))

        typeList = SortListOfTuples(typeList)
        for eachTypeID, eachQty in typeList[:MAX_TOOLTIP_ENTRIES]:
            typeCont = TooltipEntry(parent=tooltipPanel,
                                    typeID=eachTypeID,
                                    qty=eachQty)

        if len(typeList) > MAX_TOOLTIP_ENTRIES:
            numItemsNotDisplayed = len(typeList) - MAX_TOOLTIP_ENTRIES
            text = GetByLabel(
                'UI/Fitting/FittingWindow/FittingManagement/MoreItemTypesMissing',
                numMoreItems=numItemsNotDisplayed)
            tooltipPanel.AddLabelMedium(text=text, align=uiconst.CENTERLEFT)
        if singleGroupShowing:
            self.AddBuyAllBtn(tooltipPanel, missingDict)

    def AddBuyAllBtn(self, tooltipPanel, missingDict):
        def BuyAll(*args):
            BuyMultipleTypesWithQty(missingDict)

        Button(parent=tooltipPanel,
               label=GetByLabel('UI/Market/MarketQuote/BuyAll'),
               func=BuyAll,
               align=uiconst.CENTER)
        if session.role & ROLE_GMH == ROLE_GMH:
            Button(parent=tooltipPanel,
                   label='GM: Give all',
                   func=self.GiveAllGM,
                   align=uiconst.CENTERRIGHT,
                   args=(missingDict, ))

    def GiveAllGM(self, missingDict):
        numToCountTo = len(missingDict) + 1
        header = 'GM Item Gift'
        sm.GetService('loading').ProgressWnd(header, '', 1, numToCountTo)
        counter = 1
        for typeID, qty in missingDict.iteritems():
            counter += 1
            sm.GetService('loading').ProgressWnd(header, '', counter,
                                                 numToCountTo)
            sm.RemoteSvc('slash').SlashCmd('/create %s %s' % (typeID, qty))

        sm.GetService('loading').ProgressWnd('Done', '', numToCountTo,
                                             numToCountTo)

    def OnItemChange(self, item, change):
        if item.typeID != self.fitting.shipTypeID:
            return
        if const.ixSingleton in change:
            self.currentProgress += 1
            self.progressCounter.text = '%s / %s' % (self.currentProgress,
                                                     self.canFitNum)

    def OnSessionChanged(self, isRemote, sess, change):
        if not IsDocked():
            self.CloseByUser()
Exemplo n.º 2
0
class MultiTrainingOverlay(Container):
    SUPPRESS_KEY = 'suppress.MultiplePilotTrainingPromotion'
    CONTENT_LEFT = 140
    CHARACTERS_LEFT = -180
    default_align = uiconst.TOALL
    default_clipChildren = True
    default_state = uiconst.UI_HIDDEN

    def ApplyAttributes(self, attributes):
        super(MultiTrainingOverlay, self).ApplyAttributes(attributes)
        self.Layout()

    def Layout(self):
        self.compactMode = False
        Frame(bgParent=self,
              texturePath='res:/UI/Texture/classes/Monetization/vignette.png',
              cornerSize=150)
        self.characters = Sprite(
            parent=self,
            align=uiconst.CENTER,
            state=uiconst.UI_DISABLED,
            left=self.CHARACTERS_LEFT,
            top=10,
            texturePath='res:/UI/Texture/classes/Monetization/characters.png',
            width=299,
            height=355)
        self.content = ContainerAutoSize(parent=self,
                                         align=uiconst.CENTER,
                                         left=self.CONTENT_LEFT,
                                         width=340)
        EveCaptionLarge(
            parent=self.content,
            align=uiconst.TOTOP,
            text=localization.GetByLabel(
                'UI/SkillQueue/MultiTrainingOverlay/MultiplePilotTraining'))
        EveLabelMedium(
            parent=self.content,
            align=uiconst.TOTOP,
            top=4,
            text=localization.GetByLabel(
                'UI/SkillQueue/MultiTrainingOverlay/MultiTrainingMessageTop'))
        itemCont = ContainerAutoSize(parent=self.content,
                                     align=uiconst.TOTOP,
                                     alignMode=uiconst.TOTOP,
                                     top=12)
        Frame(bgParent=itemCont,
              texturePath=
              'res:/UI/Texture/classes/Monetization/item_well_frame.png',
              cornerSize=2)
        itemIconCont = ContainerAutoSize(parent=itemCont,
                                         align=uiconst.TOLEFT,
                                         padding=(8, 8, 0, 8))
        Icon(parent=itemIconCont,
             align=uiconst.TOPLEFT,
             state=uiconst.UI_DISABLED,
             size=64,
             typeID=typeMultiTrainingToken)
        Sprite(parent=itemIconCont,
               align=uiconst.TOPLEFT,
               state=uiconst.UI_DISABLED,
               texturePath='res:/UI/Texture/classes/InvItem/bgNormal.png',
               width=64,
               height=64)
        EveLabelLargeBold(parent=itemCont,
                          align=uiconst.TOTOP,
                          padding=(8, 8, 24, 0),
                          text=evetypes.GetName(typeMultiTrainingToken))
        InfoIcon(parent=itemCont,
                 align=uiconst.TOPRIGHT,
                 top=8,
                 left=8,
                 typeID=typeMultiTrainingToken)
        self.estimatePriceLabel = EveLabelMedium(parent=itemCont,
                                                 align=uiconst.TOTOP,
                                                 padding=(8, 0, 8, 6),
                                                 color=Color.GRAY5)
        buyButtonCont = FlowContainer(parent=itemCont,
                                      align=uiconst.TOTOP,
                                      padding=(8, 0, 8, 8),
                                      contentSpacing=(8, 0))
        MultiTrainingBuyButtonIsk(parent=buyButtonCont,
                                  align=uiconst.NOALIGN,
                                  typeID=typeMultiTrainingToken)
        MultiTrainingBuyButtonAur(parent=buyButtonCont,
                                  align=uiconst.NOALIGN,
                                  types=[typeMultiTrainingToken])
        EveLabelMedium(
            parent=self.content,
            align=uiconst.TOTOP,
            top=12,
            text=localization.GetByLabel(
                'UI/SkillQueue/MultiTrainingOverlay/MultiTrainingMessageBottom'
            ))
        dismissCont = FlowContainer(parent=self.content,
                                    align=uiconst.TOTOP,
                                    padding=(8, 24, 8, 0),
                                    contentAlignment=CONTENT_ALIGN_CENTER,
                                    contentSpacing=(8, 4))
        Button(parent=dismissCont,
               align=uiconst.NOALIGN,
               label=localization.GetByLabel(
                   'UI/SkillQueue/MultiTrainingOverlay/Dismiss'),
               func=lambda *args: self.Dismiss())
        self.suppressCheckbox = Checkbox(
            parent=dismissCont,
            align=uiconst.NOALIGN,
            width=200,
            text=localization.GetByLabel('UI/Common/SuppressionShowMessage'),
            checked=self.suppressed,
            callback=self.OnSuppressChanged)

    def OnSuppressChanged(self, checkbox):
        self.suppressed = self.suppressCheckbox.GetValue()

    @classmethod
    def IsSuppressed(cls):
        return settings.user.suppress.Get(cls.SUPPRESS_KEY, False)

    @property
    def suppressed(self):
        return self.IsSuppressed()

    @suppressed.setter
    def suppressed(self, suppressed):
        if suppressed:
            settings.user.suppress.Set(self.SUPPRESS_KEY, suppressed)
        else:
            settings.user.suppress.Delete(self.SUPPRESS_KEY)
        sm.GetService('settings').SaveSettings()

    def ShouldDisplay(self):
        if self.suppressed:
            return False
        if sm.GetService('skillqueue').SkillInTraining() is not None:
            return False
        queues = sm.GetService(
            'skillqueue').GetMultipleCharacterTraining().items()
        characterData = sm.GetService('cc').GetCharacterSelectionData()
        activeQueues = 1 + len(queues)
        usedQueues = 0
        for characterDetails in characterData.details.values():
            isTraining = characterDetails.GetSkillInTrainingInfo(
            )['currentSkill'] is not None
            if characterDetails.charID != session.charid and isTraining:
                usedQueues += 1

        return usedQueues == activeQueues

    def Display(self):
        self.Load()
        self.Enable()
        self.AnimShow()

    def Load(self):
        self.UpdateEstimatedPrice()
        self.suppressCheckbox.SetValue(self.suppressed)

    def UpdateEstimatedPrice(self):
        try:
            tokenAveragePrice = GetAveragePrice(typeMultiTrainingToken)
        except KeyError:
            tokenAveragePrice = None

        if not tokenAveragePrice:
            text = localization.GetByLabel(
                'UI/SkillQueue/MultiTrainingOverlay/EstimatedPriceUnknown')
        else:
            amount = RoundISK(tokenAveragePrice)
            text = localization.GetByLabel(
                'UI/SkillQueue/MultiTrainingOverlay/EstimatedPrice',
                amount=amount)
        self.estimatePriceLabel.SetText(text)

    def Dismiss(self):
        self.Disable()
        self.AnimHide()

    def AnimShow(self):
        self.Show()
        animations.FadeTo(self, duration=0.4)
        if not self.compactMode:
            animations.FadeTo(self.characters, timeOffset=0.3)
        animations.FadeTo(self.content, timeOffset=0.3)

    def AnimHide(self):
        animations.FadeOut(self, duration=0.4)

    def EnterCompactMode(self):
        if self.compactMode:
            return
        self.compactMode = True
        animations.FadeOut(self.characters, duration=0.2)
        animations.MorphScalar(self.characters,
                               'left',
                               startVal=self.characters.left,
                               endVal=self.CHARACTERS_LEFT - 60,
                               duration=0.3)
        animations.MorphScalar(self.content,
                               'left',
                               startVal=self.content.left,
                               endVal=0,
                               duration=0.3)

    def ExitCompactMode(self):
        if not self.compactMode:
            return
        self.compactMode = False
        animations.FadeIn(self.characters, duration=0.2)
        animations.MorphScalar(self.characters,
                               'left',
                               startVal=self.characters.left,
                               endVal=self.CHARACTERS_LEFT,
                               duration=0.3)
        animations.MorphScalar(self.content,
                               'left',
                               startVal=self.content.left,
                               endVal=self.CONTENT_LEFT,
                               duration=0.3)

    def UpdateAlignment(self,
                        budgetLeft=0,
                        budgetTop=0,
                        budgetWidth=0,
                        budgetHeight=0,
                        updateChildrenOnly=False):
        if budgetWidth < 640:
            self.EnterCompactMode()
        else:
            self.ExitCompactMode()
        return super(MultiTrainingOverlay,
                     self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth,
                                           budgetHeight, updateChildrenOnly)
Exemplo n.º 3
0
class AutoBotWindow(Window):
    """ An Insider window which makes it easy to debug UI containers """
    default_windowID = 'AutoBotWindow'
    default_width = 360
    default_height = 300
    default_topParentHeight = 0
    default_minSize = (default_width, default_height)
    default_caption = 'AutoBot Control Box'

    def ApplyAttributes(self, attributes):
        Window.ApplyAttributes(self, attributes)
        self.CreateLocationSelector()
        self.CreateSecurityFilter()
        self.CreateShipSelector()
        self.CreatePasses()
        self.CreateButtons()
        self.CreateLogDisplay()

    def CreateButtons(self):
        buttonCont = FlowContainer(name='SubCategoryButtons',
                                   parent=self.sr.main,
                                   centerContent=True,
                                   align=uiconst.TOBOTTOM,
                                   contentSpacing=(2, 1),
                                   state=uiconst.UI_PICKCHILDREN,
                                   padding=(0, 4, 0, 4))
        Button(parent=buttonCont,
               label='Roll out!!',
               func=self.StartBot,
               align=uiconst.NOALIGN,
               padding=2)
        Button(parent=buttonCont,
               label='Stop',
               func=self.StopBot,
               align=uiconst.NOALIGN,
               padding=2)
        Button(parent=buttonCont,
               label='Clear Log',
               func=self.ClearLogs,
               align=uiconst.NOALIGN,
               padding=2)

    def CreateLocationSelector(self):
        EveLabelSmall(
            parent=self.sr.main,
            text=
            '<color=orange>This is a tool for automating visits to solar systems and locations within them. There are several actions available while visiting each location.',
            align=uiconst.TOTOP,
            padding=4)
        EveLabelSmall(parent=self.sr.main,
                      text='Systems, Constellations or Regions',
                      align=uiconst.TOTOP,
                      padding=4)
        self.locationsEdit = EditPlainText(parent=self.sr.main,
                                           align=uiconst.TOTOP,
                                           height=50,
                                           padding=4)

    def CreateSecurityFilter(self):
        secCont = Container(parent=self.sr.main,
                            height=20,
                            padding=2,
                            align=uiconst.TOTOP)
        EveLabelSmall(parent=secCont,
                      text='Security Band:',
                      align=uiconst.TOLEFT,
                      padding=4)
        EveLabelSmall(parent=secCont,
                      text='Min Security',
                      align=uiconst.TOLEFT,
                      padding=4)
        self.minSecEdit = SinglelineEdit(parent=secCont,
                                         name='minSec',
                                         width=30,
                                         floats=(-1.0, 1.0, 1),
                                         align=uiconst.TOLEFT,
                                         padTop=-3,
                                         setvalue='-1.0')
        EveLabelSmall(parent=secCont,
                      text='Max Security',
                      align=uiconst.TOLEFT,
                      padding=4)
        self.maxSecEdit = SinglelineEdit(parent=secCont,
                                         name='maxSec',
                                         width=30,
                                         floats=(-1.0, 1.0, 1),
                                         align=uiconst.TOLEFT,
                                         padTop=-3,
                                         setvalue='1.0')

    def CreateShipSelector(self):
        cont = Container(parent=self.sr.main,
                         name='ship_options',
                         align=uiconst.TOTOP,
                         height=20)
        self.spawnShipCheckbox = Checkbox(parent=cont,
                                          align=uiconst.TOLEFT,
                                          text='Spawn new ship',
                                          checked=False,
                                          padLeft=8,
                                          callback=self.OnChangeSpawnShip,
                                          width=150)
        Container(parent=cont, width=16, align=uiconst.TOLEFT)
        EveLabelSmall(parent=cont, text='DNA', align=uiconst.TOLEFT, padding=4)
        self.dnaEdit = SinglelineEdit(parent=cont,
                                      setvalue='DNA:593:2528:20197',
                                      align=uiconst.TOLEFT,
                                      width=200)

    def CreatePasses(self):
        EveLabelSmall(parent=self.sr.main,
                      text='Actions for each system visited',
                      align=uiconst.TOTOP,
                      padding=4)
        self.CreateSystemPass(1)
        self.CreateSystemPass(2)

    def CreateSystemPass(self, passNumber):
        def GetLocationsMenu(menuParent):
            passConfig = GetPassConfig()[passNumber]
            menuParent.AddHeader(text='Locations to visit')
            for groupId in (const.groupAsteroidBelt, const.groupStargate,
                            const.groupStation):
                menuParent.AddCheckBox(
                    text=cfg.invgroups.Get(groupId).groupName,
                    checked=groupId in passConfig['locations'],
                    callback=(ToggleLocationGroupForPass, passNumber, groupId))

            menuParent.AddDivider()
            menuParent.AddHeader(text='Actions')
            menuParent.AddCheckBox(text='Nuke location',
                                   checked=passConfig['nuke'],
                                   callback=(ToggleNuke, passNumber))

        passConfig = {
            'locations': {const.groupAsteroidBelt},
            'nuke': False,
            'enabled': passNumber == 1,
            'minTime': 1
        }
        GetPassConfig()[passNumber] = passConfig
        menuCont = Container(name='pass%d' % passNumber,
                             parent=self.sr.main,
                             align=uiconst.TOTOP,
                             height=20,
                             padLeft=4)
        cont = Container(parent=menuCont, width=100, align=uiconst.TOLEFT)
        Checkbox(parent=cont,
                 text='Enable Pass %s' % passNumber,
                 align=uiconst.CENTERLEFT,
                 checked=passConfig['enabled'],
                 callback=lambda checkbox: SetPass(checkbox, passNumber),
                 width=200)
        cont = Container(parent=menuCont, width=100, align=uiconst.TOLEFT)
        EveLabelSmall(parent=cont,
                      text='Min time (sec)',
                      align=uiconst.CENTERRIGHT,
                      left=4)
        SinglelineEdit(
            parent=menuCont,
            ints=(1, 999),
            OnChange=lambda textValue: SetPassMinTime(textValue, passNumber),
            setvalue=passConfig['minTime'],
            align=uiconst.TOLEFT,
            width=50)
        UtilMenu(menuAlign=uiconst.TOPRIGHT,
                 parent=menuCont,
                 align=uiconst.TOLEFT,
                 GetUtilMenu=GetLocationsMenu,
                 label='Options',
                 texturePath='res:/UI/Texture/Icons/38_16_229.png',
                 closeTexturePath='res:/UI/Texture/Icons/38_16_230.png')

    def CreateLogDisplay(self):
        self.logEdit = EditPlainText(parent=self.sr.main,
                                     align=uiconst.TOALL,
                                     readonly=True,
                                     padTop=4)

    def OnChangeSpawnShip(self, checkbox):
        if checkbox.GetValue():
            self.dnaEdit.SetReadOnly(False)
            self.dnaEdit.opacity = 1.0
        else:
            self.dnaEdit.SetReadOnly(True)
            self.dnaEdit.opacity = 0.5

    def StartBot(self, *args):
        config = GetConfig()
        locations = SplitLocationsText(self.locationsEdit.GetValue())
        config['locations'] = locations
        config['minSecurity'] = self.minSecEdit.GetValue()
        config['maxSecurity'] = self.maxSecEdit.GetValue()
        if self.spawnShipCheckbox.GetValue():
            config['shipDna'] = self.dnaEdit.GetValue()
        else:
            config['shipDna'] = None
        sm.GetService('autobot').StartBot()
        self.logUpdated = AutoTimer(2000, self.UpdateLogText)

    def PauseBot(self, *args):
        sm.GetService('autobot').PauseBot()

    def StopBot(self, *args):
        sm.GetService('autobot').StopBot()
        self.logUpdated = None

    def ClearLogs(self, *args):
        sm.GetService('autobot').ClearLogs()

    def UpdateLogText(self):
        logLines = sm.GetService('autobot').logLines
        self.logEdit.SetValue('\n'.join([str(x) for x in reversed(logLines)]))
Exemplo n.º 4
0
class ProbeTooltipCheckboxRow(ProbeTooltipButtonBase):
    deleteFunction = None
    editFunction = None

    def ApplyAttributes(self, attributes):
        ProbeTooltipButtonBase.ApplyAttributes(self, attributes)
        self.checkBox = Checkbox(groupname=attributes.groupName,
                                 align=uiconst.CENTER,
                                 checked=attributes.checked,
                                 retval=attributes.retval,
                                 wrapLabel=True,
                                 prefstype=None,
                                 width=16,
                                 height=16,
                                 state=uiconst.UI_DISABLED)
        self.AddCell(self.checkBox, cellPadding=(5, 1, 4, 1))
        self.deleteFunction = attributes.deleteFunc
        self.editFunction = attributes.editFunc
        self.label = EveLabelSmall(text=attributes.text,
                                   bold=True,
                                   align=uiconst.CENTERLEFT,
                                   autoFitToText=True,
                                   width=128)
        self.AddCell(self.label,
                     colSpan=1 if attributes.filterIndex is not None else 2,
                     cellPadding=(0, 2, 6, 2))
        if attributes.filterIndex is not None:
            shortcutObj = ShortcutHint(text=str(attributes.filterIndex))
            self.AddCell(shortcutObj, cellPadding=(2, 2, 2, 0))
            return shortcutObj

    def OnDelete(self, *args):
        if self.deleteFunction:
            self.state = uiconst.UI_DISABLED
            if callable(self.deleteFunction):
                self.deleteFunction()
            elif isinstance(self.deleteFunction, tuple):
                func, args = self.deleteFunction
                func(*args)
            uicore.animations.FadeOut(self, duration=0.5, callback=self.Close)

    def OnEdit(self, *args):
        if callable(self.editFunction):
            self.editFunction()
        elif isinstance(self.editFunction, tuple):
            func, args = self.editFunction
            func(*args)

    def OnClick(self, *args):
        self.checkBox.ToggleState()
        if self.func:
            self.func(self.checkBox.data['value'], self.checkBox.GetValue())

    def GetMenu(self):
        m = []
        if self.editFunction:
            m.append((localization.GetByLabel('UI/Inventory/Filters/Edit'),
                      self.OnEdit))
        if self.deleteFunction:
            m.append(
                (localization.GetByLabel('UI/Common/Delete'), self.OnDelete))
        return m
class ChannelPasswordWindow(Window):
    MAX_TRIES = 3

    def ApplyAttributes(self, attributes):
        Window.ApplyAttributes(self, attributes)
        self.title = attributes.title
        self.channelID = attributes.channelID
        self.channelName = attributes.channelName
        self.displayName = attributes.displayName
        self.SetMinSize([250, 250])
        self.SetCaption(localization.GetByLabel('UI/Menusvc/PasswordRequired'))
        self.SetTopparentHeight(0)
        self.tries = 0
        settings.user.ui.Set('%sPassword' % self.channelName, '')
        parentGrid = LayoutGrid(parent=self.sr.main,
                                columns=1,
                                state=uiconst.UI_PICKCHILDREN,
                                align=uiconst.TOPLEFT,
                                left=10,
                                top=4)
        topLabel = EveLabelMedium(text=attributes.title,
                                  state=uiconst.UI_DISABLED,
                                  align=uiconst.TOPLEFT,
                                  width=300)
        parentGrid.AddCell(cellObject=topLabel)
        passwordLabel = localization.GetByLabel(
            'UI/Menusvc/PleaseEnterPassword')
        self.passwordLabel = EveLabelMedium(text=passwordLabel,
                                            state=uiconst.UI_DISABLED,
                                            align=uiconst.TOPLEFT,
                                            padTop=10)
        parentGrid.AddCell(cellObject=self.passwordLabel)
        self.passwordEdit = SinglelineEdit(name='passwordEdit',
                                           align=uiconst.TOTOP,
                                           passwordCharacter=u'\u2022',
                                           top=4)
        parentGrid.AddCell(cellObject=self.passwordEdit)
        savePasswordLabel = localization.GetByLabel('UI/Chat/SavePassword')
        self.rememberPwdCb = Checkbox(text=savePasswordLabel,
                                      configName='rememberPwdCb',
                                      retval=1,
                                      checked=0,
                                      groupname=None,
                                      align=uiconst.TOTOP)
        parentGrid.AddCell(cellObject=self.rememberPwdCb)
        parentGrid.RefreshGridLayout()
        self.btnGroup = ButtonGroup(parent=self.sr.main, idx=0)
        self.btnGroup.AddButton(
            localization.GetByLabel('UI/Chat/ChannelWindow/JoinChannel'),
            self.TryPassword, ())
        self.btnGroup.AddButton(localization.GetByLabel('UI/Common/Cancel'),
                                self.Close, ())
        self.height = self.btnGroup.height + parentGrid.height + self.sr.headerParent.height + parentGrid.top + 10
        self.width = parentGrid.width + 2 * parentGrid.left
        self.MakeUnResizeable()
        self.MakeUnMinimizable()
        self.MakeUncollapseable()

    def TryPassword(self):
        password = self.passwordEdit.GetValue()
        password = password.strip()
        if len(password) < 1:
            eve.Message('CustomInfo', {
                'info':
                localization.GetByLabel('UI/Common/PleaseTypeSomething')
            })
            return
        self.tries += 1
        savePassword = self.rememberPwdCb.GetValue()
        didWork = sm.GetService('LSC').TryOpenChannel(self.channelID,
                                                      self.channelName,
                                                      password, savePassword)
        if didWork is True:
            self.Close()
            return
        self.passwordEdit.SetValue('')
        uicore.Message('uiwarning03')
        self.passwordLabel.text = localization.GetByLabel(
            'UI/Menusvc/PleaseTryEnteringPasswordAgain')
        if self.tries >= self.MAX_TRIES:
            if didWork is False and password is not None:
                sm.GetService('LSC').OpenChannel(
                    self.channelID, 0, ('LSCWrongPassword', {
                        'channelName': self.displayName
                    }))
            self.Close()
Exemplo n.º 6
0
class PerformanceBenchmarkWindow(Window):
    default_caption = 'Performance Tools'
    default_windowID = 'PerformanceToolsWindowID'
    default_width = 220
    default_height = 200
    default_topParentHeight = 0
    default_minSize = (default_width, default_height)
    default_wontUseThis = 10

    def ApplyAttributes(self, attributes):
        Window.ApplyAttributes(self, attributes)
        self.lastPitch = 0.0
        self.lastYaw = 0.0
        self.camLock = False
        self.benchmarkDuration = BENCHMARK_DEFAULT_DURATION_IN_MS
        self.benchmarkRunning = False
        self.sceneDirector = SceneDirector()
        self.testOptions = [('classic cube of death', CUBE_CLASSIC),
                            ('capital wrecks of death', CUBE_CAPITAL_WRECKS),
                            ('AmarrCube', CUBE_AMARR),
                            ('CaldariCube', CUBE_CALDARI),
                            ('GallenteCube', CUBE_GALLENTE),
                            ('MinmatarCube', CUBE_MINMATAR),
                            ('UltraLODCube', CUBE_LOD),
                            ('Add More Here', CUBE_ADD_MORE_HERE)]
        self.testCaseDescription = {
            CUBE_CLASSIC: 'Spawns a cube with a lot of different ships.',
            CUBE_CAPITAL_WRECKS: 'Spawns a cube with a lot of wrecks.',
            CUBE_AMARR: 'Spawns a cube of Amarr ships.',
            CUBE_CALDARI: 'Spawns a cube of Caldari ships.',
            CUBE_GALLENTE: 'Spawns a cube of Gallente ships.',
            CUBE_MINMATAR: 'Spawns a cube of Minmatar ships.',
            CUBE_LOD: 'Spawns a cube of ships around the camera.',
            CUBE_ADD_MORE_HERE: 'Does nothing useful.'
        }
        self.camPresetOptions = [('None', CAMERA_PRESET_NONE),
                                 ('Deathcube Far', CAMERA_PRESET_FAR),
                                 ('Deathcube Near', CAMERA_PRESET_NEAR),
                                 ('Deathcube UltraLOD',
                                  CAMERA_PRESET_ULTRA_LOD)]
        self._AddHeader('Test Cases')
        self._SetupTestCasePanel(self.sr.main)
        self._AddHeader('Camera')
        self._SetupCameraPanel(self.sr.main)
        self._AddHeader('Duration')
        self._SetupDurationPanel(self.sr.main)
        self.benchmarkButton = Button(name='myButton',
                                      parent=self.sr.main,
                                      align=uiconst.CENTERBOTTOM,
                                      label='Start Benchmark',
                                      func=self.ToggleBenchmark,
                                      width=40,
                                      padding=(0, 0, 0, 6))

    def _AddHeader(self, text):
        EveHeaderSmall(parent=self.sr.main,
                       text=text,
                       align=uiconst.TOTOP,
                       padding=(8, 6, 0, 3))

    def _SetupTestCasePanel(self, mainCont):
        cont = Container(name='cont',
                         parent=mainCont,
                         align=uiconst.TOTOP,
                         padLeft=4,
                         padRight=4,
                         height=40)
        self.testCombo = Combo(parent=cont,
                               align=uiconst.TOTOP,
                               options=self.testOptions,
                               callback=self.TestComboChanged)
        self.testCombo.SetHint(self.testCaseDescription[1])
        buttonBox = Container(name='buttonBox',
                              parent=cont,
                              align=uiconst.TOTOP,
                              padTop=3,
                              height=20)
        self.stayHereCheckbox = Checkbox(parent=buttonBox,
                                         text=u'Stay where you are',
                                         align=uiconst.TOLEFT,
                                         checked=False,
                                         height=18,
                                         width=120)
        Button(parent=buttonBox,
               label='Spawn',
               align=uiconst.TORIGHT,
               func=self.SpawnTestcase,
               width=40,
               height=18)
        Button(parent=buttonBox,
               label='Clear',
               align=uiconst.TORIGHT,
               func=self.sceneDirector.ClearAll,
               width=40,
               height=18)
        Button(parent=buttonBox,
               label='Damage',
               align=uiconst.TORIGHT,
               func=self.sceneDirector.ApplyDamage,
               width=40,
               height=18,
               hint='Wait for ships to load before calling this')

    def _SetupCameraPanel(self, mainCont):
        presetCont = Container(name='presetCont',
                               parent=mainCont,
                               align=uiconst.TOTOP,
                               height=20,
                               padLeft=4,
                               padRight=4)
        Label(name='presetCombo',
              parent=presetCont,
              align=uiconst.TOLEFT,
              width=40,
              text='Preset')
        self.cboCamPresets = Combo(parent=presetCont,
                                   align=uiconst.TOTOP,
                                   options=self.camPresetOptions,
                                   callback=self.OnCamPreset)
        pitchCont = Container(name='pitchCont',
                              parent=mainCont,
                              align=uiconst.TOTOP,
                              height=20,
                              padLeft=4,
                              padRight=4)
        Label(name='pitchLabel',
              parent=pitchCont,
              align=uiconst.TOLEFT,
              width=40,
              padTop=3,
              text='Pitch')
        self.pitchField = SinglelineEdit(name='pitchField',
                                         parent=pitchCont,
                                         align=uiconst.TOTOP,
                                         floats=[-90.0, 90.0, 1],
                                         setvalue=str(self.lastPitch))
        self.pitchField.OnChange = self.OnCamChange
        yawCont = Container(name='yawCont',
                            parent=mainCont,
                            align=uiconst.TOTOP,
                            height=20,
                            padLeft=4,
                            padRight=4)
        Label(name='yawLabel',
              parent=yawCont,
              align=uiconst.TOLEFT,
              width=40,
              padTop=3,
              text='Yaw')
        self.yawField = SinglelineEdit(name='yawField',
                                       parent=yawCont,
                                       align=uiconst.TOTOP,
                                       floats=[-180.0, 180.0, 1],
                                       setvalue=str(self.lastYaw))
        self.yawField.OnChange = self.OnCamChange
        panCont = Container(name='panCont',
                            parent=mainCont,
                            align=uiconst.TOTOP,
                            height=20,
                            padLeft=4,
                            padRight=4)
        Label(name='panLabel',
              parent=panCont,
              align=uiconst.TOLEFT,
              width=40,
              padTop=3,
              text='Pan')
        self.panField = SinglelineEdit(
            name='panField',
            parent=panCont,
            align=uiconst.TOTOP,
            ints=[MIN_PAN_DISTANCE, MAX_PAN_DISTANCE],
            setvalue=0)
        self.panField.OnChange = self.OnCamChange
        buttonBox = Container(name='buttonBox',
                              parent=mainCont,
                              align=uiconst.TOTOP,
                              padTop=3,
                              height=20)
        Button(
            parent=buttonBox,
            label='Capture camera coords',
            align=uiconst.TORIGHT,
            func=self.OnStoreCurrentCameraValues,
            width=40,
            height=18,
            hint=
            'Captures the current camera coordinates and saves them in the input fields'
        )
        uthread.new(self._GetCurrentCameraValues)

    def _SetupDurationPanel(self, parent):
        maxSeconds = int(BENCHMARK_MAX_DURATION_IN_MS / 1000)
        defaultSeconds = int(BENCHMARK_DEFAULT_DURATION_IN_MS / 1000)
        self.durationSlider = Slider(
            name='mySlider',
            parent=parent,
            minValue=1,
            maxValue=maxSeconds,
            startVal=defaultSeconds,
            increments=[i + 1 for i in xrange(maxSeconds)],
            onsetvaluefunc=self._OnTimeChanged,
            align=uiconst.TOTOP,
            padLeft=10,
            padRight=10)
        self.progress = Gauge(name='progress',
                              parent=parent,
                              color=Color.WHITE,
                              align=uiconst.TOTOP,
                              padTop=20,
                              padLeft=10,
                              padRight=10)
        self._OnTimeChanged(self.durationSlider)

    def _OnTimeChanged(self, slider):
        self.benchmarkDuration = slider.GetValue() * 1000

    def TestComboChanged(self, *args):
        self.testCombo.SetHint(
            self.testCaseDescription[self.testCombo.GetValue()])

    def OnCamChange(self, *args):
        if self.camLock:
            return
        self.lastPitch = float(self.pitchField.GetValue())
        self.lastYaw = float(self.yawField.GetValue())
        self.pan = int(self.panField.GetValue())
        self.sceneDirector.SetCamera(self.lastYaw, self.lastPitch, self.pan)

    def OnCamPreset(self, *args):
        presId = self.cboCamPresets.GetValue()
        if presId == 0:
            return
        pitch, yaw, pan = CAMERA_PRESETS[presId]
        self.camLock = True
        self.pitchField.SetValue(pitch)
        self.yawField.SetValue(yaw)
        self.panField.SetValue(pan)
        self.camLock = False
        self.OnCamChange()

    def _GetMemoryUsage(self):
        try:
            meg = 1.0 / 1024.0 / 1024.0
            mem, pymem, workingset, pagefaults, bluemem = blue.pyos.cpuUsage[
                -1][2]
            return mem * meg
        except:
            pass

        return 0

    def ToggleBenchmark(self, *args):
        self.progress.SetValue(0)

        def _thread():
            frameTimes = []
            graphData = {}
            t0 = blue.os.GetWallclockTime()
            startTime = blue.os.GetWallclockTime()
            startMem = self._GetMemoryUsage()
            while self.benchmarkRunning:
                blue.synchro.Yield()
                t1 = blue.os.GetWallclockTime()
                ms = float(blue.os.TimeDiffInUs(t0, t1)) / 1000.0
                t0 = t1
                frameTimes.append(ms)
                timeFromStartInMs = float(blue.os.TimeDiffInUs(startTime,
                                                               t1)) / 1000.0
                graphData[timeFromStartInMs] = ms
                if blue.os.TimeDiffInMs(startTime,
                                        t1) > self.benchmarkDuration:
                    self.benchmarkRunning = False
                    break
                self.progress.SetValue(timeFromStartInMs /
                                       self.benchmarkDuration,
                                       animate=False)

            frameTimes.sort()
            median = frameTimes[len(frameTimes) / 2]
            minMS = frameTimes[0]
            maxMS = frameTimes[-1]
            summed = reduce(lambda x, y: x + y, frameTimes)
            avg = summed / len(frameTimes)
            result = 'Min: %0.1fms Max: %0.1fms\n' % (minMS, maxMS)
            result += 'Median:  %0.1fms %0.1ffps\n' % (median, 1000.0 / median)
            result += 'Average: %0.1fms %0.1ffps\n' % (avg, 1000.0 / avg)
            endMem = self._GetMemoryUsage()
            result += 'Start Memory Usage: %0.1fmb\n' % (startMem, )
            result += 'End Memory Usage: %0.1fmb\n' % (endMem, )
            ResultDialog.Open(resultText=result, graphData=graphData)
            self.benchmarkButton.SetLabel('Start Benchmark')

        if self.benchmarkRunning:
            self.benchmarkRunning = False
        else:
            self.benchmarkRunning = True
            self.benchmarkButton.SetLabel('Stop Benchmark')
            uthread.new(_thread)

    def OnStoreCurrentCameraValues(self, *args):
        self._GetCurrentCameraValues()

    def _GetCurrentCameraValues(self):
        self.camLock = True
        cam = sm.GetService('sceneManager').GetActiveCamera()
        self.lastPitch = math.degrees(cam.pitch)
        self.lastYaw = math.degrees(cam.yaw)
        self.pan = pan = ClampPan(int(cam.GetZoomDistance()))
        self.pitchField.SetValue(self.lastPitch)
        self.yawField.SetValue(self.lastYaw)
        self.panField.SetValue(self.pan)
        self.camLock = False
        self.OnCamChange()

    def SpawnTestcase(self, *args):
        testID = self.testCombo.GetValue()
        stayHere = self.stayHereCheckbox.GetValue()
        startPos = self.sceneDirector.GoToAndReturnStartPosition(stayHere)
        self.sceneDirector.SpawnTestcase(testID, startPos)