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

circleView.py (8745B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\careerPortal\circleView\circleView.py
      2 import math
      3 import carbonui.const as uiconst
      4 import telemetry
      5 import trinity
      6 from carbonui.primitives.container import Container
      7 from carbonui.primitives.transform import Transform
      8 from carbonui.primitives.vectorlinetrace import DashedCircle
      9 from carbonui.uianimations import animations
     10 from carbonui.uicore import uicore
     11 from carbonui.util.dpi import ScaleDpi
     12 from carbonui.util.various_unsorted import GetWindowAbove
     13 from careergoals.client.signal import on_goal_completed
     14 from eve.client.script.ui import eveColor
     15 from eve.client.script.ui.shared.careerPortal import careerConst, cpSignals
     16 from eve.client.script.ui.shared.careerPortal.circleView.innerCircles import InnerCircles
     17 from eveexceptions import EatsExceptions
     18 from eveui import Sprite
     19 MAX_CIRCLE_WIDTH = 800
     20 GLOW_WIDTH = 220
     21 
     22 class CircleViewContainer(Container):
     23     default_opacity = 0
     24     default_height = 800
     25     default_width = 800
     26     default_align = uiconst.CENTER
     27 
     28     def __init__(self, initialState, *args, **kwargs):
     29         super(CircleViewContainer, self).__init__(*args, **kwargs)
     30         self.initialState = initialState
     31         self.nodesByID = {}
     32         self.currentState = None
     33         self.PrepareUI()
     34         self.ConnectToSignals()
     35         self.OnCareerWindowStateChanged(initialState)
     36 
     37     def PrepareUI(self):
     38         wnd = GetWindowAbove(self)
     39         w, _ = wnd.GetAbsoluteSize()
     40         self.width = self.height = min(MAX_CIRCLE_WIDTH, w / 2)
     41         self.circleView = self.CreateCircleView(width=self.width, height=self.height)
     42 
     43     def CreateCircleView(self, *args, **kwargs):
     44         raise NotImplementedError
     45 
     46     def Close(self):
     47         self.DisconnectFromSignals()
     48         super(CircleViewContainer, self).Close()
     49 
     50     def GetSignals(self):
     51         return [(careerConst.CAREER_WINDOW_STATE_SETTING.on_change, self.OnCareerWindowStateChanged), (cpSignals.on_cp_window_size_changed, self.on_parent_window_end_resize)]
     52 
     53     def on_parent_window_end_resize(self, wnd):
     54         w, _ = wnd.GetAbsoluteSize()
     55         self.circleView.width = self.circleView.height = min(MAX_CIRCLE_WIDTH, w / 2)
     56         self.width = self.height = min(MAX_CIRCLE_WIDTH, w / 2)
     57         self.circleView.UpdateCircle()
     58 
     59     def OnCareerWindowStateChanged(self, newState, animate = True):
     60         raise NotImplementedError
     61 
     62     @EatsExceptions('CircleView::ConnectToSignals')
     63     def ConnectToSignals(self):
     64         for signal, callback in self.GetSignals():
     65             signal.connect(callback)
     66 
     67     @EatsExceptions('CircleView::DisconnectFromSignals')
     68     def DisconnectFromSignals(self):
     69         for signal, callback in self.GetSignals():
     70             signal.disconnect(callback)
     71 
     72 
     73 class CircleView(Transform):
     74     default_height = 800
     75     default_width = 800
     76     default_align = uiconst.CENTER
     77     default_arc_opacity = 0.8
     78     default_scalingCenter = (0.5, 0.5)
     79     innerCircleTexturePath = 'res:/UI/Texture/classes/careerPortal/innerCircles.png'
     80 
     81     def ApplyAttributes(self, attributes):
     82         super(CircleView, self).ApplyAttributes(attributes)
     83         self.nodes = []
     84         self._initialized = False
     85         self.innerCircles = None
     86         self.outerCircle = None
     87         self.nodeParent = Container(name='nodeParent', parent=self, align=uiconst.TOALL)
     88         self.ConstructInnerCircles()
     89         self.fill = Sprite(name='fill', parent=self, align=uiconst.CENTER, texturePath='res:/UI/Texture/classes/careerPortal/circle_glow.png', state=uiconst.UI_DISABLED, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, opacity=0.5)
     90         on_goal_completed.connect(self.OnGoalCompleted)
     91 
     92     def Close(self):
     93         on_goal_completed.disconnect(self.OnGoalCompleted)
     94         super(CircleView, self).Close()
     95 
     96     def OnGoalCompleted(self, *args):
     97         if not self.nodes:
     98             return
     99         self.UpdateViewColor()
    100 
    101     def ConstructOuterCircle(self, radius):
    102         prevOpacity = 1
    103         if self.outerCircle is not None:
    104             prevOpacity = self.outerCircle.opacity
    105             self.outerCircle.Close()
    106         angle, dashSizeFactor, nodeCount = self.GetOuterCircleVariables(radius)
    107         self.outerCircle = DashedCircle(name='OuterCircle', parent=self, align=uiconst.CENTER, range=math.radians(360), lineWidth=ScaleDpi(2), radius=radius, glowBrightness=0.5, startAngle=angle, dashCount=nodeCount, dashSizeFactor=dashSizeFactor, opacity=prevOpacity)
    108 
    109     def GetOuterCircleVariables(self, radius):
    110         nodeCount = self._GetNodesCount()
    111         nodeSize = self.GetNodeSize()
    112         angle = self._GetAngleOffset() + 0 / float(nodeCount) * 2 * math.pi
    113         dashSizeFactor = (math.pi * (2 * radius) - nodeCount * nodeSize) / (nodeCount * nodeSize)
    114         return (angle, dashSizeFactor, nodeCount)
    115 
    116     def ConstructInnerCircles(self):
    117         if self.innerCircles is not None:
    118             self.innerCircles.Close()
    119         self.innerCircles = InnerCircles(parent=self, align=uiconst.CENTER, texturePath=self.innerCircleTexturePath, spriteEffect=trinity.TR2_SFX_MODULATE, state=uiconst.UI_DISABLED)
    120 
    121     def _GetViewColor(self):
    122         if any((not node.IsCompleted() for node in self.nodes)):
    123             return eveColor.WHITE
    124         else:
    125             return eveColor.LEAFY_GREEN
    126 
    127     def Reset(self):
    128         self.nodes = []
    129         self.nodeParent.Flush()
    130 
    131     def AddNode(self, node):
    132         self.nodes.append(node)
    133         node.SetParent(self.nodeParent)
    134 
    135     @telemetry.ZONE_METHOD
    136     def UpdateCircle(self):
    137         if not self.nodes:
    138             return
    139         size = self.width
    140         nodeSize = self.GetNodeSize()
    141         diameter = size - nodeSize
    142         radius = diameter * 0.5
    143         self.ConstructOuterCircle(radius)
    144         self.UpdateCircleMask()
    145         self.innerCircles.pos = (0,
    146          0,
    147          diameter - 10,
    148          diameter - 10)
    149         fillSize = diameter * 1.33
    150         self.fill.SetSize(fillSize, fillSize)
    151         self.UpdateViewColor()
    152         self.AdjustNodes(size, radius)
    153 
    154     def UpdateViewColor(self):
    155         viewColor = eveColor.Color(self._GetViewColor())
    156         self.fill.color = viewColor.SetOpacity(self.fill.opacity).GetRGBA()
    157         self.outerCircle.color = viewColor.SetOpacity(self.outerCircle.opacity).GetRGBA()
    158 
    159     def UpdateCircleMask(self):
    160         maskTexturePath = self._GetNodeMask()
    161         self.innerCircles.SetSecondaryTexturePath(maskTexturePath)
    162         self.innerCircles.scaleSecondary = self._GetInnerCircleScale()
    163 
    164     def _GetNodeMask(self):
    165         return 'res:/UI/Texture/classes/careerPortal/nodeMasks/%s_node_mask.png' % len(self.nodes)
    166 
    167     def _GetInnerCircleScale(self):
    168         if uicore.dpiScaling > 1.25:
    169             return (0.94, 0.94)
    170         return (0.91, 0.91)
    171 
    172     @staticmethod
    173     def _GetFillScale():
    174         scale = 900 / 730.0
    175         return (scale, scale)
    176 
    177     def OnAdjustSizeDone(self, radius):
    178         self.radius = radius
    179 
    180     @telemetry.ZONE_METHOD
    181     def AdjustNodes(self, size, radius):
    182         for i, nodeCont in enumerate(self.nodes):
    183             self.AdjustNode(nodeCont, i, size, radius)
    184 
    185     def AdjustNode(self, node, idx, size, radius, animate = False):
    186         nodeSize = self.GetNodeSize()
    187         left, top, angle = self._GetNodeContPositionFromSizeAndRadius(nodeSize, idx, radius)
    188         node.ResizeComponents(nodeSize, left, top, angle, animate)
    189 
    190     def _GetNodesCount(self):
    191         return len(self.nodes)
    192 
    193     def _GetNodeAngleMeasure(self, radius):
    194         if radius <= 0:
    195             return 0
    196         else:
    197             adjustment_radius = 0.5 * self.GetNodeSize() / radius
    198             try:
    199                 node_angle_measure = 2.0 * math.asin(adjustment_radius)
    200             except ValueError:
    201                 return 0
    202 
    203             return node_angle_measure
    204 
    205     def _GetArcAngleMeasure(self, nodeAngleMeasure):
    206         count = float(self._GetNodesCount())
    207         if count > 0:
    208             return (2 * math.pi - count * nodeAngleMeasure) / count
    209         return 2 * math.pi
    210 
    211     def _GetNodeContPositionFromSizeAndRadius(self, nodeSize, i, radius):
    212         angle = self._GetAngleOffset() + i / float(self._GetNodesCount()) * 2 * math.pi
    213         left = radius * math.cos(angle) + int(nodeSize / 2 - nodeSize / 2)
    214         top = radius * math.sin(angle) + int(nodeSize / 2 - nodeSize / 2)
    215         return (left, top, angle)
    216 
    217     def _GetAngleOffset(self):
    218         return -math.pi / 2
    219 
    220     def GetNodeSize(self):
    221         raise NotImplementedError
    222 
    223     def SetArcOpacity(self, opacity, duration, animate = True):
    224         if animate:
    225             animations.FadeTo(self.outerCircle, self.outerCircle.opacity, opacity, duration=duration)
    226         else:
    227             self.outerCircle.opacity = opacity