shipTreeContainer.py (14091B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\shipTree\shipTreeContainer.py 2 import evetypes 3 import geo2 4 import inventorycommon.typeHelpers 5 import trinity 6 from carbonui import uiconst 7 from carbonui.primitives.container import Container 8 from carbonui.primitives.containerAutoSize import ContainerAutoSize 9 from carbonui.primitives.sprite import Sprite 10 from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal 11 from carbonui.primitives.vectorlinetrace import VectorLineTrace 12 from carbonui.uicore import uicore 13 from characterdata.factions import get_faction_name 14 from eve.client.script.ui.shared.cloneGrade import ORIGIN_SHIPTREE 15 from eve.client.script.ui.shared.cloneGrade.omegaCloneIcon import OmegaCloneIcon 16 from eve.client.script.ui.shared.shipTree.shipTreeShipGroup import ShipTreeShipGroup 17 from eve.client.script.ui.shared.shipTree import shipTreeConst 18 from eve.client.script.ui.shared.shipTree.shipTreeConst import TREE_SCALE, NODETYPE_GROUP, NODETYPE_OTHERFACTIONGROUP, COLOR_BG, NODETYPE_ROOT, BG_BY_FACTIONID, COLOR_MASTERED 19 from carbonui.control.buttonIcon import ButtonIcon 20 from eve.client.script.ui.control.eveLabel import Label 21 from eve.common.script.net.eveMachoNetVersion import machoVersion 22 from eve.common.lib import appConst as const 23 from inventorycommon.const import typeCapsule 24 from localization import GetByMessageID, GetByLabel 25 from omega.client.clone_grade_svc import get_clone_grade_svc 26 X_OFFSET = 22 27 Y_OFFSET = 40 28 COLOR_FONT = (0.667, 29 0.796, 30 0.906, 31 1.0) 32 COLOR_LINE_TO = (1.0, 33 1.0, 34 1.0, 35 1.0) 36 COLOR_LINE_OMEGA = (1.0, 37 0.8, 38 0.0, 39 1.0) 40 41 class ShipTreeContainer(ContainerAutoSize): 42 default_name = 'ShipTreeContainer' 43 44 def ApplyAttributes(self, attributes): 45 ContainerAutoSize.ApplyAttributes(self, attributes) 46 self.factionID = attributes.factionID 47 self._offset = None 48 self._leftFloat = 0.0 49 self._topFloat = 0.0 50 self.rootNode = None 51 self.shipGroups = {} 52 self.lineCont = Container(name='lineCont', parent=self) 53 self.ConstructTree() 54 self.bgCont = Container(name='bgContainer', align=uiconst.CENTER, state=uiconst.UI_DISABLED, parent=self, padding=-100) 55 self.topFrame = TopFrame(parent=self.bgCont, align=uiconst.TOTOP) 56 self.bottomFrame = BottomFrame(parent=self.bgCont, align=uiconst.TOBOTTOM) 57 Sprite(name='grid', bgParent=self.bgCont, state=uiconst.UI_DISABLED, align=uiconst.CENTER, texturePath='res:/UI/Texture/Classes/ShipTree/grid.png', color=(0.43, 0.727, 1.0, 0.2), idx=0, tileX=True, tileY=True) 58 texturePath = BG_BY_FACTIONID.get(self.factionID) 59 w, h = self.rootNode.GetDimensions() 60 h = max(w, h) / 2 61 height = 3.2 * h * TREE_SCALE 62 width = 1.6 / 1.8 * height 63 self.factionBG = Sprite(name='factionBG', parent=self.bgCont, align=uiconst.CENTER, texturePath=texturePath, width=width, height=height, opacity=0.18, idx=0) 64 65 def ConstructTree(self): 66 self.rootNode = sm.GetService('shipTree').GetRootNode(self.factionID) 67 self._offset, _ = self.rootNode.GetBoundingBox() 68 self.ConstructNodes() 69 self.ConstructLines() 70 71 def ConstructNodes(self): 72 self.shipGroups = {} 73 self._ConstructNodes(self.rootNode) 74 75 def _ConstructNodes(self, node, i = 0, line = None): 76 nodeType = node.GetNodeType() 77 if nodeType == NODETYPE_GROUP: 78 self.RenderShipGroup(node, i) 79 elif nodeType == NODETYPE_OTHERFACTIONGROUP: 80 self.RenderNodeOtherFactionGroup(node) 81 elif nodeType == NODETYPE_ROOT: 82 self.RenderRootNode(node) 83 for childNode in node.children: 84 self._ConstructNodes(childNode, i + 1, line) 85 86 def ConstructLines(self, animate = True): 87 self.lineCont.Flush() 88 self._ConstructLines(self.rootNode, animate=animate) 89 90 def _ConstructLines(self, node, i = 0, line = None, animate = True): 91 if node.nodeType == NODETYPE_GROUP: 92 line = None 93 for childNode in node.children: 94 line = self.RenderLine(node, childNode, i, line, animate=animate) 95 self._ConstructLines(childNode, i + 1, line, animate) 96 line = None 97 98 def GetGroupNodeByID(self, shipGroupID): 99 return self.rootNode.GetChildByID(shipGroupID) 100 101 def GetGroupByID(self, shipGroupID): 102 if not self.shipGroups: 103 return None 104 return self.shipGroups[shipGroupID] 105 106 def RenderShipGroup(self, node, i): 107 if node.parent and node.parent.nodeType == NODETYPE_OTHERFACTIONGROUP: 108 return 109 x, y = self._GetNodePosition(node) 110 group = ShipTreeShipGroup(parent=self, node=node, alignMode=uiconst.TOPLEFT, left=x, top=y, idx=0, nodeNum=i) 111 self.shipGroups[node.shipGroupID] = group 112 113 def RenderNodeOtherFactionGroup(self, node): 114 left, top = self._GetNodePosition(node) 115 opacity = 0.2 if node.IsLocked() else 1.0 116 texturePath = shipTreeConst.ICON_BY_FACTIONID.get(node.factionID) 117 size = 64 118 shipGroupData = cfg.infoBubbleGroups[node.shipGroupID] 119 shipGroupName = GetByMessageID(shipGroupData['nameID']) 120 ButtonIcon(parent=self, texturePath=texturePath, pos=(left - size / 2 + X_OFFSET, 121 top - size / 2 + Y_OFFSET, 122 size, 123 size), iconSize=65, idx=0, func=self.OnOtherFactionClicked, args=(node,), opacity=opacity, hint='<b>%s</b>\n%s' % (get_faction_name(node.factionID), shipGroupName)) 124 125 def RenderOmegaIcon(self, node): 126 left, top = self.GetOmegaIconPosition(node, node.GetParent()) 127 if self.IsOmega(): 128 tooltipText = GetByLabel('UI/CloneState/ShipTreeTooltipOmega') 129 size = 32 130 opacity = 0.5 131 else: 132 tooltipText = GetByLabel('UI/CloneState/ShipTreeTooltipAlpha') 133 size = 64 134 opacity = 1.0 135 OmegaCloneIcon(parent=self.lineCont, pos=(left - size / 2, 136 top - size / 2, 137 size, 138 size), idx=0, tooltipText=tooltipText, opacity=opacity, origin=ORIGIN_SHIPTREE) 139 140 def GetOmegaIconPosition(self, node, parent): 141 parentPosition = self._GetNodePosition(parent) 142 childPosition = self._GetNodePosition(node) 143 if childPosition[1] == parentPosition[1]: 144 try: 145 offset = parent.GetGroupWidth() 146 s = offset / geo2.Vec2Length(geo2.Vec2Subtract(childPosition, parentPosition)) 147 parentPosition = geo2.Vec2Lerp(parentPosition, childPosition, s) 148 except AttributeError: 149 pass 150 151 position = geo2.Vec2Lerp(parentPosition, childPosition, 0.5) 152 position = geo2.Vec2Add(position, (X_OFFSET, Y_OFFSET)) 153 return position 154 155 def RenderRootNode(self, node): 156 texturePath = inventorycommon.typeHelpers.GetHoloIconPath(typeCapsule) 157 size = 32 158 left, top = self._GetNodePosition(node) 159 if self.IsInGoldenPod(): 160 color = COLOR_MASTERED 161 typeID = const.typeCapsuleGolden 162 else: 163 color = (1, 1, 1, 1) 164 typeID = const.typeCapsule 165 btn = RootNode(parent=self, pos=(left - size / 2 + X_OFFSET - 6, 166 top - size / 2 - 2 + Y_OFFSET, 167 size, 168 size), func=sm.GetService('info').ShowInfo, iconSize=size, args=(typeID,), texturePath=texturePath, hint=evetypes.GetName(typeID), iconColor=color) 169 btn.icon.blendMode = trinity.TR2_SBM_ADD 170 171 def RenderLine(self, nodeFrom, nodeTo, i, line, animate = True): 172 if nodeTo.nodeType == NODETYPE_OTHERFACTIONGROUP: 173 return None 174 if nodeTo.IsRestricted() and not self.IsOmega(): 175 colorTo = COLOR_LINE_OMEGA 176 else: 177 colorTo = COLOR_LINE_TO 178 lineTexturePath = self.GetLineTexturePath(nodeTo) 179 if not line or line.texturePath != lineTexturePath: 180 line = VectorLineTraceShipTree(parent=self.lineCont, nodeFrom=nodeFrom, nodeTo=nodeTo, texturePath=lineTexturePath) 181 pos = self.GetNewLineStartPos(nodeFrom, nodeTo) 182 if i == 0 or nodeFrom.nodeType == NODETYPE_OTHERFACTIONGROUP: 183 colorFrom = (1.0, 1.0, 1.0, -0.05) 184 elif nodeFrom.IsRestricted() and not self.IsOmega(): 185 colorFrom = COLOR_LINE_OMEGA 186 else: 187 colorFrom = COLOR_LINE_TO 188 line.AddPoint(pos, colorFrom) 189 posTo = self._GetLinePosition(nodeTo) 190 line.AddPoint(posTo, colorTo) 191 opacity = 0.7 if nodeTo.IsLocked() else 1.0 192 if animate: 193 uicore.animations.FadeIn(line, opacity, timeOffset=0.05 * i + 0.2, duration=0.3) 194 else: 195 line.opacity = opacity 196 if nodeTo.IsRestricted() and not nodeFrom.IsRestricted() and not nodeFrom.nodeType == NODETYPE_OTHERFACTIONGROUP: 197 self.RenderOmegaIcon(nodeTo) 198 return line 199 200 def IsInGoldenPod(self): 201 implants = sm.GetService('godma').GetItem(session.charid).implants 202 if implants is None: 203 return False 204 for implant in implants: 205 if implant.typeID == const.typeGoldenCapsuleImplant: 206 return True 207 208 return False 209 210 def IsOmega(self): 211 return get_clone_grade_svc().is_omega_with_grace_period() 212 213 def GetLineTexturePath(self, nodeTo): 214 if nodeTo.IsPathToElite(): 215 return 'res:/UI/Texture/classes/shipTree/lines/elite.png' 216 if nodeTo.IsLocked(): 217 return 'res:/UI/Texture/classes/shipTree/lines/locked.png' 218 return 'res:/UI/Texture/classes/shipTree/lines/unlocked.png' 219 220 def GetNewLineStartPos(self, node, childNode): 221 pos = self._GetLinePosition(node) 222 childPos = self._GetLinePosition(childNode) 223 if node.nodeType == NODETYPE_GROUP: 224 if childPos[1] == pos[1]: 225 offset = node.GetGroupWidth() + 24 226 s = offset / geo2.Vec2Length(geo2.Vec2Subtract(childPos, pos)) 227 pos = geo2.Vec2Lerp(pos, childPos, s) 228 return (int(pos[0]), int(pos[1])) 229 230 def _GetNodePosition(self, node): 231 vec = geo2.Vec2Subtract(node.GetPosition(), self._offset) 232 return geo2.Vec2Scale(vec, TREE_SCALE) 233 234 def _GetLinePosition(self, node): 235 vec = self._GetNodePosition(node) 236 vec = geo2.Vec2Add(vec, (X_OFFSET, Y_OFFSET)) 237 return (int(vec[0]), int(vec[1])) 238 239 def GetLeftFloat(self): 240 return self._leftFloat 241 242 def SetLeftFloat(self, value): 243 self._leftFloat = value 244 self.left = value 245 246 leftFloat = property(GetLeftFloat, SetLeftFloat) 247 248 def GetTopFloat(self): 249 return self._topFloat 250 251 def SetTopFloat(self, value): 252 self._topFloat = value 253 self.top = value 254 255 topFloat = property(GetTopFloat, SetTopFloat) 256 257 def OnOtherFactionClicked(self, node): 258 sm.GetService('shipTreeUI').OpenAndShowShipGroup(node.factionID, node.shipGroupID) 259 260 def UpdateTreeSkills(self): 261 self.rootNode.FlushCache() 262 self.ConstructLines(animate=False) 263 264 265 class RootNode(ButtonIcon): 266 isDragObject = True 267 268 def GetDragData(self): 269 import eveui 270 return [eveui.dragdata.ItemType(type_id=typeCapsule)] 271 272 def OnEndDrag(self, *args): 273 ButtonIcon.OnEndDrag(self, *args) 274 self.OnMouseExit() 275 276 277 class VectorLineTraceShipTree(VectorLineTrace): 278 default_spriteEffect = trinity.TR2_SFX_COPY 279 default_lineWidth = 10.0 280 default_textureWidth = 10.0 281 default_opacity = 0.0 282 default_idx = -1 283 default_state = uiconst.UI_DISABLED 284 285 286 class TopFrame(Container): 287 default_name = 'topFrame' 288 default_height = 26 289 290 def ApplyAttributes(self, attributes): 291 Container.ApplyAttributes(self, attributes) 292 Sprite(parent=self, align=uiconst.TOLEFT, width=126, texturePath='res:/UI/Texture/classes/shipTree/frame/topLeft.png') 293 cont = ContainerAutoSize(parent=self, align=uiconst.TOLEFT, alignMode=uiconst.TOPLEFT, bgTexturePath='res:/UI/Texture/classes/shipTree/frame/topMiddle.png') 294 Label(parent=cont, text=GetByLabel('UI/ShipTree/InterbusShipIdentificationSystem'), color=COLOR_BG, top=3, fontsize=12, uppercase=True, bold=True, padRight=4) 295 StretchSpriteHorizontal(parent=Container(parent=self), align=uiconst.TOTOP, texturePath='res:/UI/Texture/classes/ShipTree/frame/topRight.png', leftEdgeSize=40, rightEdgeSize=5, height=26) 296 297 298 class BottomFrame(Container): 299 default_name = 'bottomFrame' 300 default_height = 59 301 302 def ApplyAttributes(self, attributes): 303 Container.ApplyAttributes(self, attributes) 304 Sprite(parent=self, align=uiconst.TOLEFT, width=259, texturePath='res:/UI/Texture/classes/shipTree/frame/bottomLeft.png') 305 cont = ContainerAutoSize(parent=self, align=uiconst.TOLEFT, padLeft=4) 306 Label(parent=cont, align=uiconst.TOPLEFT, text=GetByLabel('UI/ShipTree/Showing'), uppercase=True, top=38, fontsize=9, color=COLOR_FONT) 307 Label(parent=self, text='V1.%s.%s' % (len(evetypes.GetTypeIDsByCategory(const.categoryShip)), machoVersion), uppercase=True, top=43, left=82, fontsize=10, color=COLOR_FONT) 308 Label(parent=cont, align=uiconst.TOPLEFT, text=GetByLabel('UI/ShipTree/MilitaryAndIndustrialVessels'), uppercase=True, top=49, fontsize=9, color=COLOR_FONT) 309 self.AddSeperator(uiconst.TOLEFT) 310 self.AddSeperator(uiconst.TORIGHT) 311 Label(parent=ContainerAutoSize(align=uiconst.TORIGHT, parent=self, padLeft=4), align=uiconst.TOPLEFT, text=GetByLabel('UI/ShipTree/CourtesyLabel'), uppercase=True, top=49, fontsize=9, color=COLOR_FONT) 312 self.AddSeperator(uiconst.TORIGHT) 313 StretchSpriteHorizontal(parent=Container(parent=self, padding=(4, 0, 4, 0)), align=uiconst.TOBOTTOM, texturePath='res:/UI/Texture/classes/ShipTree/frame/bottomLine.png', leftEdgeSize=20, rightEdgeSize=20, height=2) 314 315 def AddSeperator(self, align): 316 Sprite(parent=Container(align=align, parent=self, width=40, padLeft=4), texturePath='res:/UI/Texture/classes/shipTree/frame/bottomSeperator.png', align=uiconst.TOBOTTOM, height=8)