示例#1
0
    def ConstructLines(self):
        for line in self.lines:
            line.Close()

        self.lines = []
        usedRows = int(ceil(len(self.materialsData) / float(self.perRow)))
        pointsStart = self.GetLineStartingPoints()
        pConnect = self.GetLineConnectionPoint(pointsStart)
        y = self.top + self.materialsCont.top + self.materialsCont.height / 2
        x = self.GetLineCirceOffset(y)
        width, height = self.parent.GetCurrentAbsoluteSize()
        self.pCircleIntersect = (width / 2 - x, pConnect[1])
        pEnd = geo2.Vec2Subtract(self.pCircleIntersect,
                                 (1 * RADIUS_CONNECTOR_SMALL, 0))
        if len(pointsStart) == 1:
            self.DrawLine((pointsStart[0], pEnd))
        else:
            for point in pointsStart:
                if point[1] == pEnd[1]:
                    self.DrawLine((point, geo2.Vec2Subtract(pConnect, (3, 0))))
                else:
                    self.DrawLine((point, (pConnect[0], point[1]), pConnect))

            self.DrawLine((geo2.Vec2Add(pConnect, (3, 0)), pEnd))
        if not self.connectorCircle:
            self.connectorCircle = MaterialGroupDashedCircle(
                parent=self.materialsCont,
                numSegments=len(self.materialsData),
                radius=RADIUS_CONNECTOR_SMALL,
                materialsByGroupID=((self.industryGroupID,
                                     self.materialsData), ),
                jobData=self.jobData)
        self.connectorCircle.left = pEnd[0]
        self.connectorCircle.top = pEnd[1] - RADIUS_CONNECTOR_SMALL
        self.UpdateState(animate=False)
 def DrawBigConnectorCircle(self, groupsData):
     x, y = self.GetPointBigCircleLeft()
     if not self.bigConnectorCircle:
         self.bigConnectorCircle = MaterialGroupDashedCircle(
             name='bigConnectorCircle',
             parent=self,
             radius=industryUIConst.RADIUS_CONNECTOR_LARGE,
             color=industryUIConst.COLOR_READY,
             numSegments=len(groupsData),
             lineWidth=3.0,
             materialsByGroupID=groupsData,
             jobData=self.jobData)
         self.bigConnectorCircle.UpdateState(1)
     self.bigConnectorCircle.left = x
     self.bigConnectorCircle.top = y - industryUIConst.RADIUS_CONNECTOR_LARGE
class MaterialGroups(Container):
    default_name = 'MaterialGroups'
    __notifyevents__ = ['OnMultipleItemChange', 'OnUIScalingChange']

    def ApplyAttributes(self, attributes):
        Container.ApplyAttributes(self, attributes)
        sm.RegisterNotify(self)
        self.jobData = attributes.jobData
        self.materialGroups = []
        self.lines = []
        self.fromLine = None
        self.bigConnectorCircle = None
        self.animateTextThread = None
        noItemsLabelCont = Container(
            parent=self,
            align=uiconst.TOPLEFT_PROP,
            pos=(0.0, 0.5, 0.5, 500),
            padRight=industryUIConst.RADIUS_CENTERCIRCLE_OUTER)
        self.noItemsRequiredLabel = EveCaptionMedium(
            name='noItemsRequiredLabel',
            parent=noItemsLabelCont,
            align=uiconst.CENTER,
            opacity=0.0)
        self.bg = StretchSpriteHorizontal(name='groupBackground',
                                          parent=self,
                                          align=uiconst.TOLEFT_PROP,
                                          state=uiconst.UI_DISABLED,
                                          width=0.5,
                                          height=402,
                                          leftEdgeSize=10,
                                          rightEdgeSize=400)
        groupsData = self.GetMaterialGroups()
        self.ConstructGroups(groupsData)
        self.ConstructLines(groupsData)
        self.UpdateState()
        self.AnimEntry()

    def DrawBigConnectorCircle(self, groupsData):
        x, y = self.GetPointBigCircleLeft()
        if not self.bigConnectorCircle:
            self.bigConnectorCircle = MaterialGroupDashedCircle(
                name='bigConnectorCircle',
                parent=self,
                radius=industryUIConst.RADIUS_CONNECTOR_LARGE,
                color=industryUIConst.COLOR_READY,
                numSegments=len(groupsData),
                lineWidth=3.0,
                materialsByGroupID=groupsData,
                jobData=self.jobData)
            self.bigConnectorCircle.UpdateState(1)
        self.bigConnectorCircle.left = x
        self.bigConnectorCircle.top = y - industryUIConst.RADIUS_CONNECTOR_LARGE

    def ConstructLines(self, groupsData):
        for line in self.lines:
            line.Close()

        if self.fromLine:
            self.fromLine.Close()
        self.lines = []
        if self.materialGroups:
            self.DrawBigConnectorCircle(groupsData)
            self.DrawLines()
        if self.jobData:
            self.DrawLineFromCenter()

    def GetStatusText(self):
        if self.jobData:
            status = self.jobData.status
            if status == industry.STATUS_UNSUBMITTED:
                text = GetByLabel('UI/Industry/NoInputItemsRequired')
            elif status == industry.STATUS_INSTALLED:
                text = GetByLabel('UI/Industry/JobActive')
            elif status == industry.STATUS_READY:
                text = GetByLabel('UI/Industry/JobReadyForDelivery')
            else:
                text = self.jobData.GetJobStateLabel()
        else:
            text = GetByLabel('UI/Industry/NoBlueprintSelectedCaption')
        return text

    def ConstructGroups(self, groupsData):
        for group in self.materialGroups:
            group.Close()

        self.materialGroups = []
        numGroups = max(len(groupsData) - 1, 0)
        numRowsByGroupIdx = GROUP_NUMROWS[numGroups]
        if groupsData:
            top = 1
            for i, (industryGroupID, materialsData) in enumerate(groupsData):
                numRows = numRowsByGroupIdx[i]
                height = 60 * numRows + 8 * max(0, numRows - 1)
                materialGroup = MaterialGroup(parent=self,
                                              industryGroupID=industryGroupID,
                                              jobData=self.jobData,
                                              materialsData=materialsData,
                                              pos=(0, top, 400, height),
                                              numRows=numRows,
                                              opacity=0.0)
                top += height + 8
                self.materialGroups.append(materialGroup)

            statusText = ''
        else:
            statusText = self.GetStatusText()
        self.AnimateStateText(statusText)
        self.bg.SetTexturePath(GROUP_BACKGROUNDS[numGroups])

    def AnimateStateText(self, text):
        if self.animateTextThread:
            self.animateTextThread.kill()
        self.animateTextThread = uthread.new(self._AnimateStateText, text)

    def _AnimateStateText(self, text):
        if self.noItemsRequiredLabel.text:
            uicore.animations.FadeOut(self.noItemsRequiredLabel,
                                      duration=0.3,
                                      sleep=True)
        self.noItemsRequiredLabel.text = text
        uicore.animations.FadeTo(self.noItemsRequiredLabel,
                                 0.0,
                                 0.9,
                                 duration=0.6)
        self.animateTextThread = None

    def GetInnerCircleIntersectPoint(self, y):
        """
        Returns inner circle intersection point and angle (in radians)
        of line coming from a group, given y-coordinate of that line
        """
        pCenter = self.GetPointCenter()
        y = pCenter[1] - y
        th = asin(y / industryUIConst.RADIUS_CENTERCIRCLE_OUTER) + pi
        r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
        p = (r * cos(th), r * sin(th))
        p = geo2.Vec2Add(p, pCenter)
        return (p, th)

    def GetOuterCirclePoint(self, p, p1):
        """
        Offset point by radius of connector circle
        """
        l = industryUIConst.RADIUS_CENTERCIRCLE_OUTER - industryUIConst.RADIUS_CENTERCIRCLE_INNER
        t = 1.0 - (l - industryUIConst.RADIUS_CONNECTOR_SMALL) / l
        return geo2.Vec2Lerp(p, p1, t)

    def DrawLine(self, points):
        line = IndustryLineTrace(parent=self, opacity=0.0)
        line.AddPoints(points)
        self.lines.append(line)

    def DrawLineFromCenter(self):
        self.fromLine = IndustryLineTrace(name='fromLine',
                                          parent=self,
                                          opacity=0.0)
        self.fromLine.AddPoints(
            (self.GetPointCenter(), self.GetPointCenterRight()))

    def DrawLineToCenter(self, p):
        self.DrawLine((p, self.GetPointBigCircleLeft()))
        self.DrawLine((self.GetPointBigCircleRight(), self.GetPointCenter()))

    def GetPointCenter(self):
        width, height = self.GetAbsoluteSize()
        return (width / 2, height / 2 + 1)

    def GetPointBigCircleLeft(self):
        x, y = self.GetPointCenter()
        return (x - BIGCIRCLE_OFFSET - industryUIConst.RADIUS_CONNECTOR_LARGE,
                y)

    def GetPointBigCircleRight(self):
        x, y = self.GetPointCenter()
        return (x - BIGCIRCLE_OFFSET + industryUIConst.RADIUS_CONNECTOR_LARGE,
                y)

    def GetPointCenterLeft(self):
        x, y = self.GetPointCenter()
        return (x - industryUIConst.RADIUS_CENTERCIRCLE_INNER, y)

    def GetPointCenterRight(self):
        w, h = self.GetCurrentAbsoluteSize()
        return (w - 334, h / 2.0)

    def DrawLines(self):
        """
        Draw lines connecting materialGroups to center circle
        """
        x1, y1 = self.GetAbsolutePosition()
        linePoints = []
        thetas = []
        for materialGroup in self.materialGroups:
            x0, y0 = materialGroup.GetEndPoint()
            p = (x0, materialGroup.top + materialGroup.height / 2.0)
            p1, theta = self.GetInnerCircleIntersectPoint(p[1])
            thetas.append(theta)
            p0 = self.GetOuterCirclePoint(p, p1)
            linePoints.append((p0, p1))

        if len(linePoints) == 1:
            p = linePoints[0][0]
            self.DrawLineToCenter(p)
            return
        thetaFirst = thetas[0]
        thetaLast = thetas[-1]
        numPoints = int(fabs((thetaFirst - thetaLast) * 8))
        stepSize = (thetaLast - thetaFirst) / numPoints
        lineStart = linePoints.pop(0)
        arcPoints = [lineStart[0]]
        r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
        for i in xrange(numPoints):
            th = thetaFirst + float(i) * stepSize
            p = (r * cos(th), r * sin(th))
            p = geo2.Vec2Add(self.GetPointCenter(), p)
            arcPoints.append(p)

        lineEnd = linePoints.pop()
        arcPoints.extend([lineEnd[1], lineEnd[0]])
        self.DrawLine(arcPoints)
        for p0, p1 in linePoints:
            self.DrawLine((p0, p1))

        self.DrawLineToCenter(self.GetPointCenterLeft())

    def AnimEntry(self, animate=True):
        k = 0.05
        for i, materialGroup in enumerate(self.materialGroups):
            if animate:
                uicore.animations.FadeTo(materialGroup,
                                         0.0,
                                         1.0,
                                         duration=0.3,
                                         timeOffset=k * i)
            else:
                materialGroup.opacity = 1.0
            materialGroup.AnimEntry(k * i, animate=animate)

        i = 0
        for i, line in enumerate(self.lines):
            line.AnimEntry(0.2, i, animate=animate)

        if self.fromLine:
            self.fromLine.AnimEntry(0.8, i + 1, animate=animate)
        if self.jobData and animate:
            uicore.animations.FadeTo(self.bg, 0.0, 1.0, duration=0.6)

    def GetMaterialGroups(self):
        if not self.jobData:
            return []
        else:
            return self.jobData.GetMaterialsByGroups()

    def OnMultipleItemChange(self, items, change):
        self.OnRunsChanged()

    def OnRunsChanged(self):
        for materialGroup in self.materialGroups:
            materialGroup.OnRunsChanged()

        self.UpdateState()

    def OnNewJobData(self, jobData):
        self.jobData = jobData
        groupsData = self.GetMaterialGroups()
        if self.bigConnectorCircle:
            self.bigConnectorCircle.Close()
            self.bigConnectorCircle = None
        self.ConstructGroups(groupsData)
        self.ConstructLines(groupsData)
        self.UpdateState(animate=False)
        self.AnimEntry()

    def UpdateState(self, animate=True):
        isReady = self.IsAllGroupsReady()
        for i, line in enumerate(self.lines):
            line.UpdateColor(isReady, animate=animate)

        if self.fromLine:
            self.fromLine.UpdateColor(isReady, animate=animate)
        if self.bigConnectorCircle:
            self.bigConnectorCircle.UpdateState(self.GetNumGroupsReady(),
                                                self.IsAllGroupsReady())

    def IsAllGroupsReady(self):
        for group in self.materialGroups:
            if not group.IsReady():
                return False

        return True

    def GetNumGroupsReady(self):
        return sum(
            [materialGroup.IsReady() for materialGroup in self.materialGroups])

    def OnUIScalingChange(self, *args):
        self.OnNewJobData(self.jobData)

    def _OnResize(self, *args):
        if not self.jobData:
            return
        for group in self.materialGroups:
            group.ConstructLines()

        self.ConstructLines(self.GetMaterialGroups())
        self.UpdateState(animate=False)
        self.AnimEntry(animate=False)
示例#4
0
class MaterialGroup(Container):
    default_name = 'MaterialGroup'
    default_height = 60
    default_alignMode = uiconst.TOPLEFT
    default_align = uiconst.TOPLEFT

    def ApplyAttributes(self, attributes):
        Container.ApplyAttributes(self, attributes)
        self.jobData = attributes.jobData
        self.materialsData = attributes.materialsData
        self.numRows = attributes.numRows
        self.industryGroupID = attributes.industryGroupID
        self.perRow = self.GetNumPerRow()
        self.materials = []
        self.lines = []
        self.connectorCircle = None
        self.pCircleIntersect = None
        self.materialsCont = ContainerAutoSize(name='materialsCont',
                                               parent=self,
                                               align=uiconst.TOPLEFT,
                                               alignMode=uiconst.TOPLEFT)
        self.icon = GroupIconSprite(name='icon',
                                    parent=self,
                                    align=uiconst.CENTERLEFT,
                                    pos=(7, 0, 22, 22),
                                    industryGroupID=self.industryGroupID)
        self.ConstructMaterials()
        self.ConstructLines()

    def AnimEntry(self, timeOffset, animate=True):
        for i, material in enumerate(self.materials):
            if animate:
                uicore.animations.FadeTo(material,
                                         0.0,
                                         1.0,
                                         duration=0.3,
                                         timeOffset=timeOffset + i * 0.02)
            else:
                material.opacity = 1.0

        for i, line in enumerate(self.lines):
            line.AnimEntry(timeOffset, i, animate)

        if animate:
            uicore.animations.FadeTo(self.connectorCircle,
                                     0.0,
                                     1.0,
                                     duration=0.3,
                                     timeOffset=timeOffset)
        else:
            self.connectorCircle.opacity = 1.0

    def ConstructLines(self):
        for line in self.lines:
            line.Close()

        self.lines = []
        usedRows = int(ceil(len(self.materialsData) / float(self.perRow)))
        pointsStart = self.GetLineStartingPoints()
        pConnect = self.GetLineConnectionPoint(pointsStart)
        y = self.top + self.materialsCont.top + self.materialsCont.height / 2
        x = self.GetLineCirceOffset(y)
        width, height = self.parent.GetCurrentAbsoluteSize()
        self.pCircleIntersect = (width / 2 - x, pConnect[1])
        pEnd = geo2.Vec2Subtract(self.pCircleIntersect,
                                 (1 * RADIUS_CONNECTOR_SMALL, 0))
        if len(pointsStart) == 1:
            self.DrawLine((pointsStart[0], pEnd))
        else:
            for point in pointsStart:
                if point[1] == pEnd[1]:
                    self.DrawLine((point, geo2.Vec2Subtract(pConnect, (3, 0))))
                else:
                    self.DrawLine((point, (pConnect[0], point[1]), pConnect))

            self.DrawLine((geo2.Vec2Add(pConnect, (3, 0)), pEnd))
        if not self.connectorCircle:
            self.connectorCircle = MaterialGroupDashedCircle(
                parent=self.materialsCont,
                numSegments=len(self.materialsData),
                radius=RADIUS_CONNECTOR_SMALL,
                materialsByGroupID=((self.industryGroupID,
                                     self.materialsData), ),
                jobData=self.jobData)
        self.connectorCircle.left = pEnd[0]
        self.connectorCircle.top = pEnd[1] - RADIUS_CONNECTOR_SMALL
        self.UpdateState(animate=False)

    def DrawLine(self, points):
        line = IndustryLineTrace(parent=self.materialsCont)
        line.AddPoints(points)
        self.lines.append(line)

    def GetEndPoint(self):
        return self.pCircleIntersect

    def ConstructMaterials(self):
        for i, materialData in enumerate(self.materialsData):
            top = 66 * (i / self.perRow)
            cls = self.GetMaterialClass()
            material = cls(parent=self.materialsCont,
                           jobData=self.jobData,
                           materialData=materialData,
                           align=uiconst.TOPLEFT,
                           left=ICONCOLUMN_WIDTH + i % self.perRow * 48,
                           top=top)
            self.materials.append(material)

        self.materialsCont.SetSizeAutomatically()
        self.materialsCont.top = (self.height - self.materialsCont.height) / 2

    def GetMaterialClass(self):
        if self.IsOptional():
            return OptionalMaterial
        else:
            return Material

    def IsOptional(self):
        for materialData in self.materialsData:
            if not materialData.IsOptional():
                return False

        return True

    def IsOptionSelected(self):
        """
        Returns True unless all items are optional and none of them have an item selected
        """
        for materialData in self.materialsData:
            if materialData.IsOptionSelected():
                return True

        return False

    def GetLineStartingPoints(self):
        ret = defaultdict(int)
        for material in self.materials:
            x = material.left + Material.default_width
            y = material.top + Material.default_height / 2
            ret[y] = max(ret[y], x)

        ret = zip(ret.values(), ret.keys())
        return ret

    def OnRunsChanged(self):
        self.UpdateState()

    def UpdateState(self, animate=True):
        for line in self.lines:
            line.UpdateColor(self.IsReady(), self.IsOptional(),
                             self.IsOptionSelected(), animate)

        numReadySegments = sum(
            [materialData.valid for materialData in self.materialsData])
        self.connectorCircle.UpdateState(numReadySegments,
                                         self.IsReady(),
                                         self.IsOptionSelected(),
                                         animate=animate)

    def GetNumPerRow(self):
        numMaterials = len(self.materialsData)
        if self.numRows >= 2:
            if numMaterials > 3:
                return min(5, int(ceil(numMaterials / 2.0)))
        return numMaterials

    def GetLineConnectionPoint(self, points):
        """
        Returs coordinates of point where all lines coming from the groups connect
        """
        x = max((x for x, _ in points))
        x += OFFSET_CONNECTIONPOINT
        y = sum((y for _, y in points)) / len(points)
        return (x, y)

    def GetLineCirceOffset(self, y):
        """
        Returns x-part of intersection line with outer circle
        """
        r = RADIUS_CENTERCIRCLE_OUTER
        y = float(y)
        return r * cos(asin((r - y) / r))

    def IsReady(self):
        """
        Are all materials in group owned in full quantity
        """
        for materialData in self.materialsData:
            if not materialData.valid:
                return False

        return True