class FrameProfiler: notify = directNotify.newCategory('FrameProfiler') # because of precision requirements, all times related to the profile/log # schedule are stored as integers Minute = 60 Hour = 60 * Minute Day = 24 * Hour def __init__(self): Hour = FrameProfiler.Hour # how long to wait between frame profiles frequent_profiles = ConfigVariableBool('frequent-frame-profiles', False) self._period = 2 * FrameProfiler.Minute if frequent_profiles: self._period = 1 * FrameProfiler.Minute # used to prevent profile from being taken exactly every 'period' seconds self._jitterMagnitude = self._period * .75 # when to log output # each entry must be an integer multiple of all previous entries # as well as an integer multiple of the period self._logSchedule = [ 1 * FrameProfiler.Hour, 4 * FrameProfiler.Hour, 12 * FrameProfiler.Hour, 1 * FrameProfiler.Day, ] # day schedule proceeds as 1, 2, 4, 8 days, etc. if frequent_profiles: self._logSchedule = [ 1 * FrameProfiler.Minute, 4 * FrameProfiler.Minute, 12 * FrameProfiler.Minute, 24 * FrameProfiler.Minute, ] for t in self._logSchedule: #assert isInteger(t) # make sure the period is evenly divisible into each element of the log schedule assert (t % self._period) == 0 # make sure each element of the schedule is evenly divisible into each subsequent element for i in range(len(self._logSchedule)): e = self._logSchedule[i] for j in range(i, len(self._logSchedule)): assert (self._logSchedule[j] % e) == 0 #assert isInteger(self._period) self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileFramesSV()) self._enableFC.pushCurrentState() def destroy(self): self._enableFC.set(False) self._enableFC.destroy() def _setEnabled(self, enabled): if enabled: self.notify.info('frame profiler started') self._startTime = globalClock.getFrameTime() self._profileCounter = 0 self._jitter = None self._period2aggregateProfile = {} self._id2session = {} self._id2task = {} # don't profile process startup self._task = taskMgr.doMethodLater( self._period, self._scheduleNextProfileDoLater, 'FrameProfilerStart-%s' % serialNum()) else: self._task.remove() del self._task for session in self._period2aggregateProfile.values(): session.release() del self._period2aggregateProfile for task in self._id2task.values(): task.remove() del self._id2task for session in self._id2session.values(): session.release() del self._id2session self.notify.info('frame profiler stopped') def _scheduleNextProfileDoLater(self, task): self._scheduleNextProfile() return Task.done def _scheduleNextProfile(self): self._profileCounter += 1 self._timeElapsed = self._profileCounter * self._period #assert isInteger(self._timeElapsed) time = self._startTime + self._timeElapsed # vary the actual delay between profiles by a random amount to prevent interaction # with periodic events jitter = self._jitter if jitter is None: jitter = normalDistrib(-self._jitterMagnitude, self._jitterMagnitude) time += jitter else: time -= jitter jitter = None self._jitter = jitter sessionId = serialNum() session = taskMgr.getProfileSession('FrameProfile-%s' % sessionId) self._id2session[sessionId] = session taskMgr.profileFrames(num=1, session=session, callback=Functor(self._analyzeResults, sessionId)) # schedule the next profile delay = max(time - globalClock.getFrameTime(), 0.) self._task = taskMgr.doMethodLater(delay, self._scheduleNextProfileDoLater, 'FrameProfiler-%s' % serialNum()) def _analyzeResults(self, sessionId): # do the analysis in a task 1) to separate the processing from the profiled frame, # and 2) to get the processing to show up in a named task instead of in the taskMgr self._id2task[sessionId] = taskMgr.add( Functor(self._doAnalysis, sessionId), 'FrameProfilerAnalysis-%s' % sessionId) def _doAnalysis(self, sessionId, task): if hasattr(task, '_generator'): gen = task._generator else: gen = self._doAnalysisGen(sessionId) task._generator = gen result = next(gen) if result == Task.done: del task._generator return result def _doAnalysisGen(self, sessionId): # generator to limit max number of profile loggings per frame p2ap = self._period2aggregateProfile self._id2task.pop(sessionId) session = self._id2session.pop(sessionId) if session.profileSucceeded(): # always add this profile to the first aggregated profile period = self._logSchedule[0] if period not in self._period2aggregateProfile: p2ap[period] = session.getReference() else: p2ap[period].aggregate(session) else: self.notify.warning('frame profile did not succeed') session.release() session = None counter = 0 # log profiles when it's time, and aggregate them upwards into the # next-longer profile for pi in range(len(self._logSchedule)): period = self._logSchedule[pi] if (self._timeElapsed % period) == 0: if period in p2ap: # delay until the next frame if we've already processed N profiles this frame if counter >= 3: counter = 0 yield Task.cont self.notify.info( 'aggregate profile of sampled frames over last %s\n%s' % (formatTimeExact(period), p2ap[period].getResults())) counter += 1 # aggregate this profile into the next larger profile nextIndex = pi + 1 if nextIndex >= len(self._logSchedule): # if we're adding a new period to the end of the log period table, # set it to double the duration of the current longest period nextPeriod = period * 2 self._logSchedule.append(nextPeriod) else: nextPeriod = self._logSchedule[nextIndex] if nextPeriod not in p2ap: p2ap[nextPeriod] = p2ap[period].getReference() else: p2ap[nextPeriod].aggregate(p2ap[period]) # this profile is now represented in the next larger profile # throw it out p2ap[period].release() del p2ap[period] else: # current time is not divisible evenly into selected period, and all higher # periods are multiples of this one break yield Task.done
class TaskProfiler: # this does intermittent profiling of tasks running on the system # if a task has a spike in execution time, the profile of the spike is logged notify = directNotify.newCategory("TaskProfiler") def __init__(self): self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileTasksSV()) self._enableFC.pushCurrentState() # table of task name pattern to TaskTracker self._namePrefix2tracker = {} self._task = None def destroy(self): if taskMgr.getProfileTasks(): self._setEnabled(False) self._enableFC.destroy() for tracker in self._namePrefix2tracker.itervalues(): tracker.destroy() del self._namePrefix2tracker del self._task @staticmethod def GetDefaultSpikeThreshold(): return config.GetFloat('profile-task-spike-threshold', 5.) @staticmethod def SetSpikeThreshold(spikeThreshold): TaskTracker.SpikeThreshold = spikeThreshold @staticmethod def GetSpikeThreshold(): return TaskTracker.SpikeThreshold def logProfiles(self, name=None): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if (name and (name not in namePrefix.lower())): continue tracker.log() def flush(self, name): if name: name = name.lower() # flush stored task profiles for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if (name and (name not in namePrefix.lower())): continue tracker.flush() def _setEnabled(self, enabled): if enabled: self.notify.info('task profiler started') self._taskName = 'profile-tasks-%s' % id(self) taskMgr.add(self._doProfileTasks, self._taskName, priority=-200) else: taskMgr.remove(self._taskName) del self._taskName self.notify.info('task profiler stopped') def _doProfileTasks(self, task=None): # gather data from the previous frame # set up for the next frame if (self._task is not None) and taskMgr._hasProfiledDesignatedTask(): session = taskMgr._getLastTaskProfileSession() # if we couldn't profile, throw this result out if session.profileSucceeded(): namePrefix = self._task.getNamePrefix() if namePrefix not in self._namePrefix2tracker: self._namePrefix2tracker[namePrefix] = TaskTracker(namePrefix) tracker = self._namePrefix2tracker[namePrefix] tracker.addProfileSession(session) # set up the next task self._task = taskMgr._getRandomTask() taskMgr._setProfileTask(self._task) return task.cont
class SiegeManager(DistributedObject, SiegeManagerBase): TeamJoinableChangedEvent = 'PVPTeamJoinableChanged' def __init__(self, cr): DistributedObject.__init__(self, cr) SiegeManagerBase.__init__(self) def generate(self): self._announcerInterest = None self._siegeTeam = 0 self._siegeTeamUpdater = FunctionCall(self._setSiegeTeam, localAvatar._siegeTeamSV) self._siegeTeamUpdater.pushCurrentState() DistributedObject.generate(self) self._pvpTeamJoinable = { } base.cr.distributedDistrict.siegeManager = self def delete(self): self._siegeTeamUpdater.destroy() del self._siegeTeamUpdater self._removeAnnouncerInterest() del self._pvpTeamJoinable del base.cr.distributedDistrict.siegeManager DistributedObject.delete(self) def setPvpEnabled(self, enabled): self._pvpEnabled = enabled def getPvpEnabled(self): return self._pvpEnabled def setTeamsJoinable(self, teamJoinableItems): for (teamId, joinable) in teamJoinableItems: self._pvpTeamJoinable[teamId] = joinable messenger.send(SiegeManager.TeamJoinableChangedEvent) def teamIsJoinable(self, teamId): if not config.GetBool('want-pvp-team-balance', 1): return True return self._pvpTeamJoinable.get(teamId, True) def sendTalk(self, message): print 'Seige Manager Sending Message %s' % message self.sendUpdate('setTalkGroup', [ 0, 0, '', message, [], 0]) def sendWLChat(self, message): self.sendUpdate('sendWLChat', [ message, 0, 0]) def sendSC(self, msgIndex): self.sendUpdate('sendSC', [ msgIndex]) def setTalkGroup(self, fromAv, fromAC, avatarName, chat, mods, flags): print 'Seige Manager- SetTalkGroup %s' % chat teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) (message, scrubbed) = localAvatar.scrubTalk(chat, mods) base.talkAssistant.receiveShipPVPMessage(fromAv, fromAC, avatarName, teamName, message, scrubbed) def recvChat(self, avatarId, message, chatFlags, DISLid, name): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % (name, self.getPVPChatTeamName(localAvatar.getSiegeTeam()), message) base.talkAssistant.receiveShipPVPMessage(avatarId, DISLid, name, teamName, message) def recvWLChat(self, avatarId, message, chatFlags, DISLid, name): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % (name, self.getPVPChatTeamName(localAvatar.getSiegeTeam()), message) base.talkAssistant.receiveShipPVPMessage(avatarId, DISLid, name, teamName, message) def recvSpeedChat(self, avatarId, msgIndex, name): print 'siege manager recvSpeedChat' if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % (name, self.getPVPChatTeamName(localAvatar.getSiegeTeam()), SCDecoders.decodeSCStaticTextMsg(msgIndex)) message = SCDecoders.decodeSCStaticTextMsg(msgIndex) teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) base.talkAssistant.receiveShipPVPMessage(avatarId, 0, name, teamName, message) def sendSCQuest(self, questInt, msgType, taskNum): self.sendUpdate('sendSCQuest', [ questInt, msgType, taskNum]) def recvSCQuest(self, avName, senderId, questInt, msgType, taskNum): senderName = avName message = base.talkAssistant.SCDecoder.decodeSCQuestMsgInt(questInt, msgType, taskNum) if not self.cr.avatarFriendsManager.checkIgnored(senderId): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) displayMess = '%s %s %s' % (avName, teamName, message) base.talkAssistant.receiveShipPVPMessage(senderId, 0, avName, teamName, message) def getPVPChatTeamName(self, teamId): if teamId == 2: return PLocalizer.PVPSpanish elif teamId == 1: return PLocalizer.PVPFrench else: return PLocalizer.PVPPrefix def _addAnnouncerInterest(self): if not self._announcerInterest: self._announcerInterest = self.cr.addTaggedInterest(self.doId, self.ANNOUNCER_ZONE, self.cr.ITAG_GAME, 'siegeAnnouncer') def _removeAnnouncerInterest(self): if self._announcerInterest: self.cr.removeTaggedInterest(self._announcerInterest) self._announcerInterest = None def _setSiegeTeam(self, siegeTeam): if siegeTeam and not (self._siegeTeam): self._addAnnouncerInterest() elif not siegeTeam and self._siegeTeam: self._removeAnnouncerInterest() self._siegeTeam = siegeTeam
class SiegeManager(DistributedObject, SiegeManagerBase): TeamJoinableChangedEvent = 'PVPTeamJoinableChanged' def __init__(self, cr): DistributedObject.__init__(self, cr) SiegeManagerBase.__init__(self) def generate(self): self._announcerInterest = None self._siegeTeam = 0 self._siegeTeamUpdater = FunctionCall(self._setSiegeTeam, localAvatar._siegeTeamSV) self._siegeTeamUpdater.pushCurrentState() DistributedObject.generate(self) self._pvpTeamJoinable = {} base.cr.distributedDistrict.siegeManager = self def delete(self): self._siegeTeamUpdater.destroy() del self._siegeTeamUpdater self._removeAnnouncerInterest() del self._pvpTeamJoinable del base.cr.distributedDistrict.siegeManager DistributedObject.delete(self) def setPvpEnabled(self, enabled): self._pvpEnabled = enabled def getPvpEnabled(self): return self._pvpEnabled def setTeamsJoinable(self, teamJoinableItems): for (teamId, joinable) in teamJoinableItems: self._pvpTeamJoinable[teamId] = joinable messenger.send(SiegeManager.TeamJoinableChangedEvent) def teamIsJoinable(self, teamId): if not config.GetBool('want-pvp-team-balance', 1): return True return self._pvpTeamJoinable.get(teamId, True) def sendTalk(self, message): print 'Seige Manager Sending Message %s' % message self.sendUpdate('setTalkGroup', [0, 0, '', message, [], 0]) def sendWLChat(self, message): self.sendUpdate('sendWLChat', [message, 0, 0]) def sendSC(self, msgIndex): self.sendUpdate('sendSC', [msgIndex]) def setTalkGroup(self, fromAv, fromAC, avatarName, chat, mods, flags): print 'Seige Manager- SetTalkGroup %s' % chat teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) (message, scrubbed) = localAvatar.scrubTalk(chat, mods) base.talkAssistant.receiveShipPVPMessage(fromAv, fromAC, avatarName, teamName, message, scrubbed) def recvChat(self, avatarId, message, chatFlags, DISLid, name): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % ( name, self.getPVPChatTeamName( localAvatar.getSiegeTeam()), message) base.talkAssistant.receiveShipPVPMessage(avatarId, DISLid, name, teamName, message) def recvWLChat(self, avatarId, message, chatFlags, DISLid, name): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % ( name, self.getPVPChatTeamName( localAvatar.getSiegeTeam()), message) base.talkAssistant.receiveShipPVPMessage(avatarId, DISLid, name, teamName, message) def recvSpeedChat(self, avatarId, msgIndex, name): print 'siege manager recvSpeedChat' if not self.cr.avatarFriendsManager.checkIgnored(avatarId): displayMess = '%s %s %s' % ( name, self.getPVPChatTeamName(localAvatar.getSiegeTeam()), SCDecoders.decodeSCStaticTextMsg(msgIndex)) message = SCDecoders.decodeSCStaticTextMsg(msgIndex) teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) base.talkAssistant.receiveShipPVPMessage(avatarId, 0, name, teamName, message) def sendSCQuest(self, questInt, msgType, taskNum): self.sendUpdate('sendSCQuest', [questInt, msgType, taskNum]) def recvSCQuest(self, avName, senderId, questInt, msgType, taskNum): senderName = avName message = base.talkAssistant.SCDecoder.decodeSCQuestMsgInt( questInt, msgType, taskNum) if not self.cr.avatarFriendsManager.checkIgnored(senderId): teamName = self.getPVPChatTeamName(localAvatar.getSiegeTeam()) displayMess = '%s %s %s' % (avName, teamName, message) base.talkAssistant.receiveShipPVPMessage(senderId, 0, avName, teamName, message) def getPVPChatTeamName(self, teamId): if teamId == 2: return PLocalizer.PVPSpanish elif teamId == 1: return PLocalizer.PVPFrench else: return PLocalizer.PVPPrefix def _addAnnouncerInterest(self): if not self._announcerInterest: self._announcerInterest = self.cr.addTaggedInterest( self.doId, self.ANNOUNCER_ZONE, self.cr.ITAG_GAME, 'siegeAnnouncer') def _removeAnnouncerInterest(self): if self._announcerInterest: self.cr.removeTaggedInterest(self._announcerInterest) self._announcerInterest = None def _setSiegeTeam(self, siegeTeam): if siegeTeam and not (self._siegeTeam): self._addAnnouncerInterest() elif not siegeTeam and self._siegeTeam: self._removeAnnouncerInterest() self._siegeTeam = siegeTeam
class FrameProfiler: notify = directNotify.newCategory('FrameProfiler') Minute = 60 Hour = 60 * Minute Day = 24 * Hour def __init__(self): Hour = FrameProfiler.Hour self._period = 2 * FrameProfiler.Minute if config.GetBool('frequent-frame-profiles', 0): self._period = 1 * FrameProfiler.Minute self._jitterMagnitude = self._period * 0.75 self._logSchedule = [ 1 * FrameProfiler.Hour, 4 * FrameProfiler.Hour, 12 * FrameProfiler.Hour, 1 * FrameProfiler.Day] if config.GetBool('frequent-frame-profiles', 0): self._logSchedule = [ 1 * FrameProfiler.Minute, 4 * FrameProfiler.Minute, 12 * FrameProfiler.Minute, 24 * FrameProfiler.Minute] for t in self._logSchedule: pass for i in xrange(len(self._logSchedule)): e = self._logSchedule[i] for j in xrange(i, len(self._logSchedule)): pass self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileFramesSV()) self._enableFC.pushCurrentState() def destroy(self): self._enableFC.set(False) self._enableFC.destroy() def _setEnabled(self, enabled): if enabled: self.notify.info('frame profiler started') self._startTime = globalClock.getFrameTime() self._profileCounter = 0 self._jitter = None self._period2aggregateProfile = { } self._id2session = { } self._id2task = { } self._task = taskMgr.doMethodLater(self._period, self._scheduleNextProfileDoLater, 'FrameProfilerStart-%s' % serialNum()) else: self._task.remove() del self._task for session in self._period2aggregateProfile.itervalues: session.release() del self._period2aggregateProfile for task in self._id2task.itervalues(): task.remove() del self._id2task for session in self._id2session.itervalues(): session.release() del self._id2session self.notify.info('frame profiler stopped') def _scheduleNextProfileDoLater(self, task): self._scheduleNextProfile() return task.done def _scheduleNextProfile(self): self._profileCounter += 1 self._timeElapsed = self._profileCounter * self._period time = self._startTime + self._timeElapsed jitter = self._jitter if jitter is None: jitter = normalDistrib(-(self._jitterMagnitude), self._jitterMagnitude) time += jitter else: time -= jitter jitter = None self._jitter = jitter sessionId = serialNum() session = taskMgr.getProfileSession('FrameProfile-%s' % sessionId) self._id2session[sessionId] = session taskMgr.profileFrames(num = 1, session = session, callback = Functor(self._analyzeResults, sessionId)) delay = max(time - globalClock.getFrameTime(), 0.0) self._task = taskMgr.doMethodLater(delay, self._scheduleNextProfileDoLater, 'FrameProfiler-%s' % serialNum()) def _analyzeResults(self, sessionId): self._id2task[sessionId] = taskMgr.add(Functor(self._doAnalysis, sessionId), 'FrameProfilerAnalysis-%s' % sessionId) def _doAnalysis(self, sessionId, task): if hasattr(task, '_generator'): gen = task._generator else: gen = self._doAnalysisGen(sessionId) task._generator = gen result = gen.next() if result == Task.done: del task._generator return result def _doAnalysisGen(self, sessionId): p2ap = self._period2aggregateProfile self._id2task.pop(sessionId) session = self._id2session.pop(sessionId) if session.profileSucceeded(): period = self._logSchedule[0] if period not in self._period2aggregateProfile: p2ap[period] = session.getReference() else: p2ap[period].aggregate(session) else: self.notify.warning('frame profile did not succeed') session.release() session = None counter = 0 for pi in xrange(len(self._logSchedule)): period = self._logSchedule[pi] if self._timeElapsed % period == 0: if period in p2ap: if counter >= 3: counter = 0 yield Task.cont self.notify.info('aggregate profile of sampled frames over last %s\n%s' % (formatTimeExact(period), p2ap[period].getResults())) counter += 1 nextIndex = pi + 1 if nextIndex >= len(self._logSchedule): nextPeriod = period * 2 self._logSchedule.append(nextPeriod) else: nextPeriod = self._logSchedule[nextIndex] if nextPeriod not in p2ap: p2ap[nextPeriod] = p2ap[period].getReference() else: p2ap[nextPeriod].aggregate(p2ap[period]) p2ap[period].release() del p2ap[period] period in p2ap break yield Task.done
class SCTerminal(SCElement): def __init__(self, linkedEmote = None): SCElement.__init__(self) self.setLinkedEmote(linkedEmote) scGui = loader.loadModel(SCMenu.GuiModelName) self.emotionIcon = scGui.find('**/emotionIcon') self.setDisabled(False) self.__numCharges = -1 self._handleWhisperModeSV = StateVar(False) self._handleWhisperModeFC = None return def destroy(self): self._handleWhisperModeSV.set(False) if self._handleWhisperModeFC: self._handleWhisperModeFC.destroy() self._handleWhisperModeSV.destroy() SCElement.destroy(self) def privSetSettingsRef(self, settingsRef): SCElement.privSetSettingsRef(self, settingsRef) if self._handleWhisperModeFC is None: self._handleWhisperModeFC = FunctionCall(self._handleWhisperModeSVChanged, self._handleWhisperModeSV) self._handleWhisperModeFC.pushCurrentState() self._handleWhisperModeSV.set(self.settingsRef is not None and not self.isWhisperable()) return def _handleWhisperModeSVChanged(self, handleWhisperMode): if handleWhisperMode: self._wmcListener = DirectObject() self._wmcListener.accept(self.getEventName(SCWhisperModeChangeEvent), self._handleWhisperModeChange) elif hasattr(self, '_wmcListener'): self._wmcListener.ignoreAll() del self._wmcListener self.invalidate() def _handleWhisperModeChange(self, whisperMode): self.invalidate() def handleSelect(self): messenger.send(self.getEventName(SCTerminalSelectedEvent)) if self.hasLinkedEmote() and self.linkedEmoteEnabled(): messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent), [self.linkedEmote]) def isWhisperable(self): return True def getLinkedEmote(self): return self.linkedEmote def setLinkedEmote(self, linkedEmote): self.linkedEmote = linkedEmote self.invalidate() def hasLinkedEmote(self): return self.linkedEmote is not None def linkedEmoteEnabled(self): if Emote.globalEmote: return Emote.globalEmote.isEnabled(self.linkedEmote) def getCharges(self): return self.__numCharges def setCharges(self, nCharges): self.__numCharges = nCharges if nCharges is 0: self.setDisabled(True) def isDisabled(self): return self.__disabled or self.isWhispering() and not self.isWhisperable() def setDisabled(self, bDisabled): self.__disabled = bDisabled def onMouseClick(self, event): if not self.isDisabled(): SCElement.onMouseClick(self, event) self.handleSelect() def getMinDimensions(self): width, height = SCElement.getMinDimensions(self) if self.hasLinkedEmote(): width += 1.3 return (width, height) def finalize(self, dbArgs = {}): if not self.isDirty(): return args = {} if self.hasLinkedEmote(): self.lastEmoteIconColor = self.getEmoteIconColor() self.emotionIcon.setColorScale(*self.lastEmoteIconColor) args.update({'image': self.emotionIcon, 'image_pos': (self.width - 0.6, 0, -self.height * 0.5)}) if self.isDisabled(): args.update({'rolloverColor': (0, 0, 0, 0), 'pressedColor': (0, 0, 0, 0), 'rolloverSound': None, 'clickSound': None, 'text_fg': self.getColorScheme().getTextDisabledColor() + (1,)}) args.update(dbArgs) SCElement.finalize(self, dbArgs=args) return def getEmoteIconColor(self): if self.linkedEmoteEnabled() and not self.isWhispering(): r, g, b = self.getColorScheme().getEmoteIconColor() else: r, g, b = self.getColorScheme().getEmoteIconDisabledColor() return (r, g, b, 1) def updateEmoteIcon(self): if hasattr(self, 'button'): self.lastEmoteIconColor = self.getEmoteIconColor() for i in xrange(self.button['numStates']): self.button['image%s_image' % i].setColorScale(*self.lastEmoteIconColor) else: self.invalidate() def enterVisible(self): SCElement.enterVisible(self) if hasattr(self, 'lastEmoteIconColor'): if self.getEmoteIconColor() != self.lastEmoteIconColor: self.invalidate() def handleWhisperModeChange(whisperMode, self = self): if self.hasLinkedEmote(): if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() self.accept(self.getEventName(SCWhisperModeChangeEvent), handleWhisperModeChange) def handleEmoteEnableStateChange(self = self): if self.hasLinkedEmote(): if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() if self.hasLinkedEmote(): if Emote.globalEmote: self.accept(Emote.globalEmote.EmoteEnableStateChanged, handleEmoteEnableStateChange) def exitVisible(self): SCElement.exitVisible(self) self.ignore(self.getEventName(SCWhisperModeChangeEvent)) if Emote.globalEmote: self.ignore(Emote.globalEmote.EmoteEnableStateChanged) def getDisplayText(self): if self.getCharges() is not -1: return self.text + ' (%s)' % self.getCharges() else: return self.text
class SCTerminal(SCElement): def __init__(self, linkedEmote = None): SCElement.__init__(self) self.setLinkedEmote(linkedEmote) scGui = loader.loadModel(SCMenu.GuiModelName) self.emotionIcon = scGui.find('**/emotionIcon') self.setDisabled(False) self.__numCharges = -1 self._handleWhisperModeSV = StateVar(False) self._handleWhisperModeFC = None return def destroy(self): self._handleWhisperModeSV.set(False) if self._handleWhisperModeFC: self._handleWhisperModeFC.destroy() self._handleWhisperModeSV.destroy() SCElement.destroy(self) def privSetSettingsRef(self, settingsRef): SCElement.privSetSettingsRef(self, settingsRef) if self._handleWhisperModeFC is None: self._handleWhisperModeFC = FunctionCall(self._handleWhisperModeSVChanged, self._handleWhisperModeSV) self._handleWhisperModeFC.pushCurrentState() self._handleWhisperModeSV.set(self.settingsRef is not None and not self.isWhisperable()) return def _handleWhisperModeSVChanged(self, handleWhisperMode): if handleWhisperMode: self._wmcListener = DirectObject() self._wmcListener.accept(self.getEventName(SCWhisperModeChangeEvent), self._handleWhisperModeChange) elif hasattr(self, '_wmcListener'): self._wmcListener.ignoreAll() del self._wmcListener self.invalidate() def _handleWhisperModeChange(self, whisperMode): self.invalidate() def handleSelect(self): messenger.send(self.getEventName(SCTerminalSelectedEvent)) if self.hasLinkedEmote() and self.linkedEmoteEnabled(): messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent), [self.linkedEmote]) def isWhisperable(self): return True def getLinkedEmote(self): return self.linkedEmote def setLinkedEmote(self, linkedEmote): self.linkedEmote = linkedEmote self.invalidate() def hasLinkedEmote(self): return self.linkedEmote is not None def linkedEmoteEnabled(self): if Emote.globalEmote: return Emote.globalEmote.isEnabled(self.linkedEmote) def getCharges(self): return self.__numCharges def setCharges(self, nCharges): self.__numCharges = nCharges if nCharges is 0: self.setDisabled(True) def isDisabled(self): return self.__disabled or self.isWhispering() and not self.isWhisperable() def setDisabled(self, bDisabled): self.__disabled = bDisabled def onMouseClick(self, event): if not self.isDisabled(): SCElement.onMouseClick(self, event) self.handleSelect() def getMinDimensions(self): width, height = SCElement.getMinDimensions(self) if self.hasLinkedEmote(): width += 1.3 return (width, height) def finalize(self, dbArgs = {}): if not self.isDirty(): return args = {} if self.hasLinkedEmote(): self.lastEmoteIconColor = self.getEmoteIconColor() self.emotionIcon.setColorScale(*self.lastEmoteIconColor) args.update({'image': self.emotionIcon, 'image_pos': (self.width - 0.6, 0, -self.height * 0.5)}) if self.isDisabled(): args.update({'rolloverColor': (0, 0, 0, 0), 'pressedColor': (0, 0, 0, 0), 'rolloverSound': None, 'clickSound': None, 'text_fg': self.getColorScheme().getTextDisabledColor() + (1,)}) args.update(dbArgs) SCElement.finalize(self, dbArgs=args) return def getEmoteIconColor(self): if self.linkedEmoteEnabled() and not self.isWhispering(): r, g, b = self.getColorScheme().getEmoteIconColor() else: r, g, b = self.getColorScheme().getEmoteIconDisabledColor() return (r, g, b, 1) def updateEmoteIcon(self): if hasattr(self, 'button'): self.lastEmoteIconColor = self.getEmoteIconColor() for i in range(self.button['numStates']): self.button['image%s_image' % i].setColorScale(*self.lastEmoteIconColor) else: self.invalidate() def enterVisible(self): SCElement.enterVisible(self) if hasattr(self, 'lastEmoteIconColor'): if self.getEmoteIconColor() != self.lastEmoteIconColor: self.invalidate() def handleWhisperModeChange(whisperMode, self = self): if self.hasLinkedEmote(): if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() self.accept(self.getEventName(SCWhisperModeChangeEvent), handleWhisperModeChange) def handleEmoteEnableStateChange(self = self): if self.hasLinkedEmote(): if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() if self.hasLinkedEmote(): if Emote.globalEmote: self.accept(Emote.globalEmote.EmoteEnableStateChanged, handleEmoteEnableStateChange) def exitVisible(self): SCElement.exitVisible(self) self.ignore(self.getEventName(SCWhisperModeChangeEvent)) if Emote.globalEmote: self.ignore(Emote.globalEmote.EmoteEnableStateChanged) def getDisplayText(self): if self.getCharges() is not -1: return self.text + ' (%s)' % self.getCharges() else: return self.text
class FrameProfiler: notify = directNotify.newCategory('FrameProfiler') # because of precision requirements, all times related to the profile/log # schedule are stored as integers Minute = 60 Hour = 60 * Minute Day = 24 * Hour def __init__(self): Hour = FrameProfiler.Hour # how long to wait between frame profiles self._period = 2 * FrameProfiler.Minute if config.GetBool('frequent-frame-profiles', 0): self._period = 1 * FrameProfiler.Minute # used to prevent profile from being taken exactly every 'period' seconds self._jitterMagnitude = self._period * .75 # when to log output # each entry must be an integer multiple of all previous entries # as well as an integer multiple of the period self._logSchedule = [ 1 * FrameProfiler.Hour, 4 * FrameProfiler.Hour, 12 * FrameProfiler.Hour, 1 * FrameProfiler.Day, ] # day schedule proceeds as 1, 2, 4, 8 days, etc. if config.GetBool('frequent-frame-profiles', 0): self._logSchedule = [ 1 * FrameProfiler.Minute, 4 * FrameProfiler.Minute, 12 * FrameProfiler.Minute, 24 * FrameProfiler.Minute, ] for t in self._logSchedule: assert isInteger(t) # make sure the period is evenly divisible into each element of the log schedule assert (t % self._period) == 0 # make sure each element of the schedule is evenly divisible into each subsequent element for i in xrange(len(self._logSchedule)): e = self._logSchedule[i] for j in xrange(i, len(self._logSchedule)): assert (self._logSchedule[j] % e) == 0 assert isInteger(self._period) self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileFramesSV()) self._enableFC.pushCurrentState() def destroy(self): self._enableFC.set(False) self._enableFC.destroy() def _setEnabled(self, enabled): if enabled: self.notify.info('frame profiler started') self._startTime = globalClock.getFrameTime() self._profileCounter = 0 self._jitter = None self._period2aggregateProfile = {} self._id2session = {} self._id2task = {} # don't profile process startup self._task = taskMgr.doMethodLater(self._period, self._scheduleNextProfileDoLater, 'FrameProfilerStart-%s' % serialNum()) else: self._task.remove() del self._task for session in self._period2aggregateProfile.itervalues: session.release() del self._period2aggregateProfile for task in self._id2task.itervalues(): task.remove() del self._id2task for session in self._id2session.itervalues(): session.release() del self._id2session self.notify.info('frame profiler stopped') def _scheduleNextProfileDoLater(self, task): self._scheduleNextProfile() return task.done def _scheduleNextProfile(self): self._profileCounter += 1 self._timeElapsed = self._profileCounter * self._period assert isInteger(self._timeElapsed) time = self._startTime + self._timeElapsed # vary the actual delay between profiles by a random amount to prevent interaction # with periodic events jitter = self._jitter if jitter is None: jitter = normalDistrib(-self._jitterMagnitude, self._jitterMagnitude) time += jitter else: time -= jitter jitter = None self._jitter = jitter sessionId = serialNum() session = taskMgr.getProfileSession('FrameProfile-%s' % sessionId) self._id2session[sessionId] = session taskMgr.profileFrames(num=1, session=session, callback=Functor( self._analyzeResults, sessionId)) # schedule the next profile delay = max(time - globalClock.getFrameTime(), 0.) self._task = taskMgr.doMethodLater(delay, self._scheduleNextProfileDoLater, 'FrameProfiler-%s' % serialNum()) def _analyzeResults(self, sessionId): # do the analysis in a task 1) to separate the processing from the profiled frame, # and 2) to get the processing to show up in a named task instead of in the taskMgr self._id2task[sessionId] = taskMgr.add( Functor(self._doAnalysis, sessionId), 'FrameProfilerAnalysis-%s' % sessionId) def _doAnalysis(self, sessionId, task): if hasattr(task, '_generator'): gen = task._generator else: gen = self._doAnalysisGen(sessionId) task._generator = gen result = gen.next() if result == Task.done: del task._generator return result def _doAnalysisGen(self, sessionId): # generator to limit max number of profile loggings per frame p2ap = self._period2aggregateProfile self._id2task.pop(sessionId) session = self._id2session.pop(sessionId) if session.profileSucceeded(): # always add this profile to the first aggregated profile period = self._logSchedule[0] if period not in self._period2aggregateProfile: p2ap[period] = session.getReference() else: p2ap[period].aggregate(session) else: self.notify.warning('frame profile did not succeed') session.release() session = None counter = 0 # log profiles when it's time, and aggregate them upwards into the # next-longer profile for pi in xrange(len(self._logSchedule)): period = self._logSchedule[pi] if (self._timeElapsed % period) == 0: if period in p2ap: # delay until the next frame if we've already processed N profiles this frame if counter >= 3: counter = 0 yield Task.cont self.notify.info('aggregate profile of sampled frames over last %s\n%s' % (formatTimeExact(period), p2ap[period].getResults())) counter += 1 # aggregate this profile into the next larger profile nextIndex = pi + 1 if nextIndex >= len(self._logSchedule): # if we're adding a new period to the end of the log period table, # set it to double the duration of the current longest period nextPeriod = period * 2 self._logSchedule.append(nextPeriod) else: nextPeriod = self._logSchedule[nextIndex] if nextPeriod not in p2ap: p2ap[nextPeriod] = p2ap[period].getReference() else: p2ap[nextPeriod].aggregate(p2ap[period]) # this profile is now represented in the next larger profile # throw it out p2ap[period].release() del p2ap[period] else: # current time is not divisible evenly into selected period, and all higher # periods are multiples of this one break yield Task.done
class TaskProfiler: notify = directNotify.newCategory('TaskProfiler') def __init__(self): self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileTasksSV()) self._enableFC.pushCurrentState() self._namePrefix2tracker = {} self._task = None return def destroy(self): if taskMgr.getProfileTasks(): self._setEnabled(False) self._enableFC.destroy() for tracker in self._namePrefix2tracker.itervalues(): tracker.destroy() del self._namePrefix2tracker del self._task @staticmethod def GetDefaultSpikeThreshold(): return config.GetFloat('profile-task-spike-threshold', 5.0) @staticmethod def SetSpikeThreshold(spikeThreshold): TaskTracker.SpikeThreshold = spikeThreshold @staticmethod def GetSpikeThreshold(): return TaskTracker.SpikeThreshold def logProfiles(self, name=None): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if name and name not in namePrefix.lower(): continue tracker.log() def flush(self, name): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if name and name not in namePrefix.lower(): continue tracker.flush() def _setEnabled(self, enabled): if enabled: self.notify.info('task profiler started') self._taskName = 'profile-tasks-%s' % id(self) taskMgr.add(self._doProfileTasks, self._taskName, priority=-200) else: taskMgr.remove(self._taskName) del self._taskName self.notify.info('task profiler stopped') def _doProfileTasks(self, task=None): if self._task is not None and taskMgr._hasProfiledDesignatedTask(): session = taskMgr._getLastTaskProfileSession() if session.profileSucceeded(): namePrefix = self._task.getNamePrefix() if namePrefix not in self._namePrefix2tracker: self._namePrefix2tracker[namePrefix] = TaskTracker( namePrefix) tracker = self._namePrefix2tracker[namePrefix] tracker.addProfileSession(session) self._task = taskMgr._getRandomTask() taskMgr._setProfileTask(self._task) return task.cont
class TaskProfiler: # this does intermittent profiling of tasks running on the system # if a task has a spike in execution time, the profile of the spike is logged notify = directNotify.newCategory("TaskProfiler") def __init__(self): self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileTasksSV()) self._enableFC.pushCurrentState() # table of task name pattern to TaskTracker self._namePrefix2tracker = {} self._task = None def destroy(self): if taskMgr.getProfileTasks(): self._setEnabled(False) self._enableFC.destroy() for tracker in self._namePrefix2tracker.itervalues(): tracker.destroy() del self._namePrefix2tracker del self._task @staticmethod def GetDefaultSpikeThreshold(): return config.GetFloat('profile-task-spike-threshold', 5.) @staticmethod def SetSpikeThreshold(spikeThreshold): TaskTracker.SpikeThreshold = spikeThreshold @staticmethod def GetSpikeThreshold(): return TaskTracker.SpikeThreshold def logProfiles(self, name=None): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if (name and (name not in namePrefix.lower())): continue tracker.log() def flush(self, name): if name: name = name.lower() # flush stored task profiles for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if (name and (name not in namePrefix.lower())): continue tracker.flush() def _setEnabled(self, enabled): if enabled: self.notify.info('task profiler started') self._taskName = 'profile-tasks-%s' % id(self) taskMgr.add(self._doProfileTasks, self._taskName, priority=-200) else: taskMgr.remove(self._taskName) del self._taskName self.notify.info('task profiler stopped') def _doProfileTasks(self, task=None): # gather data from the previous frame # set up for the next frame if (self._task is not None) and taskMgr._hasProfiledDesignatedTask(): session = taskMgr._getLastTaskProfileSession() # if we couldn't profile, throw this result out if session.profileSucceeded(): namePrefix = self._task.getNamePrefix() if namePrefix not in self._namePrefix2tracker: self._namePrefix2tracker[namePrefix] = TaskTracker(namePrefix) tracker = self._namePrefix2tracker[namePrefix] tracker.addProfileSession(session) # set up the next task self._task = taskMgr._getRandomTask() taskMgr._setProfileTask(self._task) return task.cont
1.0, 1.0]) RepairKitHp = StateVarSetting('pvp.shipHeal.repairKit.HP', WeaponGlobals.getAttackHullHP(InventoryType.ShipRepairKit)) RepairKitSp = StateVarSetting('pvp.shipHeal.repairKit.SP', WeaponGlobals.getAttackSailHP(InventoryType.ShipRepairKit)) SinkHpBonusPercent = StateVarSetting('pvp.sinkBonus.hp.percent', 0.80000000000000004) SinkStreakPeriod = StateVarSetting('pvp.announcements.sinkStreakPeriod', 5) def updateRepairKitHp(hp): WeaponGlobals.__skillInfo[InventoryType.ShipRepairKit][WeaponGlobals.HULL_HP_INDEX] = hp def updateRepairKitSp(sp): WeaponGlobals.__skillInfo[InventoryType.ShipRepairKit][WeaponGlobals.SAIL_HP_INDEX] = sp UpdateRepairKitHp = FunctionCall(updateRepairKitHp, RepairKitHp) UpdateRepairKitHp.pushCurrentState() UpdateRepairKitSp = FunctionCall(updateRepairKitSp, RepairKitSp) UpdateRepairKitSp.pushCurrentState() RepairSpotLocatorNames = [ 'repair_spot_0', 'repair_spot_1', 'repair_spot_2', 'repair_spot_3'] repairSpotNamePrefix = 'pvp.shipHeal.repairSpots.spots.' ShipClass2repairLocators = { ShipGlobals.INTERCEPTORL1: StateVarSetting(repairSpotNamePrefix + 'interceptorL1', [ 0, 1, 2, 3]), ShipGlobals.INTERCEPTORL2: StateVarSetting(repairSpotNamePrefix + 'interceptorL2', [
1.0, 1.0]) RepairKitHp = StateVarSetting('pvp.shipHeal.repairKit.HP', WeaponGlobals.getAttackHullHP(InventoryType.ShipRepairKit)) RepairKitSp = StateVarSetting('pvp.shipHeal.repairKit.SP', WeaponGlobals.getAttackSailHP(InventoryType.ShipRepairKit)) SinkHpBonusPercent = StateVarSetting('pvp.sinkBonus.hp.percent', 0.80000000000000004) SinkStreakPeriod = StateVarSetting('pvp.announcements.sinkStreakPeriod', 5) def updateRepairKitHp(hp): WeaponGlobals.__skillInfo[InventoryType.ShipRepairKit][WeaponGlobals.HULL_HP_INDEX] = hp def updateRepairKitSp(sp): WeaponGlobals.__skillInfo[InventoryType.ShipRepairKit][WeaponGlobals.SAIL_HP_INDEX] = sp UpdateRepairKitHp = FunctionCall(updateRepairKitHp, RepairKitHp) UpdateRepairKitHp.pushCurrentState() UpdateRepairKitSp = FunctionCall(updateRepairKitSp, RepairKitSp) UpdateRepairKitSp.pushCurrentState() RepairSpotLocatorNames = [ 'repair_spot_0', 'repair_spot_1', 'repair_spot_2', 'repair_spot_3'] repairSpotNamePrefix = 'pvp.shipHeal.repairSpots.spots.' ShipClass2repairLocators = { ShipGlobals.INTERCEPTORL1: StateVarSetting(repairSpotNamePrefix + 'interceptorL1', [ 0, 1, 2, 3]), ShipGlobals.INTERCEPTORL2: StateVarSetting(repairSpotNamePrefix + 'interceptorL2', [
class SCTerminal(SCElement): """ SCTerminal is the base class for all 'terminal' speedchat entities """ def __init__(self, linkedEmote=None): SCElement.__init__(self) self.setLinkedEmote(linkedEmote) scGui = loader.loadModel(SCMenu.GuiModelName) self.emotionIcon = scGui.find('**/emotionIcon') self.setDisabled(False) self.__numCharges = -1 # should we listen for whisper mode changes? self._handleWhisperModeSV = StateVar(False) # can't set this up until we're ready to have the handler func called self._handleWhisperModeFC = None def destroy(self): self._handleWhisperModeSV.set(False) if self._handleWhisperModeFC: self._handleWhisperModeFC.destroy() self._handleWhisperModeSV.destroy() SCElement.destroy(self) def privSetSettingsRef(self, settingsRef): SCElement.privSetSettingsRef(self, settingsRef) if self._handleWhisperModeFC is None: self._handleWhisperModeFC = FunctionCall(self._handleWhisperModeSVChanged, self._handleWhisperModeSV) self._handleWhisperModeFC.pushCurrentState() # if this terminal is not whisperable, we need to listen for whisper mode changes self._handleWhisperModeSV.set((self.settingsRef is not None) and (not self.isWhisperable())) def _handleWhisperModeSVChanged(self, handleWhisperMode): if handleWhisperMode: # this terminal can't be whispered. we need to reconstruct # our GUI element when the whisper mode changes # listen for that mode change # create a DirectObject to avoid conflicts with other parts of this # object that are listening for this event self._wmcListener = DirectObject() self._wmcListener.accept(self.getEventName(SCWhisperModeChangeEvent), self._handleWhisperModeChange) else: if hasattr(self, '_wmcListener'): # we no longer need to listen for whisper mode changes self._wmcListener.ignoreAll() del self._wmcListener # make sure our GUI element is appropriate self.invalidate() def _handleWhisperModeChange(self, whisperMode): # whisper mode changed, we need to change our GUI element self.invalidate() # the meat of SCTerminal; inheritors should override this # and perform the appropriate action def handleSelect(self): """ called when the user selects this node """ # send the generic 'something was selected' event messenger.send(self.getEventName(SCTerminalSelectedEvent)) # if we have a linked emote, and it isn't disabled, generate a msg if self.hasLinkedEmote() and self.linkedEmoteEnabled(): messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent), [self.linkedEmote]) def isWhisperable(self): # can this terminal be sent as a whisper message? return True # Some terminal nodes have an emote associated with them, which # should be invoked when the node is selected. def getLinkedEmote(self): return self.linkedEmote def setLinkedEmote(self, linkedEmote): self.linkedEmote = linkedEmote # TODO: we should make sure we're listening for emote # enable state changes if this is set while we're visible self.invalidate() def hasLinkedEmote(self): return (self.linkedEmote is not None) def linkedEmoteEnabled(self): if Emote.globalEmote: return Emote.globalEmote.isEnabled(self.linkedEmote) def getCharges(self): return self.__numCharges def setCharges(self, nCharges): self.__numCharges = nCharges if (nCharges is 0): self.setDisabled(True) # support for disabled terminals def isDisabled(self): return self.__disabled or (self.isWhispering() and not self.isWhisperable()) def setDisabled(self, bDisabled): # make the button 'unclickable' self.__disabled = bDisabled # from SCElement def onMouseClick(self, event): if not self.isDisabled(): SCElement.onMouseClick(self, event) self.handleSelect() def getMinDimensions(self): width, height = SCElement.getMinDimensions(self) if self.hasLinkedEmote(): # add space for the emotion icon width += 1.3 return width, height def finalize(self, dbArgs={}): """ catch this call and influence the appearance of our button """ if not self.isDirty(): return args = {} if self.hasLinkedEmote(): self.lastEmoteIconColor = self.getEmoteIconColor() self.emotionIcon.setColorScale(*self.lastEmoteIconColor) args.update({ 'image': self.emotionIcon, 'image_pos': (self.width-.6,0,-self.height*.5), }) if self.isDisabled(): args.update({ 'rolloverColor': (0,0,0,0), 'pressedColor': (0,0,0,0), 'rolloverSound': None, 'clickSound': None, 'text_fg': self.getColorScheme().getTextDisabledColor()+(1,), }) args.update(dbArgs) SCElement.finalize(self, dbArgs=args) def getEmoteIconColor(self): if self.linkedEmoteEnabled() and (not self.isWhispering()): r,g,b = self.getColorScheme().getEmoteIconColor() else: r,g,b = self.getColorScheme().getEmoteIconDisabledColor() return (r,g,b,1) def updateEmoteIcon(self): if hasattr(self, 'button'): self.lastEmoteIconColor = self.getEmoteIconColor() for i in range(self.button['numStates']): self.button['image%s_image' % i].setColorScale( *self.lastEmoteIconColor) else: self.invalidate() # from SCObject def enterVisible(self): SCElement.enterVisible(self) # Check if the emote state has changed since the last time # we were finalized, and invalidate if it's different. if hasattr(self, 'lastEmoteIconColor'): if self.getEmoteIconColor() != self.lastEmoteIconColor: self.invalidate() # listen for whisper-mode changes def handleWhisperModeChange(whisperMode, self=self): if self.hasLinkedEmote(): # we are leaving or entering whisper mode; # the appearance of our emote icon needs to change # (no linked emotes on whispers) if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() self.accept(self.getEventName(SCWhisperModeChangeEvent), handleWhisperModeChange) # listen for emote-enable state changes def handleEmoteEnableStateChange(self=self): if self.hasLinkedEmote(): # emotions have just become enabled/disabled # update our emote icon # (no emotes when whispering) if self.isVisible() and not self.isWhispering(): self.updateEmoteIcon() if self.hasLinkedEmote(): if Emote.globalEmote: self.accept(Emote.globalEmote.EmoteEnableStateChanged, handleEmoteEnableStateChange) def exitVisible(self): SCElement.exitVisible(self) self.ignore(self.getEventName(SCWhisperModeChangeEvent)) if Emote.globalEmote: self.ignore(Emote.globalEmote.EmoteEnableStateChanged) def getDisplayText(self): if self.getCharges() is not -1: return self.text + " (%s)" % self.getCharges() else: return self.text
class FrameProfiler(): __module__ = __name__ notify = directNotify.newCategory('FrameProfiler') Minute = 60 Hour = 60 * Minute Day = 24 * Hour def __init__(self): Hour = FrameProfiler.Hour self._period = 2 * FrameProfiler.Minute if config.GetBool('frequent-frame-profiles', 0): self._period = 1 * FrameProfiler.Minute self._jitterMagnitude = self._period * 0.75 self._logSchedule = [1 * FrameProfiler.Hour, 4 * FrameProfiler.Hour, 12 * FrameProfiler.Hour, 1 * FrameProfiler.Day] if config.GetBool('frequent-frame-profiles', 0): self._logSchedule = [1 * FrameProfiler.Minute, 4 * FrameProfiler.Minute, 12 * FrameProfiler.Minute, 24 * FrameProfiler.Minute] for t in self._logSchedule: pass for i in xrange(len(self._logSchedule)): e = self._logSchedule[i] for j in xrange(i, len(self._logSchedule)): pass self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileFramesSV()) self._enableFC.pushCurrentState() def destroy(self): self._enableFC.set(False) self._enableFC.destroy() def _setEnabled(self, enabled): if enabled: self.notify.info('frame profiler started') self._startTime = globalClock.getFrameTime() self._profileCounter = 0 self._jitter = None self._period2aggregateProfile = {} self._id2session = {} self._id2task = {} self._task = taskMgr.doMethodLater(self._period, self._scheduleNextProfileDoLater, 'FrameProfilerStart-%s' % serialNum()) else: self._task.remove() del self._task for session in self._period2aggregateProfile.itervalues: session.release() del self._period2aggregateProfile for task in self._id2task.itervalues(): task.remove() del self._id2task for session in self._id2session.itervalues(): session.release() del self._id2session self.notify.info('frame profiler stopped') return def _scheduleNextProfileDoLater(self, task): self._scheduleNextProfile() return task.done def _scheduleNextProfile(self): self._profileCounter += 1 self._timeElapsed = self._profileCounter * self._period time = self._startTime + self._timeElapsed jitter = self._jitter if jitter is None: jitter = normalDistrib(-self._jitterMagnitude, self._jitterMagnitude) time += jitter else: time -= jitter jitter = None self._jitter = jitter sessionId = serialNum() session = taskMgr.getProfileSession('FrameProfile-%s' % sessionId) self._id2session[sessionId] = session taskMgr.profileFrames(num=1, session=session, callback=Functor(self._analyzeResults, sessionId)) delay = max(time - globalClock.getFrameTime(), 0.0) self._task = taskMgr.doMethodLater(delay, self._scheduleNextProfileDoLater, 'FrameProfiler-%s' % serialNum()) return def _analyzeResults(self, sessionId): self._id2task[sessionId] = taskMgr.add(Functor(self._doAnalysis, sessionId), 'FrameProfilerAnalysis-%s' % sessionId) def _doAnalysis(self, sessionId, task): if hasattr(task, '_generator'): gen = task._generator else: gen = self._doAnalysisGen(sessionId) task._generator = gen result = gen.next() if result == Task.done: del task._generator return result def _doAnalysisGen--- This code section failed: ---
class TaskProfiler(): __module__ = __name__ notify = directNotify.newCategory('TaskProfiler') def __init__(self): self._enableFC = FunctionCall(self._setEnabled, taskMgr.getProfileTasksSV()) self._enableFC.pushCurrentState() self._namePrefix2tracker = {} self._task = None return def destroy(self): if taskMgr.getProfileTasks(): self._setEnabled(False) self._enableFC.destroy() for tracker in self._namePrefix2tracker.itervalues(): tracker.destroy() del self._namePrefix2tracker del self._task @staticmethod def GetDefaultSpikeThreshold(): return config.GetFloat('profile-task-spike-threshold', 5.0) @staticmethod def SetSpikeThreshold(spikeThreshold): TaskTracker.SpikeThreshold = spikeThreshold @staticmethod def GetSpikeThreshold(): return TaskTracker.SpikeThreshold def logProfiles(self, name = None): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if name and name not in namePrefix.lower(): continue tracker.log() def flush(self, name): if name: name = name.lower() for namePrefix, tracker in self._namePrefix2tracker.iteritems(): if name and name not in namePrefix.lower(): continue tracker.flush() def _setEnabled(self, enabled): if enabled: self.notify.info('task profiler started') self._taskName = 'profile-tasks-%s' % id(self) taskMgr.add(self._doProfileTasks, self._taskName, priority=-200) else: taskMgr.remove(self._taskName) del self._taskName self.notify.info('task profiler stopped') def _doProfileTasks(self, task = None): if self._task is not None and taskMgr._hasProfiledDesignatedTask(): session = taskMgr._getLastTaskProfileSession() if session.profileSucceeded(): namePrefix = self._task.getNamePrefix() if namePrefix not in self._namePrefix2tracker: self._namePrefix2tracker[namePrefix] = TaskTracker(namePrefix) tracker = self._namePrefix2tracker[namePrefix] tracker.addProfileSession(session) self._task = taskMgr._getRandomTask() taskMgr._setProfileTask(self._task) return task.cont