message.py (12453B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\message.py 2 import collections 3 import blue 4 import localization 5 import logging 6 import uthread 7 from carbonui import uiconst 8 from carbonui.control.message import MessageData, MessageParentClass 9 from carbonui.primitives.container import Container 10 from carbonui.primitives.containerAutoSize import ContainerAutoSize 11 from carbonui.primitives.frame import Frame 12 from carbonui.primitives.sprite import Sprite 13 from carbonui.uicore import uicore 14 from eve.client.script.ui.control.eveLabel import Label 15 from eve.client.script.util.settings import IsShipHudTopAligned 16 from eve.common.lib import appConst as const 17 log = logging.getLogger(__name__) 18 19 class CombatMessage(MessageParentClass): 20 21 def ApplyAttributes(self, attributes): 22 self.noDamageMsgTimer = 10 * const.SEC 23 self.expiryTime = 5 * const.SEC 24 numMessagePerSec = 6 25 self.messageSleepTime = 1000 / numMessagePerSec 26 self.messageSleepTimeInMs = self.messageSleepTime / 1000.0 27 self.fadeOutTime = 5.0 28 self.moveUpTime = 0.8 29 self.messageList = [] 30 self.showingMessage = False 31 self.configName = 'damageMessages_config' 32 self.settingNameAlign = 'dmgnotifictions_alignment' 33 self.defaultConfig = self.GetDefaultAlignmentValues() 34 MessageParentClass.ApplyAttributes(self, attributes) 35 self.myLayer = uicore.layer.target 36 self.minTop = -40 37 self.scope = uiconst.SCOPE_INGAME 38 self.state = uiconst.UI_DISABLED 39 self.allContainers = [] 40 self.allLabels = [] 41 self.noDamageDict = {} 42 self.messageCounter = collections.deque([], maxlen=8 * numMessagePerSec) 43 uthread.new(self.ShowMsg) 44 45 def GetLayerOffset(self): 46 return uicore.layer.target.absoluteLeft 47 48 def GetDefaultAlignmentValues(self, *args): 49 offset = sm.GetService('window').GetCameraLeftOffset(300, align=uiconst.CENTERTOP, left=0) 50 if IsShipHudTopAligned(): 51 top = uicore.desktop.height * 0.7 52 else: 53 top = max(uicore.desktop.height * 0.32, 225) 54 defaultConfig = (uiconst.CENTERTOP, 55 uiconst.CENTERBOTTOM, 56 offset, 57 top) 58 return defaultConfig 59 60 def Prepare_Text_(self): 61 uiAlignment = self.GetUIAlignment(self.currentTextAlignment) 62 notificationFontSize = settings.user.ui.Get('dmgnotifictions_fontsize', 12) 63 for i in xrange(6): 64 container = ContainerAutoSize(parent=self, name='C%s' % i, left=6, top=5, align=uiAlignment, state=uiconst.UI_DISABLED) 65 numberContainer = ContainerAutoSize(parent=container, width=0, height=0, align=uiconst.TOLEFT) 66 container.numberLabel = Label(text='', name='N%s' % i, parent=numberContainer, align=uiAlignment, state=uiconst.UI_DISABLED, fontsize=notificationFontSize) 67 iconContainer = Container(parent=container, width=0, height=0, align=uiconst.TOLEFT) 68 container.iconContainer = iconContainer 69 name = 'L%s' % i 70 labelContainer = ContainerAutoSize(parent=container, width=0, height=0, align=uiconst.TOLEFT) 71 message = Label(text='', name=name, parent=labelContainer, align=uiAlignment, state=uiconst.UI_DISABLED, fontsize=notificationFontSize) 72 container.msgIndex = i 73 container.label = message 74 container.display = False 75 setattr(self, 'message%s' % i, message) 76 self.allLabels.append(message) 77 self.allContainers.append(container) 78 79 def ShowMsg(self, *args): 80 if self.showingMessage: 81 return 82 while 1: 83 if not self or self.destroyed: 84 return 85 try: 86 if len(self.messageList) == 0: 87 self.messageCounter.append(0) 88 continue 89 self.messageCounter.append(1) 90 now = blue.os.GetWallclockTime() 91 validTime = now - self.expiryTime 92 message = None 93 numMessagesDiscarded = 0 94 while len(self.messageList) > 0: 95 message = self.messageList.pop(0) 96 if message.time_stamp < validTime: 97 numMessagesDiscarded += 1 98 continue 99 break 100 101 if numMessagesDiscarded: 102 sm.GetService('logger').LogWarn('CombatMessage::ShowMsg - Discarded %s combat UI messages' % numMessagesDiscarded) 103 if not message or not message.text: 104 continue 105 if len(self.allContainers) < 1: 106 self.Prepare_Text_() 107 fakeText = self.GetFakeText() 108 if fakeText: 109 fakeText.Close() 110 container, otherVisibleContainers = self.FindFreeContainer() 111 self.apply_message_to_container(container, message) 112 self.SetSizeAndPosition() 113 otherVisibleContainers.sort(lambda x, y: cmp(x.top, y.top)) 114 if sum(self.messageCounter) > 8: 115 duration = 0.166 116 secondPoint = 0.05 117 else: 118 secondPoint = 0.2 119 duration = 0.4 120 for i, ovc in enumerate(otherVisibleContainers): 121 uicore.animations.MorphScalar(ovc, 'top', startVal=ovc.top, endVal=(i + 1) * 20, duration=duration) 122 ovc.msgIndex = i 123 if i == 4: 124 uicore.animations.FadeOut(ovc, duration=self.messageSleepTimeInMs) 125 126 curvePoints = ([0, 0], [secondPoint, 1.0], [1, 0]) 127 uicore.animations.MorphScalar(container, 'opacity', duration=self.fadeOutTime, curveType=curvePoints) 128 self.SetOrder(0) 129 except Exception as e: 130 log.exception(e) 131 finally: 132 blue.pyos.synchro.SleepWallclock(self.messageSleepTime) 133 134 def apply_message_to_container(self, container, message): 135 if message.icons: 136 container.label.text = ' ' + message.text 137 else: 138 container.label.text = message.text 139 container.iconContainer.Flush() 140 container.iconContainer.width = container.label.height * len(message.icons) 141 container.width = container.label.width + container.iconContainer.width 142 container.height = container.label.height 143 container.top = 0 144 container.msgIndex = -1 145 if message.damage_html is not None: 146 container.numberLabel.text = message.damage_html + ' ' 147 container.numberLabel.Show() 148 else: 149 container.numberLabel.Hide() 150 container.display = True 151 for iconResPath in message.icons: 152 Sprite(parent=container.iconContainer, width=container.label.height, height=container.label.height, texturePath=iconResPath, align=uiconst.TORIGHT, color=message.icon_color) 153 154 def AddActionMessage(self, text, icons = None, icon_color = None): 155 now = blue.os.GetWallclockTime() 156 if icons is None: 157 icons = [] 158 self.messageList.append(MessageData(now, text, icons, icon_color=icon_color)) 159 160 def AddMessage(self, text, hitQuality, attackerID, images, damage_html, icon_color = None, *args): 161 now = blue.os.GetWallclockTime() 162 if hitQuality == 0 and attackerID: 163 if attackerID in self.noDamageDict: 164 lastNoDmgMsgTime = self.noDamageDict[attackerID] 165 if lastNoDmgMsgTime > now - self.noDamageMsgTimer: 166 return 167 self.noDamageDict[attackerID] = now 168 damage_html = None 169 else: 170 self.noDamageDict.pop(attackerID, None) 171 self.messageList.append(MessageData(now, text, icons=images, damage_html=damage_html, icon_color=icon_color)) 172 173 def FindFreeContainer(self, *args): 174 myContainer = None 175 self.allContainers.sort(lambda x, y: cmp(x.msgIndex, y.msgIndex), reverse=True) 176 myContainer = self.allContainers[0] 177 myContainer.StopAnimations() 178 otherVisibleContainers = [] 179 for container in self.allContainers: 180 if container == myContainer: 181 continue 182 if container.display and self.IsStillFadingOut(container): 183 otherVisibleContainers.append(container) 184 else: 185 container.display = False 186 container.msgIndex = len(self.allContainers) 187 188 return (myContainer, otherVisibleContainers) 189 190 def IsStillFadingOut(self, label): 191 curveSet = uicore.animations.GetAnimationCurveSet(label, 'opacity') 192 return bool(curveSet) 193 194 def SetSizeAndPosition(self, *args): 195 boxHeight = 0 196 widths = [] 197 for container in self.allContainers: 198 if container.display: 199 boxHeight += container.label.textheight 200 widths.append(container.label.textwidth) 201 202 fakeText = self.GetFakeText() 203 if not widths and fakeText: 204 widths = [fakeText.textwidth] 205 else: 206 widths.append(100) 207 self.width = max(widths) + 30 208 if boxHeight == 0 and fakeText: 209 self.height = fakeText.textheight 210 else: 211 self.height = boxHeight 212 self.height += 10 213 self.top = max(self.minTop, min(uicore.desktop.height - self.height, self.topOffset - self.height)) 214 215 def SaveSettings(self, *args): 216 settings.char.ui.Set('damageMessages_config', (self.align, 217 self.currentTextAlignment, 218 self.left, 219 self.topOffset)) 220 221 def SetTextAlignmentIfNeeded(self, alignment, *args): 222 alignmentMode = settings.user.ui.Get(self.settingNameAlign, 'auto') 223 if alignmentMode != 'auto' and alignmentMode in ('center', 'right', 'left'): 224 alignment = alignmentMode 225 if self.currentTextAlignment != alignment: 226 uiAlignment = self.GetUIAlignment(alignment) 227 for container in self.allContainers: 228 container.SetAlign(uiAlignment) 229 230 fakeText = self.GetFakeText() 231 if fakeText: 232 fakeText.text = '<%s>%s' % (alignment, self.fakeText.cleanText) 233 self.currentTextAlignment = alignment 234 235 def GetUIAlignment(self, alignment): 236 if alignment == 'left': 237 uiAlignment = uiconst.BOTTOMLEFT 238 elif alignment == 'right': 239 uiAlignment = uiconst.BOTTOMRIGHT 240 else: 241 uiAlignment = uiconst.CENTERBOTTOM 242 return uiAlignment 243 244 def ExitDragMode(self, *args): 245 if getattr(self, 'border', None) is not None: 246 self.border.Close() 247 MessageParentClass.ExitDragMode(self, *args) 248 self.state = uiconst.UI_DISABLED 249 self.SetParent(uicore.layer.target) 250 251 def EnterDragMode(self, *args): 252 for container in self.allContainers: 253 if container.display and container.opacity > 0.05: 254 break 255 else: 256 uiAlignment = self.GetUIAlignment(self.currentTextAlignment) 257 self.fakeText = Label(text='', name='faketext', parent=self, left=6, top=5, align=uiAlignment, state=uiconst.UI_DISABLED, fontsize=12, width=380) 258 text = localization.GetByLabel('UI/Accessories/Log/ExampleText') 259 self.fakeText.text = '<%s>%s' % (self.currentTextAlignment, text) 260 self.fakeText.cleanText = text 261 self.height = self.fakeText.textheight + 20 262 self.width = 400 263 264 self.border = Frame(parent=self, frameConst=uiconst.FRAME_BORDER1_CORNER5, state=uiconst.UI_DISABLED, color=(1.0, 1.0, 1.0, 0.25), top=-5) 265 MessageParentClass.EnterDragMode(self, *args) 266 self.dragFill.top = -5 267 self.exitMoveModeBtn.top = -5 268 self.SetParent(uicore.layer.abovemain) 269 270 def ResetAlignment(self, *args): 271 MessageParentClass.ResetAlignment(self, *args) 272 self.ChangeAlignment() 273 274 def ChangeFontSize(self, *args): 275 fontsize = settings.user.ui.Get('dmgnotifictions_fontsize', 12) 276 if len(self.allLabels) < 1: 277 return 278 for label in self.allLabels: 279 label.fontsize = fontsize 280 281 def ChangeAlignment(self, *args): 282 self.DoAlignment() 283 284 def OnSessionChanged(self, isRemote, sess, change): 285 self.noDamageDict = {}