NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

materialGroups.py (13057B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\industry\views\materialGroups.py
      2 import math
      3 from math import acos, cos, sin, asin, pi, fabs
      4 import carbonui.const as uiconst
      5 from carbonui.primitives.container import Container
      6 from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal
      7 from carbonui.util.color import Color
      8 from eve.client.script.ui.shared.industry.views.materialGroupDashedCircle import MaterialGroupDashedCircle
      9 import industry
     10 from localization import GetByLabel
     11 from eve.client.script.ui.control.eveLabel import EveCaptionMedium
     12 from eve.client.script.ui.shared.industry import industryUIConst
     13 from eve.client.script.ui.shared.industry.views.industryLine import IndustryLineTrace
     14 from eve.client.script.ui.shared.industry.views.materialGroup import MaterialGroup
     15 import geo2
     16 import uthread
     17 from carbonui.uicore import uicore
     18 BIGCIRCLE_OFFSET = 100
     19 TOTAL_ROWS = 6
     20 GROUP_NUMROWS = ((6,),
     21  (3, 3),
     22  (2, 2, 2),
     23  (2, 1, 1, 2),
     24  (1, 1, 2, 1, 1),
     25  (1, 1, 1, 1, 1, 1))
     26 GROUP_BACKGROUNDS = {GROUP_NUMROWS[0]: 'res:/UI/Texture/Classes/Industry/Input/bg1Groups.png',
     27  GROUP_NUMROWS[1]: 'res:/UI/Texture/Classes/Industry/Input/bg2Groups.png',
     28  GROUP_NUMROWS[2]: 'res:/UI/Texture/Classes/Industry/Input/bg3Groups.png',
     29  GROUP_NUMROWS[3]: 'res:/UI/Texture/Classes/Industry/Input/bg4Groups.png',
     30  GROUP_NUMROWS[4]: 'res:/UI/Texture/Classes/Industry/Input/bg5Groups.png',
     31  GROUP_NUMROWS[5]: 'res:/UI/Texture/Classes/Industry/Input/bg6Groups.png',
     32  (2, 3, 1): 'res:/UI/Texture/Classes/Industry/Input/bgGroups_2_3_1.png',
     33  (3, 1, 1, 1): 'res:/UI/Texture/Classes/Industry/Input/bgGroups_3_1_1_1.png',
     34  (4, 2): 'res:/UI/Texture/Classes/Industry/Input/bgGroups_4_2.png',
     35  (5, 1): 'res:/UI/Texture/Classes/Industry/Input/bgGroups_5_1.png'}
     36 
     37 class MaterialGroups(Container):
     38     default_name = 'MaterialGroups'
     39     __notifyevents__ = ['OnMultipleItemChange', 'OnUIScalingChange']
     40 
     41     def ApplyAttributes(self, attributes):
     42         Container.ApplyAttributes(self, attributes)
     43         sm.RegisterNotify(self)
     44         self.jobData = attributes.jobData
     45         self.materialGroups = []
     46         self.lines = []
     47         self.fromLine = None
     48         self.bigConnectorCircle = None
     49         self.animateTextThread = None
     50         noItemsLabelCont = Container(name='noItemsLabelCont', parent=self, align=uiconst.TOPLEFT_PROP, pos=(0.0, 0.5, 0.5, 500), padRight=industryUIConst.RADIUS_CENTERCIRCLE_OUTER)
     51         self.noItemsRequiredLabel = EveCaptionMedium(name='noItemsRequiredLabel', parent=noItemsLabelCont, align=uiconst.CENTER, opacity=0.0, maxWidth=250)
     52         self.bg = StretchSpriteHorizontal(name='groupBackground', parent=self, align=uiconst.TOLEFT_PROP, state=uiconst.UI_DISABLED, width=0.5, height=402, leftEdgeSize=10, rightEdgeSize=400)
     53         groupsData = self.GetMaterialGroups()
     54         self.ConstructGroups(groupsData)
     55         self.ConstructLines(groupsData)
     56         self.UpdateState()
     57         self.AnimEntry()
     58 
     59     def DrawBigConnectorCircle(self, groupsData):
     60         x, y = self.GetPointBigCircleLeft()
     61         if not self.bigConnectorCircle:
     62             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)
     63             self.bigConnectorCircle.UpdateState(1)
     64         self.bigConnectorCircle.left = x
     65         self.bigConnectorCircle.top = y - industryUIConst.RADIUS_CONNECTOR_LARGE
     66 
     67     def ConstructLines(self, groupsData):
     68         for line in self.lines:
     69             line.Close()
     70 
     71         if self.fromLine:
     72             self.fromLine.Close()
     73         self.lines = []
     74         if self.materialGroups:
     75             self.DrawBigConnectorCircle(groupsData)
     76             self.DrawLines()
     77         if self.jobData:
     78             self.DrawLineFromCenter()
     79 
     80     def GetStatusText(self):
     81         if self.jobData:
     82             status = self.jobData.status
     83             if status == industry.STATUS_UNSUBMITTED:
     84                 text = GetByLabel('UI/Industry/NoInputItemsRequired')
     85             elif status == industry.STATUS_INSTALLED:
     86                 text = GetByLabel('UI/Industry/JobActive')
     87             elif status == industry.STATUS_READY:
     88                 text = GetByLabel('UI/Industry/JobReadyForDelivery')
     89             else:
     90                 text = self.jobData.GetJobStateLabel()
     91         else:
     92             text = GetByLabel('UI/Industry/NoBlueprintSelectedCaption')
     93         return text
     94 
     95     def ConstructGroups(self, groupsData):
     96         for group in self.materialGroups:
     97             group.Close()
     98 
     99         self.materialGroups = []
    100         numRowsByGroupIdx = self._GetNumRowsByGroup(groupsData)
    101         bgTexturePath = GROUP_BACKGROUNDS.get(numRowsByGroupIdx, 'res:/UI/Texture/Classes/Industry/Input/bg1Groups.png')
    102         if groupsData:
    103             top = 1
    104             for i, (industryGroupID, materialsData) in enumerate(groupsData):
    105                 numRows = numRowsByGroupIdx[i]
    106                 height = 60 * numRows + 8 * max(0, numRows - 1)
    107                 materialGroup = MaterialGroup(parent=self, industryGroupID=industryGroupID, jobData=self.jobData, materialsData=materialsData, pos=(0,
    108                  top,
    109                  400,
    110                  height), numRows=numRows, opacity=0.0)
    111                 top += height + 8
    112                 self.materialGroups.append(materialGroup)
    113 
    114             statusText = ''
    115         else:
    116             statusText = self.GetStatusText()
    117         self.AnimateStateText(statusText)
    118         self.bg.SetTexturePath(bgTexturePath)
    119 
    120     def _GetNumRowsByGroup(self, groupsData):
    121         numGroups = len(groupsData)
    122         numGroupsIdx = max(numGroups - 1, 0)
    123         numRowsByGroup = GROUP_NUMROWS[numGroupsIdx]
    124         MAX_MATERIAL_PER_ROW = 5
    125         rowsNeeded = []
    126         for industryGroupID, materialsData in groupsData:
    127             numMaterials = len(materialsData)
    128             numRows = int(math.ceil(float(numMaterials) / MAX_MATERIAL_PER_ROW))
    129             rowsNeeded.append(numRows)
    130 
    131         numRowsNeeded = sum(rowsNeeded)
    132         if numRowsNeeded > TOTAL_ROWS:
    133             return numRowsByGroup
    134         for shouldBe, needed in zip(numRowsByGroup, rowsNeeded):
    135             if needed > shouldBe:
    136                 if numRowsNeeded < TOTAL_ROWS:
    137                     lastRowValue = rowsNeeded[-1]
    138                     newLastRowValue = lastRowValue + (TOTAL_ROWS - numRowsNeeded)
    139                     rowsNeeded[-1] = newLastRowValue
    140                 return tuple(rowsNeeded)
    141 
    142         return numRowsByGroup
    143 
    144     def AnimateStateText(self, text):
    145         if self.animateTextThread:
    146             self.animateTextThread.kill()
    147         self.animateTextThread = uthread.new(self._AnimateStateText, text)
    148 
    149     def _AnimateStateText(self, text):
    150         if self.noItemsRequiredLabel.text:
    151             uicore.animations.FadeOut(self.noItemsRequiredLabel, duration=0.3, sleep=True)
    152         self.noItemsRequiredLabel.text = text
    153         uicore.animations.FadeTo(self.noItemsRequiredLabel, 0.0, 0.9, duration=0.6)
    154         self.animateTextThread = None
    155 
    156     def GetInnerCircleIntersectPoint(self, y):
    157         pCenter = self.GetPointCenter()
    158         y = pCenter[1] - y
    159         th = asin(y / industryUIConst.RADIUS_CENTERCIRCLE_OUTER) + pi
    160         r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
    161         p = (r * cos(th), r * sin(th))
    162         p = geo2.Vec2Add(p, pCenter)
    163         return (p, th)
    164 
    165     def GetOuterCirclePoint(self, p, p1):
    166         l = industryUIConst.RADIUS_CENTERCIRCLE_OUTER - industryUIConst.RADIUS_CENTERCIRCLE_INNER
    167         t = 1.0 - (l - industryUIConst.RADIUS_CONNECTOR_SMALL) / l
    168         return geo2.Vec2Lerp(p, p1, t)
    169 
    170     def DrawLine(self, points):
    171         line = IndustryLineTrace(parent=self, opacity=0.0)
    172         line.AddPoints(points)
    173         self.lines.append(line)
    174 
    175     def DrawLineFromCenter(self):
    176         self.fromLine = IndustryLineTrace(name='fromLine', parent=self, opacity=0.0)
    177         self.fromLine.AddPoints((self.GetPointCenter(), self.GetPointCenterRight()))
    178 
    179     def DrawLineToCenter(self, p):
    180         self.DrawLine((p, self.GetPointBigCircleLeft()))
    181         self.DrawLine((self.GetPointBigCircleRight(), self.GetPointCenter()))
    182 
    183     def GetPointCenter(self):
    184         width, height = self.GetAbsoluteSize()
    185         return (width / 2, height / 2 + 1)
    186 
    187     def GetPointBigCircleLeft(self):
    188         x, y = self.GetPointCenter()
    189         return (x - BIGCIRCLE_OFFSET - industryUIConst.RADIUS_CONNECTOR_LARGE, y)
    190 
    191     def GetPointBigCircleRight(self):
    192         x, y = self.GetPointCenter()
    193         return (x - BIGCIRCLE_OFFSET + industryUIConst.RADIUS_CONNECTOR_LARGE, y)
    194 
    195     def GetPointCenterLeft(self):
    196         x, y = self.GetPointCenter()
    197         return (x - industryUIConst.RADIUS_CENTERCIRCLE_INNER, y)
    198 
    199     def GetPointCenterRight(self):
    200         w, h = self.GetCurrentAbsoluteSize()
    201         return (w - 334, h / 2.0)
    202 
    203     def DrawLines(self):
    204         x1, y1 = self.GetAbsolutePosition()
    205         linePoints = []
    206         thetas = []
    207         for materialGroup in self.materialGroups:
    208             pCircleIntersect = materialGroup.GetEndPoint()
    209             if pCircleIntersect is None:
    210                 continue
    211             x0, y0 = pCircleIntersect
    212             p = (x0, materialGroup.top + materialGroup.height / 2.0)
    213             p1, theta = self.GetInnerCircleIntersectPoint(p[1])
    214             thetas.append(theta)
    215             p0 = self.GetOuterCirclePoint(p, p1)
    216             linePoints.append((p0, p1))
    217 
    218         if len(linePoints) == 1:
    219             p = linePoints[0][0]
    220             self.DrawLineToCenter(p)
    221             return
    222         if not thetas:
    223             return
    224         thetaFirst = thetas[0]
    225         thetaLast = thetas[-1]
    226         numPoints = int(fabs((thetaFirst - thetaLast) * 8))
    227         stepSize = (thetaLast - thetaFirst) / numPoints
    228         lineStart = linePoints.pop(0)
    229         arcPoints = [lineStart[0]]
    230         r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
    231         for i in xrange(numPoints):
    232             th = thetaFirst + float(i) * stepSize
    233             p = (r * cos(th), r * sin(th))
    234             p = geo2.Vec2Add(self.GetPointCenter(), p)
    235             arcPoints.append(p)
    236 
    237         lineEnd = linePoints.pop()
    238         arcPoints.extend([lineEnd[1], lineEnd[0]])
    239         self.DrawLine(arcPoints)
    240         for p0, p1 in linePoints:
    241             self.DrawLine((p0, p1))
    242 
    243         self.DrawLineToCenter(self.GetPointCenterLeft())
    244 
    245     def AnimEntry(self, animate = True):
    246         k = 0.05
    247         for i, materialGroup in enumerate(self.materialGroups):
    248             if animate:
    249                 uicore.animations.FadeTo(materialGroup, 0.0, 1.0, duration=0.3, timeOffset=k * i)
    250             else:
    251                 materialGroup.opacity = 1.0
    252             materialGroup.AnimEntry(k * i, animate=animate)
    253 
    254         i = 0
    255         for i, line in enumerate(self.lines):
    256             line.AnimEntry(0.2, i, animate=animate)
    257 
    258         if self.fromLine:
    259             self.fromLine.AnimEntry(0.8, i + 1, animate=animate)
    260         if self.jobData and animate:
    261             uicore.animations.FadeTo(self.bg, 0.0, 1.0, duration=0.6)
    262 
    263     def GetMaterialGroups(self):
    264         if not self.jobData:
    265             return []
    266         else:
    267             return self.jobData.GetMaterialsByGroups()
    268 
    269     def OnMultipleItemChange(self, items, change):
    270         self.OnRunsChanged()
    271 
    272     def OnRunsChanged(self):
    273         for materialGroup in self.materialGroups:
    274             materialGroup.OnRunsChanged()
    275 
    276         self.UpdateState()
    277 
    278     def OnNewJobData(self, jobData):
    279         if self.destroyed:
    280             return
    281         self.jobData = jobData
    282         groupsData = self.GetMaterialGroups()
    283         if self.bigConnectorCircle:
    284             self.bigConnectorCircle.Close()
    285             self.bigConnectorCircle = None
    286         self.ConstructGroups(groupsData)
    287         self.ConstructLines(groupsData)
    288         self.UpdateState(animate=False)
    289         self.AnimEntry()
    290 
    291     def UpdateState(self, animate = True):
    292         isReady = self.IsAllGroupsReady()
    293         for i, line in enumerate(self.lines):
    294             line.UpdateColor(isReady, animate=animate)
    295 
    296         if self.fromLine:
    297             self.fromLine.UpdateColor(isReady, animate=animate)
    298         if self.bigConnectorCircle:
    299             self.bigConnectorCircle.UpdateState(self.GetNumGroupsReady(), self.IsAllGroupsReady())
    300 
    301     def IsAllGroupsReady(self):
    302         for group in self.materialGroups:
    303             if not group.IsReady():
    304                 return False
    305 
    306         return True
    307 
    308     def GetNumGroupsReady(self):
    309         return sum([ materialGroup.IsReady() for materialGroup in self.materialGroups ])
    310 
    311     def OnUIScalingChange(self, *args):
    312         self.OnNewJobData(self.jobData)
    313 
    314     def _OnResize(self, *args):
    315         if not self.jobData:
    316             return
    317         for group in self.materialGroups:
    318             group.ConstructLines()
    319 
    320         self.ConstructLines(self.GetMaterialGroups())
    321         self.UpdateState(animate=False)
    322         self.AnimEntry(animate=False)