def doMagicWord(self, word, av, zoneId, senderId): wordIs = self.getWordIs(word) if wordIs("~rename"): if (not self.supportRename): self.notify.warning( "Rename is not supported for %s, requested by %d" % (av.name, senderId)) else: name = string.strip(word[8:]) if name == "": response = "No name." else: av.d_setName(name) elif wordIs("~badname"): self.notify.warning( "Renaming inappropriately named toon %s (doId %d)." % (av.name, av.doId)) name = "toon%d" % (av.doId % 1000000) av.d_setName(name) elif wordIs("~chat"): if (not self.supportSuperchat) and (senderId != av.doId): self.notify.warning( "Super chat is not supported for %s, requested by %d" % (av.name, senderId)) else: av.d_setCommonChatFlags(OTPGlobals.CommonChat) self.notify.debug("Giving common chat permission to " + av.name) elif wordIs("~superchat"): if not self.supportSuperchat: self.notify.warning("Super chat is not supported for " + av.name) else: av.d_setCommonChatFlags(OTPGlobals.SuperChat) self.notify.debug("Giving super chat permission to " + av.name) elif wordIs("~nochat"): av.d_setCommonChatFlags(0) self.notify.debug("Removing special chat permissions for " + av.name) elif wordIs("~listen"): if (not self.supportSuperchat) and (senderId != av.doId): self.notify.warning( "Listen is not supported for %s, requested by %d" % (av.name, senderId)) else: # This is a client-side word. if (senderId != av.doId): self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId]) elif wordIs("~fix"): anyChanged = av.fixAvatar() if anyChanged: response = "avatar fixed." else: response = "avatar does not need fixing." self.down_setMagicWordResponse(senderId, response) self.down_setMagicWordResponse(senderId, response) elif wordIs("~who all"): str = '' for obj in list(self.air.doId2do.values()): if hasattr(obj, "accountName"): str += '%s %s\n' % (obj.accountName, obj.name) if not str: str = "No avatars." self.down_setMagicWordResponse(senderId, str) elif wordIs("~ouch"): if av.hp < 1: av.b_setHp(0) av.toonUp(1) else: av.b_setHp(1) self.notify.debug("Only 1 hp for " + av.name) elif wordIs("~sad"): av.b_setHp(0) self.notify.debug("Only 0 hp for " + av.name) elif wordIs("~dead"): av.takeDamage(av.hp) self.notify.debug(av.name + " is dead") elif wordIs("~waydead"): av.takeDamage(av.hp) av.b_setHp(-100) self.notify.debug(av.name + " is way dead") elif wordIs("~toonup"): av.toonUp(av.maxHp) self.notify.debug("Full heal for " + av.name) elif wordIs('~hp'): args = word.split() hp = int(args[1]) av.b_setHp(hp) self.notify.debug('Set hp to %s for %s' % (hp, av.name)) elif wordIs("~ainotify"): args = word.split() n = Notify.ptr().getCategory(args[1]) n.setSeverity({ 'error': NSError, 'warning': NSWarning, 'info': NSInfo, 'debug': NSDebug, 'spam': NSSpam, }[args[2]]) elif wordIs("~ghost"): # Toggle ghost mode. Ghost mode == 2 indicates a magic # word was the source. if av.ghostMode: av.b_setGhostMode(0) else: av.b_setGhostMode(2) elif wordIs('~immortal'): # ~immortal toggles immortal mode on and off # ~immortal 0/1 and ~immortal on/off sets the mode explicitly args = word.split() invalid = False if len(args) > 1 and args[1] in ('0', 'off'): immortal = False elif len(args) > 1 and args[1] in ('1', 'on'): immortal = True elif len(args) > 1: invalid = True else: immortal = not av.immortalMode if invalid: self.down_setMagicWordResponse(senderId, 'unknown argument %s' % args[1]) else: # immortality av.setImmortalMode(immortal) if av.immortalMode: response = 'immortality ON' else: response = 'immortality OFF' self.down_setMagicWordResponse(senderId, response) elif wordIs("~dna"): # Fiddle with your dna. self.doDna(word, av, zoneId, senderId) elif wordIs('~ai'): # Execute an arbitrary Python command on the AI. command = string.strip(word[3:]) self.notify.warning("Executing command '%s' from %s" % (command, senderId)) text = self.__execMessage( command)[:simbase.config.GetInt("ai-debug-length", 300)] self.down_setMagicWordResponse(senderId, text) elif wordIs('~ud'): # Execute an arbitrary Python command on the ud. print(word) channel, command = re.match("~ud ([0-9]+) (.+)", word).groups() channel = int(channel) if (simbase.air.doId2do.get(channel)): self.notify.warning("Passing command '%s' to %s from %s" % (command, channel, senderId)) try: simbase.air.doId2do[channel].sendUpdate( "execCommand", [command, self.doId, senderId, zoneId]) except: pass elif wordIs('~aiobjects'): args = word.split() from direct.showbase import ObjectReport report = ObjectReport.ObjectReport('AI ~objects') if 'all' in args: self.notify.info('printing full object set...') report.getObjectPool().printObjsByType( printReferrers='ref' in args) if hasattr(self, 'baselineObjReport'): self.notify.info( 'calculating diff from baseline ObjectReport...') self.lastDiff = self.baselineObjReport.diff(report) self.lastDiff.printOut(full=('diff' in args or 'dif' in args)) if 'baseline' in args or not hasattr(self, 'baselineObjReport'): self.notify.info('recording baseline ObjectReport...') if hasattr(self, 'baselineObjReport'): self.baselineObjReport.destroy() self.baselineObjReport = report self.down_setMagicWordResponse(senderId, 'objects logged') elif wordIs('~aiobjecthg'): import gc objs = gc.get_objects() type2count = {} for obj in objs: tn = safeTypeName(obj) type2count.setdefault(tn, 0) type2count[tn] += 1 count2type = invertDictLossless(type2count) counts = list(count2type.keys()) counts.sort() counts.reverse() for count in counts: print('%s: %s' % (count, count2type[count])) self.down_setMagicWordResponse(senderId, '~aiobjecthg complete') elif wordIs('~aicrash'): # TODO: require a typed explanation in production # if we call notify.error directly, the magic word mgr will catch it # self.notify.error doesn't seem to work either DelayedCall( Functor(simbase.air.notify.error, '~aicrash: simulating an AI crash')) elif wordIs('~aicontainers'): args = word.split() limit = 30 if 'full' in args: limit = None ContainerReport.ContainerReport('~aicontainers', log=True, limit=limit, threaded=True) elif wordIs('~aigarbage'): args = word.split() # it can take a LOOONG time to print out the garbage referrers and referents # by reference (as opposed to by number) full = ('full' in args) safeMode = ('safe' in args) verbose = ('verbose' in args) delOnly = ('delonly' in args) def handleGarbageDone(senderId, garbageReport): self.down_setMagicWordResponse( senderId, 'garbage logged, %s AI cycles' % garbageReport.getNumCycles()) # This does a garbage collection and dumps the list of leaked (uncollectable) objects to the AI log. GarbageReport.GarbageReport('~aigarbage', fullReport=full, verbose=verbose, log=True, threaded=True, doneCallback=Functor( handleGarbageDone, senderId), safeMode=safeMode, delOnly=delOnly) elif wordIs("~creategarbage"): args = word.split() num = 1 if len(args) > 1: num = int(args[1]) GarbageReport._createGarbage(num) self.down_setMagicWordResponse(senderId, 'leaked garbage created') elif wordIs('~leaktask'): def leakTask(task): return task.cont taskMgr.add(leakTask, uniqueName('leakedTask')) leakTask = None self.down_setMagicWordResponse(senderId, 'leaked task created') elif wordIs('~aileakmessage'): MessengerLeakDetector._leakMessengerObject() self.down_setMagicWordResponse(senderId, 'messenger leak object created') elif wordIs('~leakContainer'): ContainerLeakDetector._createContainerLeak() self.down_setMagicWordResponse(senderId, 'leak container task created') elif wordIs('~aipstats'): args = word.split() hostname = None port = None if len(args) > 1: hostname = args[1] if len(args) > 2: port = int(args[2]) # make sure pstats is enabled simbase.wantStats = 1 Task.TaskManager.pStatsTasks = 1 result = simbase.createStats(hostname, port) connectionName = '%s' % hostname if port is not None: connectionName += ':%s' % port if result: response = 'connected AI pstats to %s' % connectionName else: response = 'could not connect AI pstats to %s' % connectionName self.down_setMagicWordResponse(senderId, response) elif wordIs('~aiprofile'): args = word.split() if len(args) > 1: num = int(args[1]) else: num = 5 session = taskMgr.getProfileSession('~aiprofile') session.setLogAfterProfile(True) taskMgr.profileFrames(num, session) self.down_setMagicWordResponse(senderId, 'profiling %s AI frames...' % num) elif wordIs('~aiframeprofile'): args = word.split() wasOn = bool(taskMgr.getProfileFrames()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileFrames(setting) self.down_setMagicWordResponse( senderId, 'AI frame profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~aitaskprofile'): args = word.split() wasOn = bool(taskMgr.getProfileTasks()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileTasks(setting) self.down_setMagicWordResponse( senderId, 'AI task profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~aitaskspikethreshold'): from direct.task.TaskProfiler import TaskProfiler args = word.split() if len(args) > 1: threshold = float(args[1]) response = 'AI task spike threshold set to %ss' % threshold else: threshold = TaskProfiler.GetDefaultSpikeThreshold() response = 'AI task spike threshold reset to %ss' % threshold TaskProfiler.SetSpikeThreshold(threshold) self.down_setMagicWordResponse(senderId, response) elif wordIs('~ailogtaskprofiles'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.logTaskProfiles(name) response = 'logged AI task profiles%s' % choice( name, ' for %s' % name, '') self.down_setMagicWordResponse(senderId, response) elif wordIs('~aitaskprofileflush'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.flushTaskProfiles(name) response = 'flushed AI task profiles%s' % choice( name, ' for %s' % name, '') self.down_setMagicWordResponse(senderId, response) elif wordIs('~aiobjectcount'): simbase.air.printObjectCount() self.down_setMagicWordResponse( senderId, 'logging AI distributed object count...') elif wordIs('~aitaskmgr'): print(taskMgr) self.down_setMagicWordResponse(senderId, 'logging AI taskMgr...') elif wordIs('~aijobmgr'): print(jobMgr) self.down_setMagicWordResponse(senderId, 'logging AI jobMgr...') elif wordIs('~aijobtime'): args = word.split() if len(args) > 1: time = float(args[1]) else: time = None response = '' if time is None: time = jobMgr.getDefaultTimeslice() time = time * 1000. response = 'reset AI jobMgr timeslice to %s ms' % time else: response = 'set AI jobMgr timeslice to %s ms' % time time = time / 1000. jobMgr.setTimeslice(time) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aidetectleaks'): started = self.air.startLeakDetector() self.down_setMagicWordResponse( senderId, choice( started, 'AI leak detector started', 'AI leak detector already started', )) elif wordIs('~aitaskthreshold'): args = word.split() if len(args) > 1.: threshold = float(args[1]) else: threshold = None response = '' if threshold is None: threshold = taskMgr.DefTaskDurationWarningThreshold response = 'reset AI task duration warning threshold to %s' % threshold else: response = 'set AI task duration warning threshold to %s' % threshold taskMgr.setTaskDurationWarningThreshold(threshold) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aimessenger'): print(messenger) self.down_setMagicWordResponse(senderId, 'logging AI messenger...') elif wordIs('~requestdeleted'): requestDeletedDOs = self.air.getRequestDeletedDOs() response = '%s requestDeleted AI objects%s' % ( len(requestDeletedDOs), choice(len(requestDeletedDOs), ', logging...', '')) s = '~requestDeleted: [' for do, age in requestDeletedDOs: s += '[%s, %s]' % (do.__class__.__name__, age) s += ']' self.notify.info(s) if len(requestDeletedDOs): response += '\noldest: %s, %s' % ( requestDeletedDOs[0][0].__class__.__name__, formatTimeCompact(requestDeletedDOs[0][1])) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aigptc'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcJob = self.cr.leakDetector.getPathsToContainers( '~aigptc', args[1], Functor(self._handleGPTCfinished, senderId, args[1])) else: self.down_setMagicWordResponse(senderId, 'error') elif wordIs('~aigptcn'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcnJob = self.cr.leakDetector.getPathsToContainersNamed( '~aigptcn', args[1], Functor(self._handleGPTCNfinished, senderId, args[1])) else: self.down_setMagicWordResponse(senderId, 'error') else: # The word is not an AI-side magic word. If the sender is # different than the target avatar, then pass the magic # word down to the target client-side MagicWordManager to # execute a client-side magic word. # MPG this gets done in child class #if (senderId != av.doId): # self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId]) return 0 return 1
def doMagicWord(self, word, avId, zoneId): wordIs = self.getWordIs(word) print word if wordIs('~oobe'): base.oobe() elif wordIs('~oobeCull'): base.oobeCull() elif wordIs('~tex'): self.doTex(word) elif wordIs('~texmem'): base.toggleTexMem() elif wordIs('~verts'): base.toggleShowVertices() elif wordIs('~wire'): base.toggleWireframe() elif wordIs('~stereo'): base.toggleStereo() elif wordIs('~showfont'): self.showfont(word[9:]) elif wordIs('~hidefont'): self.hidefont() elif wordIs('~guiPopup'): self.toggleGuiPopup() elif wordIs('~showCS') or wordIs('~showcs'): bitmask = self.getCSBitmask(word[7:]) render.showCS(bitmask) self.csShown = 1 elif wordIs('~hideCS') or wordIs('~hidecs'): bitmask = self.getCSBitmask(word[7:]) render.hideCS(bitmask) self.csShown = 0 elif wordIs('~cs'): bitmask = self.getCSBitmask(word[3:]) if self.csShown: render.hideCS(bitmask) self.csShown = 0 else: render.showCS(bitmask) self.csShown = 1 elif wordIs('~showShadowCollisions'): self.showShadowCollisions() elif wordIs('~hideShadowCollisions'): self.hideShadowCollisions() elif wordIs('~showCollisions'): self.showCollisions() elif wordIs('~hideCollisions'): self.hideCollisions() elif wordIs('~showCameraCollisions'): self.showCameraCollisions() elif wordIs('~hideCameraCollisions'): self.hideCameraCollisions() elif wordIs('~collidespam'): n = Notify.ptr().getCategory(':collide') if hasattr(self, '_collideSpamSeverity'): n.setSeverity(self._collideSpamSeverity) del self._collideSpamSeverity else: self._collideSpamSeverity = n.getSeverity() n.setSeverity(NSSpam) elif wordIs('~notify'): args = word.split() n = Notify.ptr().getCategory(args[1]) n.setSeverity({ 'error': NSError, 'warning': NSWarning, 'info': NSInfo, 'debug': NSDebug, 'spam': NSSpam }[args[2]]) elif wordIs('~stress'): factor = word[7:] if factor: factor = float(factor) LOD.setStressFactor(factor) response = 'Set LOD stress factor to %s' % factor else: factor = LOD.getStressFactor() response = 'LOD stress factor is %s' % factor self.setMagicWordResponse(response) elif wordIs('~for'): self.forAnother(word, avId, zoneId) elif wordIs('~badname'): word = '~for %s ~badname' % word[9:] print 'word is %s' % word self.forAnother(word, avId, zoneId) elif wordIs('~avId'): self.setMagicWordResponse(str(localAvatar.doId)) elif wordIs('~doId'): name = string.strip(word[6:]) objs = self.identifyDistributedObjects(name) if len(objs) == 0: response = '%s is unknown.' % name else: response = '' for (name, obj) in objs: response += '\n%s %d' % (name, obj.doId) response = response[1:] self.setMagicWordResponse(response) elif wordIs('~exec'): ChatManager = ChatManager import otp.chat ChatManager.ChatManager.execChat = 1 elif wordIs('~run'): self.toggleRun() elif wordIs('~runFaster'): if config.GetBool('want-running', 1): args = word.split() if len(args) > 1: base.debugRunningMultiplier = float(args[1]) else: base.debugRunningMultiplier = 10 inputState.set('debugRunning', True) elif wordIs('~who'): avIds = [] for av in Avatar.Avatar.ActiveAvatars: if hasattr(av, 'getFriendsList'): avIds.append(av.doId) continue self.d_setWho(avIds) elif wordIs('~sync'): tm = self.cr.timeManager if tm == None: response = 'No TimeManager.' self.setMagicWordResponse(response) else: tm.extraSkew = 0.0 skew = string.strip(word[5:]) if skew != '': tm.extraSkew = float(skew) globalClockDelta.clear() tm.handleHotkey() elif wordIs('~period'): timeout = string.strip(word[7:]) if timeout != '': seconds = int(timeout) self.cr.stopPeriodTimer() self.cr.resetPeriodTimer(seconds) self.cr.startPeriodTimer() if self.cr.periodTimerExpired: response = 'Period timer has expired.' elif self.cr.periodTimerStarted: elapsed = globalClock.getFrameTime( ) - self.cr.periodTimerStarted secondsRemaining = self.cr.periodTimerSecondsRemaining - elapsed response = 'Period timer expires in %s seconds.' % int( secondsRemaining) else: response = 'Period timer not set.' self.setMagicWordResponse(response) elif wordIs('~DIRECT'): args = word.split() fEnableLight = 0 if len(args) > 1: if direct and args[1] == 'CAM': direct.enable() taskMgr.removeTasksMatching('updateSmartCamera*') camera.wrtReparentTo(render) direct.cameraControl.enableMouseFly() self.setMagicWordResponse('Enabled DIRECT camera') return None elif args[1] == 'LIGHT': fEnableLight = 1 base.startTk() DirectSession = DirectSession import direct.directtools if fEnableLight: direct.enableLight() else: direct.enable() self.setMagicWordResponse('Enabled DIRECT') elif wordIs('~TT'): if not direct: return None args = word.split() if len(args) > 1: if args[1] == 'CAM': direct.cameraControl.disableMouseFly() camera.wrtReparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() self.setMagicWordResponse('Disabled DIRECT camera') return None direct.disable() camera.wrtReparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() self.setMagicWordResponse('Disabled DIRECT') elif wordIs('~net'): if self.cr.networkPlugPulled(): self.cr.restoreNetworkPlug() self.cr.startHeartbeat() response = 'Network restored.' else: self.cr.pullNetworkPlug() self.cr.stopHeartbeat() response = 'Network disconnected.' self.setMagicWordResponse(response) elif wordIs('~disconnect'): base.cr.distributedDistrict.sendUpdate('broadcastMessage') elif wordIs('~model'): args = word.split() path = args[1] model = loader.loadModel(path) model.reparentTo(localAvatar) model.wrtReparentTo(render) self.setMagicWordResponse('loaded %s' % path) elif wordIs('~axis'): axis = loader.loadModel('models/misc/xyzAxis.bam') axis.reparentTo(render) axis.setPos(base.localAvatar, 0, 0, 0) axis.setHpr(render, 0, 0, 0) axis10 = loader.loadModel('models/misc/xyzAxis.bam') axis10.reparentTo(render) axis10.setPos(base.localAvatar, 0, 0, 0) axis10.setScale(10) axis10.setHpr(render, 0, 0, 0) axis10.setColorScale(1, 1, 1, 0.40000000000000002) axis10.setTransparency(1) elif wordIs('~clearAxes') or wordIs('~clearAxis'): render.findAllMatches('**/xyzAxis.egg').detach() elif wordIs('~myAxis'): if hasattr(self, 'myAxis'): self.myAxis.detachNode() del self.myAxis else: self.myAxis = loader.loadModel('models/misc/xyzAxis.bam') self.myAxis.reparentTo(localAvatar) elif wordIs('~osd'): onScreenDebug.enabled = not (onScreenDebug.enabled) elif wordIs('~osdScale'): args = word.split() defScale = 0.050000000000000003 if len(args) > 1: scale = float(args[1]) else: scale = 1.0 onScreenDebug.onScreenText.setScale(defScale * scale) elif wordIs('~osdTaskMgr'): if taskMgr.osdEnabled(): taskMgr.stopOsd() elif not onScreenDebug.enabled: onScreenDebug.enabled = True taskMgr.startOsd() elif wordIs('~fps'): self.doFps(word, avId, zoneId) elif wordIs('~sleep'): args = word.split() if len(args) > 1: s = float(args[1]) base.setSleep(s) response = 'sleeping %s' % s else: base.setSleep(0.0) response = 'not sleeping' self.setMagicWordResponse(response) elif wordIs('~objects'): args = word.split() ObjectReport = ObjectReport import direct.showbase report = ObjectReport.ObjectReport('client ~objects') if 'all' in args: self.notify.info('printing full object set...') report.getObjectPool().printObjsByType( printReferrers='ref' in args) if hasattr(self, 'baselineObjReport'): self.notify.info( 'calculating diff from baseline ObjectReport...') self.lastDiff = self.baselineObjReport.diff(report) if not 'diff' in args: pass self.lastDiff.printOut(full='dif' in args) if 'baseline' in args or not hasattr(self, 'baselineObjReport'): self.notify.info('recording baseline ObjectReport...') if hasattr(self, 'baselineObjReport'): self.baselineObjReport.destroy() self.baselineObjReport = report self.setMagicWordResponse('objects logged') elif wordIs('~objectcount'): def handleObjectCountDone(objectCount): self.setMagicWordResponse('object count logged') oc = ObjectCount('~objectcount', doneCallback=handleObjectCountDone) elif wordIs('~objecthg'): import gc as gc objs = gc.get_objects() type2count = {} for obj in objs: tn = safeTypeName(obj) type2count.setdefault(tn, 0) type2count[tn] += 1 count2type = invertDictLossless(type2count) counts = count2type.keys() counts.sort() counts.reverse() for count in counts: print '%s: %s' % (count, count2type[count]) self.setMagicWordResponse('~aiobjecthg complete') elif wordIs('~containers'): args = word.split() limit = 30 if 'full' in args: limit = None ContainerReport.ContainerReport('~containers', log=True, limit=limit, threaded=True) elif wordIs('~garbage'): args = word.split() full = 'full' in args safeMode = 'safe' in args delOnly = 'delonly' in args GarbageReport.GarbageLogger('~garbage', fullReport=full, threaded=True, safeMode=safeMode, delOnly=delOnly, doneCallback=self.garbageReportDone) elif wordIs('~guicreates'): base.printGuiCreates = True self.setMagicWordResponse('printing gui creation stacks') elif wordIs('~creategarbage'): GarbageReport._createGarbage() elif wordIs('~leakTask'): def leakTask(task): return task.cont taskMgr.add(leakTask, uniqueName('leakedTask')) leakTask = None elif wordIs('~leakmessage'): MessengerLeakDetector._leakMessengerObject() self.down_setMagicWordResponse(senderId, 'messenger leak object created') elif wordIs('~pstats'): args = word.split() hostname = None port = None if len(args) > 1: hostname = args[1] if len(args) > 2: port = int(args[2]) base.wantStats = 1 Task.TaskManager.pStatsTasks = 1 result = base.createStats(hostname, port) connectionName = '%s' % hostname if port is not None: connectionName += ':%s' % port if result: response = 'connected client pstats to %s' % connectionName else: response = 'could not connect pstats to %s' % connectionName self.setMagicWordResponse(response) elif wordIs('~profile'): args = word.split() if len(args) > 1: num = int(args[1]) else: num = 5 session = taskMgr.getProfileSession('~profile') session.setLogAfterProfile(True) taskMgr.profileFrames(num, session) self.setMagicWordResponse('profiling %s client frames...' % num) elif wordIs('~frameprofile'): args = word.split() wasOn = bool(taskMgr.getProfileFrames()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileFrames(setting) self.setMagicWordResponse( 'frame profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~taskprofile'): args = word.split() wasOn = bool(taskMgr.getProfileTasks()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileTasks(setting) self.setMagicWordResponse( 'task profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~taskspikethreshold'): args = word.split() if len(args) > 1: threshold = float(args[1]) response = 'task spike threshold set to %ss' % threshold else: threshold = TaskProfiler.GetDefaultSpikeThreshold() response = 'task spike threshold reset to %ss' % threshold TaskProfiler.SetSpikeThreshold(threshold) self.setMagicWordResponse(response) elif wordIs('~logtaskprofiles'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.logTaskProfiles(name) response = 'logged task profiles%s' % choice( name, ' for %s' % name, '') self.setMagicWordResponse(response) elif wordIs('~taskprofileflush'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.flushTaskProfiles(name) response = 'flushed AI task profiles%s' % choice( name, ' for %s' % name, '') self.setMagicWordResponse(response) elif wordIs('~dobjectcount'): base.cr.printObjectCount() self.setMagicWordResponse( 'logging client distributed object count...') elif wordIs('~taskmgr'): print taskMgr self.setMagicWordResponse('logging client taskMgr...') elif wordIs('~jobmgr'): print jobMgr self.setMagicWordResponse('logging client jobMgr...') elif wordIs('~jobtime'): args = word.split() if len(args) > 1: time = float(args[1]) else: time = None response = '' if time is None: time = jobMgr.getDefaultTimeslice() response = 'reset client jobMgr timeslice to %s ms' % time else: response = 'set client jobMgr timeslice to %s ms' % time time = time / 1000.0 jobMgr.setTimeslice(time) self.setMagicWordResponse(response) elif wordIs('~detectleaks'): started = self.cr.startLeakDetector() self.setMagicWordResponse( choice(started, 'leak detector started', 'leak detector already started')) elif wordIs('~taskthreshold'): args = word.split() if len(args) > 1.0: threshold = float(args[1]) else: threshold = None response = '' if threshold is None: threshold = taskMgr.DefTaskDurationWarningThreshold response = 'reset task duration warning threshold to %s' % threshold else: response = 'set task duration warning threshold to %s' % threshold taskMgr.setTaskDurationWarningThreshold(threshold) self.setMagicWordResponse(response) elif wordIs('~messenger'): print messenger self.setMagicWordResponse('logging client messenger...') elif wordIs('~clientcrash'): DelayedCall( Functor(self.notify.error, '~clientcrash: simulating a client crash')) elif wordIs('~badDelete'): doId = 0 while doId in base.cr.doId2do: doId += 1 DelayedCall( Functor(base.cr.deleteObjectLocation, ScratchPad(doId=doId), 1, 1)) self.setMagicWordResponse('doing bad delete') elif wordIs('~idTags'): messenger.send('nameTagShowAvId', []) base.idTags = 1 elif wordIs('~nameTags'): messenger.send('nameTagShowName', []) base.idTags = 0 elif wordIs('~hideNames'): if NametagGlobals.getMasterNametagsVisible(): NametagGlobals.setMasterNametagsVisible(0) else: NametagGlobals.setMasterNametagsVisible(1) elif wordIs('~hideGui'): if aspect2d.isHidden(): aspect2d.show() else: aspect2d.hide() elif wordIs('~flush'): base.cr.doDataCache.flush() base.cr.cache.flush() self.setMagicWordResponse('client object and data caches flushed') elif wordIs('~prof'): import time as time name = 'default' p = Point3() ts = time.time() for i in xrange(1000000): p.set(1, 2, 3) tf = time.time() dt = tf - ts response = 'prof(%s): %s secs' % (name, dt) print response self.setMagicWordResponse(response) elif wordIs('~gptc'): args = word.split() if len(args) > 1.0 and hasattr(self.cr, 'leakDetector'): gptcJob = self.cr.leakDetector.getPathsToContainers( '~gptc', args[1], Functor(self._handleGPTCfinished, args[1])) else: self.setMagicWordResponse('error') elif wordIs('~gptcn'): args = word.split() if len(args) > 1.0 and hasattr(self.cr, 'leakDetector'): gptcnJob = self.cr.leakDetector.getPathsToContainersNamed( '~gptcn', args[1], Functor(self._handleGPTCNfinished, args[1])) else: self.setMagicWordResponse('error') else: return 0 return 1
class TaskManager(): notify = directNotify.newCategory('TaskManager') extendedExceptions = False MaxEpochSpeed = 1.0 / 30.0 def __init__(self): self.mgr = AsyncTaskManager.getGlobalPtr() self.resumeFunc = None self.globalClock = self.mgr.getClock() self.stepping = False self.running = False self.destroyed = False self.fKeyboardInterrupt = False self.interruptCount = 0 self._frameProfileQueue = Queue() self._profileFrames = None self._frameProfiler = None self._profileTasks = None self._taskProfiler = None self._taskProfileInfo = ScratchPad(taskId=None, profiled=False, session=None) return def finalInit(self): from direct.fsm.StatePush import StateVar self._profileTasks = StateVar(False) self.setProfileTasks( ConfigVariableBool('profile-task-spikes', 0).getValue()) self._profileFrames = StateVar(False) self.setProfileFrames( ConfigVariableBool('profile-frames', 0).getValue()) def destroy(self): self.running = False self.notify.info('TaskManager.destroy()') self.destroyed = True self._frameProfileQueue.clear() self.mgr.cleanup() def setClock(self, clockObject): self.mgr.setClock(clockObject) self.globalClock = clockObject def invokeDefaultHandler(self, signalNumber, stackFrame): print '*** allowing mid-frame keyboard interrupt.' if signal: signal.signal(signal.SIGINT, signal.default_int_handler) raise KeyboardInterrupt def keyboardInterruptHandler(self, signalNumber, stackFrame): self.fKeyboardInterrupt = 1 self.interruptCount += 1 if self.interruptCount == 1: print '* interrupt by keyboard' else: if self.interruptCount == 2: print '** waiting for end of frame before interrupting...' signal.signal(signal.SIGINT, self.invokeDefaultHandler) def getCurrentTask(self): return Thread.getCurrentThread().getCurrentTask() def hasTaskChain(self, chainName): return self.mgr.findTaskChain(chainName) != None def setupTaskChain(self, chainName, numThreads=None, tickClock=None, threadPriority=None, frameBudget=None, frameSync=None, timeslicePriority=None): chain = self.mgr.makeTaskChain(chainName) if numThreads is not None: chain.setNumThreads(numThreads) if tickClock is not None: chain.setTickClock(tickClock) if threadPriority is not None: chain.setThreadPriority(threadPriority) if frameBudget is not None: chain.setFrameBudget(frameBudget) if frameSync is not None: chain.setFrameSync(frameSync) if timeslicePriority is not None: chain.setTimeslicePriority(timeslicePriority) return def hasTaskNamed(self, taskName): return bool(self.mgr.findTask(taskName)) def getTasksNamed(self, taskName): return self.__makeTaskList(self.mgr.findTasks(taskName)) def getTasksMatching(self, taskPattern): return self.__makeTaskList( self.mgr.findTasksMatching(GlobPattern(taskPattern))) def getAllTasks(self): return self.__makeTaskList(self.mgr.getTasks()) def getTasks(self): return self.__makeTaskList(self.mgr.getActiveTasks()) def getDoLaters(self): return self.__makeTaskList(self.mgr.getSleepingTasks()) def __makeTaskList(self, taskCollection): l = [] for i in range(taskCollection.getNumTasks()): l.append(taskCollection.getTask(i)) return l def doMethodLater(self, delayTime, funcOrTask, name, extraArgs=None, sort=None, priority=None, taskChain=None, uponDeath=None, appendTask=False, owner=None): if delayTime < 0: pass task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath) task.setDelay(delayTime) self.mgr.add(task) return task def add(self, funcOrTask, name=None, sort=None, extraArgs=None, priority=None, uponDeath=None, appendTask=False, taskChain=None, owner=None): task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath) self.mgr.add(task) return task def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath): if isinstance(funcOrTask, AsyncTask): task = funcOrTask else: if hasattr(funcOrTask, '__call__'): task = PythonTask(funcOrTask) else: self.notify.error( 'add: Tried to add a task that was not a Task or a func') if hasattr(task, 'setArgs'): if extraArgs is None: extraArgs = [] appendTask = True task.setArgs(extraArgs, appendTask) else: if extraArgs is not None: self.notify.error('Task %s does not accept arguments.' % repr(task)) if name is not None: task.setName(name) if priority is not None and sort is None: task.setSort(priority) else: if priority is not None: task.setPriority(priority) if sort is not None: task.setSort(sort) if taskChain is not None: task.setTaskChain(taskChain) if owner is not None: task.setOwner(owner) if uponDeath is not None: task.setUponDeath(uponDeath) return task def remove(self, taskOrName): if isinstance(taskOrName, types.StringTypes): tasks = self.mgr.findTasks(taskOrName) return self.mgr.remove(tasks) if isinstance(taskOrName, AsyncTask): return self.mgr.remove(taskOrName) if isinstance(taskOrName, types.ListType): for task in taskOrName: self.remove(task) else: self.notify.error('remove takes a string or a Task') def removeTasksMatching(self, taskPattern): tasks = self.mgr.findTasksMatching(GlobPattern(taskPattern)) return self.mgr.remove(tasks) def step(self): self.fKeyboardInterrupt = 0 self.interruptCount = 0 if signal: signal.signal(signal.SIGINT, self.keyboardInterruptHandler) startFrameTime = self.globalClock.getRealTime() self.mgr.poll() nextTaskTime = self.mgr.getNextWakeTime() self.doYield(startFrameTime, nextTaskTime) if signal: signal.signal(signal.SIGINT, signal.default_int_handler) if self.fKeyboardInterrupt: raise KeyboardInterrupt def run(self): t = self.globalClock.getFrameTime() timeDelta = t - self.globalClock.getRealTime() self.globalClock.setRealTime(t) messenger.send('resetClock', [timeDelta]) if self.resumeFunc != None: self.resumeFunc() if self.stepping: self.step() else: self.running = True while self.running: try: if len(self._frameProfileQueue): numFrames, session, callback = self._frameProfileQueue.pop( ) def _profileFunc(numFrames=numFrames): self._doProfiledFrames(numFrames) session.setFunc(_profileFunc) session.run() _profileFunc = None if callback: callback() session.release() else: self.step() except KeyboardInterrupt: self.stop() except SystemExit: self.stop() raise except IOError as ioError: code, message = self._unpackIOError(ioError) if code == 4: self.stop() else: raise except Exception as e: if self.extendedExceptions: self.stop() print_exc_plus() else: if ExceptionVarDump.wantStackDumpLog and ExceptionVarDump.dumpOnExceptionInit: ExceptionVarDump._varDump__print(e) raise except: if self.extendedExceptions: self.stop() print_exc_plus() else: raise self.mgr.stopThreads() return def _unpackIOError(self, ioError): try: code, message = ioError except: code = 0 message = ioError return (code, message) def stop(self): self.running = False def __tryReplaceTaskMethod(self, task, oldMethod, newFunction): if not isinstance(task, PythonTask): return 0 method = task.getFunction() if type(method) == types.MethodType: function = method.im_func else: function = method if function == oldMethod: newMethod = types.MethodType(newFunction, method.im_self, method.im_class) task.setFunction(newMethod) return 1 return 0 def replaceMethod(self, oldMethod, newFunction): numFound = 0 for task in self.getAllTasks(): numFound += self.__tryReplaceTaskMethod(task, oldMethod, newFunction) return numFound def popupControls(self): from direct.tkpanels import TaskManagerPanel return TaskManagerPanel.TaskManagerPanel(self) def getProfileSession(self, name=None): if name is None: name = 'taskMgrFrameProfile' from direct.showbase.ProfileSession import ProfileSession return ProfileSession(name) def profileFrames(self, num=None, session=None, callback=None): if num is None: num = 1 if session is None: session = self.getProfileSession() session.acquire() self._frameProfileQueue.push((num, session, callback)) return def _doProfiledFrames(self, numFrames): for i in xrange(numFrames): result = self.step() return result def getProfileFrames(self): return self._profileFrames.get() def getProfileFramesSV(self): return self._profileFrames def setProfileFrames(self, profileFrames): self._profileFrames.set(profileFrames) if not self._frameProfiler and profileFrames: from direct.task.FrameProfiler import FrameProfiler self._frameProfiler = FrameProfiler() def getProfileTasks(self): return self._profileTasks.get() def getProfileTasksSV(self): return self._profileTasks def setProfileTasks(self, profileTasks): self._profileTasks.set(profileTasks) if not self._taskProfiler and profileTasks: from direct.task.TaskProfiler import TaskProfiler self._taskProfiler = TaskProfiler() def logTaskProfiles(self, name=None): if self._taskProfiler: self._taskProfiler.logProfiles(name) def flushTaskProfiles(self, name=None): if self._taskProfiler: self._taskProfiler.flush(name) def _setProfileTask(self, task): if self._taskProfileInfo.session: self._taskProfileInfo.session.release() self._taskProfileInfo.session = None self._taskProfileInfo = ScratchPad(taskFunc=task.getFunction(), taskArgs=task.getArgs(), task=task, profiled=False, session=None) task.setFunction(self._profileTask) task.setArgs([self._taskProfileInfo], True) return def _profileTask(self, profileInfo, task): appendTask = False taskArgs = profileInfo.taskArgs if taskArgs and taskArgs[-1] == task: appendTask = True taskArgs = taskArgs[:-1] task.setArgs(taskArgs, appendTask) task.setFunction(profileInfo.taskFunc) from direct.showbase.ProfileSession import ProfileSession profileSession = ProfileSession( 'profiled-task-%s' % task.getName(), Functor(profileInfo.taskFunc, *profileInfo.taskArgs)) ret = profileSession.run() profileInfo.session = profileSession profileInfo.profiled = True return ret def _hasProfiledDesignatedTask(self): return self._taskProfileInfo.profiled def _getLastTaskProfileSession(self): return self._taskProfileInfo.session def _getRandomTask(self): now = globalClock.getFrameTime() avgFrameRate = globalClock.getAverageFrameRate() if avgFrameRate < 1e-05: avgFrameDur = 0.0 else: avgFrameDur = 1.0 / globalClock.getAverageFrameRate() next = now + avgFrameDur tasks = self.mgr.getTasks() i = random.randrange(tasks.getNumTasks()) task = tasks.getTask(i) while not isinstance(task, PythonTask) or task.getWakeTime() > next: tasks.removeTask(i) i = random.randrange(tasks.getNumTasks()) task = tasks.getTask(i) return task def __repr__(self): return str(self.mgr) def doYield(self, frameStartTime, nextScheduledTaskTime): pass def _runTests(self): pass
def setProfileTasks(self, profileTasks): self._profileTasks.set(profileTasks) if not self._taskProfiler and profileTasks: from direct.task.TaskProfiler import TaskProfiler self._taskProfiler = TaskProfiler()
def doMagicWord(self, word, avId, zoneId): wordIs = self.getWordIs(word) print word if wordIs("~oobe"): base.oobe() elif wordIs("~oobeCull"): base.oobeCull() elif wordIs("~tex"): self.doTex(word) elif wordIs("~texmem"): base.toggleTexMem() elif wordIs("~verts"): base.toggleShowVertices() elif wordIs("~wire"): base.toggleWireframe() elif wordIs("~stereo"): base.toggleStereo() elif wordIs("~showfont"): self.showfont(word[9:]) elif wordIs("~hidefont"): self.hidefont() elif wordIs("~guiPopup"): self.toggleGuiPopup() elif wordIs("~showCS") or wordIs("~showcs"): bitmask = self.getCSBitmask(word[7:]) render.showCS(bitmask) self.csShown = 1 elif wordIs("~hideCS") or wordIs("~hidecs"): bitmask = self.getCSBitmask(word[7:]) render.hideCS(bitmask) self.csShown = 0 elif wordIs("~cs"): # Toggle hide/show collision solids: # (Also a shorthand for ~hideCS and ~showCS). bitmask = self.getCSBitmask(word[3:]) if self.csShown: render.hideCS(bitmask) self.csShown = 0 else: render.showCS(bitmask) self.csShown = 1 elif wordIs("~showShadowCollisions"): self.showShadowCollisions() elif wordIs("~hideShadowCollisions"): self.hideShadowCollisions() elif wordIs("~showCollisions"): self.showCollisions() elif wordIs("~hideCollisions"): self.hideCollisions() elif wordIs("~showCameraCollisions"): self.showCameraCollisions() elif wordIs("~hideCameraCollisions"): self.hideCameraCollisions() elif wordIs("~collidespam"): n = Notify.ptr().getCategory(':collide') if hasattr(self, '_collideSpamSeverity'): n.setSeverity(self._collideSpamSeverity) del self._collideSpamSeverity else: self._collideSpamSeverity = n.getSeverity() n.setSeverity(NSSpam) elif wordIs("~notify"): args = word.split() n = Notify.ptr().getCategory(args[1]) n.setSeverity({ 'error': NSError, 'warning': NSWarning, 'info': NSInfo, 'debug': NSDebug, 'spam': NSSpam, }[args[2]]) # MPG we probably need generic versions of these #elif wordIs("~listen"): # base.localAvatar.garbleChat = 0 #elif wordIs("~nochat") or wordIs("~chat") or wordIs("~superchat"): # base.localAvatar.garbleChat = 1 elif wordIs("~stress"): factor = word[7:] if factor: factor = float(factor) LOD.setStressFactor(factor) response = "Set LOD stress factor to %s" % (factor) else: factor = LOD.getStressFactor() response = "LOD stress factor is %s" % (factor) self.setMagicWordResponse(response) elif wordIs("~for"): self.forAnother(word, avId, zoneId) elif wordIs("~badname"): # ~badname with an argument becomes ~for ... ~badname word = "~for %s ~badname" % (word[9:]) print "word is %s" % (word) self.forAnother(word, avId, zoneId) elif wordIs('~avId'): self.setMagicWordResponse(str(localAvatar.doId)) elif wordIs("~doId"): name = string.strip(word[6:]) objs = self.identifyDistributedObjects(name) if (len(objs) == 0): response = "%s is unknown." % (name) else: response = "" for name, obj in objs: response += "\n%s %d" % (name, obj.doId) response = response[1:] self.setMagicWordResponse(response) # MPG - need generic versions of these #elif wordIs("~collisions_on"): # base.localAvatar.collisionsOn() #elif wordIs("~collisions_off"): # base.localAvatar.collisionsOff() #elif wordIs('~addCameraPosition'): # base.localAvatar.addCameraPosition() #elif wordIs('~removeCameraPosition'): # base.localAvatar.removeCameraPosition() #elif wordIs('~printCameraPosition'): # base.localAvatar.printCameraPosition( # base.localAvatar.cameraIndex) #elif wordIs('~printCameraPositions'): # base.localAvatar.printCameraPositions() elif wordIs("~exec"): # Enable execChat. from otp.chat import ChatManager ChatManager.ChatManager.execChat = 1 elif wordIs("~run"): self.toggleRun() elif wordIs("~runFaster"): if (config.GetBool("want-running", 1)): args = word.split() if (len(args) > 1): base.debugRunningMultiplier = float(args[1]) else: base.debugRunningMultiplier = 10 inputState.set("debugRunning", True) elif wordIs("~who"): # Get all the nearby avIds and send them to the AI. avIds = [] for av in Avatar.Avatar.ActiveAvatars: # If the avatar has a friends list, it's probably a # real avatar and not an NPC. if hasattr(av, "getFriendsList"): avIds.append(av.doId) self.d_setWho(avIds) elif wordIs("~sync"): # Sync with the AI, like F6, but rather than accumulating # sync informatoin, throw away whatever information was # there from before. If a second parameter is supplied, # it is a number of seconds of temporary extra skew to # apply; the default is 0. tm = self.cr.timeManager if tm == None: response = "No TimeManager." self.setMagicWordResponse(response) else: tm.extraSkew = 0.0 skew = string.strip(word[5:]) if skew != "": tm.extraSkew = float(skew) globalClockDelta.clear() tm.handleHotkey() elif wordIs("~period"): # Reset the period timer to expire in the indicated number # of seconds, or with no parameter, report the number of # seconds remaining. timeout = string.strip(word[7:]) if timeout != "": seconds = int(timeout) self.cr.stopPeriodTimer() self.cr.resetPeriodTimer(seconds) self.cr.startPeriodTimer() # Now report the number of seconds remaining. if self.cr.periodTimerExpired: response = "Period timer has expired." elif self.cr.periodTimerStarted: elapsed = globalClock.getFrameTime( ) - self.cr.periodTimerStarted secondsRemaining = self.cr.periodTimerSecondsRemaining - elapsed response = "Period timer expires in %s seconds." % ( int(secondsRemaining)) else: response = "Period timer not set." self.setMagicWordResponse(response) elif wordIs("~DIRECT"): args = word.split() fEnableLight = 0 if len(args) > 1: if direct and (args[1] == 'CAM'): direct.enable() taskMgr.removeTasksMatching('updateSmartCamera*') camera.wrtReparentTo(render) direct.cameraControl.enableMouseFly() self.setMagicWordResponse("Enabled DIRECT camera") return elif args[1] == 'LIGHT': fEnableLight = 1 # Start up DIRECT base.startTk() from direct.directtools import DirectSession if fEnableLight: direct.enableLight() else: direct.enable() self.setMagicWordResponse("Enabled DIRECT") elif wordIs("~TT"): if not direct: return args = word.split() if len(args) > 1: if (args[1] == 'CAM'): direct.cameraControl.disableMouseFly() camera.wrtReparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() self.setMagicWordResponse("Disabled DIRECT camera") return # Return to toontown mode direct.disable() camera.wrtReparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() self.setMagicWordResponse("Disabled DIRECT") elif wordIs("~net"): # Simulate pulling or restoring the network plug. if self.cr.networkPlugPulled(): self.cr.restoreNetworkPlug() self.cr.startHeartbeat() response = "Network restored." else: self.cr.pullNetworkPlug() self.cr.stopHeartbeat() response = "Network disconnected." self.setMagicWordResponse(response) elif wordIs('~disconnect'): # force a simulated disconnect # you can also do this from the OTP webpage base.cr.distributedDistrict.sendUpdate('broadcastMessage') elif wordIs("~model"): # load a model into the scene graph at the location of localAvatar args = word.split() path = args[1] model = loader.loadModel(path) model.reparentTo(localAvatar) model.wrtReparentTo(render) self.setMagicWordResponse('loaded %s' % path) elif wordIs("~axis"): # Show a 10 foot and 100 foot axis at the spot of the avatar # axis aligned to render axis = loader.loadModel("models/misc/xyzAxis.bam") axis.reparentTo(render) axis.setPos(base.localAvatar, 0, 0, 0) axis.setHpr(render, 0, 0, 0) axis10 = loader.loadModel("models/misc/xyzAxis.bam") axis10.reparentTo(render) axis10.setPos(base.localAvatar, 0, 0, 0) axis10.setScale(10) axis10.setHpr(render, 0, 0, 0) axis10.setColorScale(1, 1, 1, 0.4) axis10.setTransparency(1) elif (wordIs("~clearAxes") or wordIs("~clearAxis")): # Remove the effects of ~axis calls render.findAllMatches("**/xyzAxis.egg").detach() elif wordIs("~myAxis"): if hasattr(self, 'myAxis'): self.myAxis.detachNode() del self.myAxis else: self.myAxis = loader.loadModel("models/misc/xyzAxis.bam") self.myAxis.reparentTo(localAvatar) elif (wordIs("~osd")): onScreenDebug.enabled = not onScreenDebug.enabled elif wordIs("~osdScale"): args = word.split() defScale = .05 if len(args) > 1: scale = float(args[1]) else: scale = 1. onScreenDebug.onScreenText.setScale(defScale * scale) elif wordIs('~osdTaskMgr'): if taskMgr.osdEnabled(): taskMgr.stopOsd() else: if not onScreenDebug.enabled: onScreenDebug.enabled = True taskMgr.startOsd() elif wordIs("~fps"): self.doFps(word, avId, zoneId) elif wordIs("~sleep"): args = word.split() if len(args) > 1: s = float(args[1]) base.setSleep(s) response = 'sleeping %s' % s else: base.setSleep(0.0) response = 'not sleeping' self.setMagicWordResponse(response) elif wordIs('~objects'): args = word.split() from direct.showbase import ObjectReport report = ObjectReport.ObjectReport('client ~objects') if 'all' in args: self.notify.info('printing full object set...') report.getObjectPool().printObjsByType( printReferrers='ref' in args) if hasattr(self, 'baselineObjReport'): self.notify.info( 'calculating diff from baseline ObjectReport...') self.lastDiff = self.baselineObjReport.diff(report) self.lastDiff.printOut(full=('diff' in args or 'dif' in args)) if 'baseline' in args or not hasattr(self, 'baselineObjReport'): self.notify.info('recording baseline ObjectReport...') if hasattr(self, 'baselineObjReport'): self.baselineObjReport.destroy() self.baselineObjReport = report self.setMagicWordResponse('objects logged') elif wordIs('~objecthg'): import gc objs = gc.get_objects() type2count = {} for obj in objs: tn = safeTypeName(obj) type2count.setdefault(tn, 0) type2count[tn] += 1 count2type = invertDictLossless(type2count) counts = count2type.keys() counts.sort() counts.reverse() for count in counts: print '%s: %s' % (count, count2type[count]) self.setMagicWordResponse('~aiobjecthg complete') elif wordIs('~containers'): args = word.split() limit = 30 if 'full' in args: limit = None ContainerReport.ContainerReport('~containers', log=True, limit=limit, threaded=True) elif wordIs('~garbage'): args = word.split() # it can take a LOOONG time to print out the garbage referrers and referents # by reference (as opposed to by number) full = 'full' in args safeMode = 'safe' in args delOnly = 'delonly' in args # This does a garbage collection and dumps the list of leaked (uncollectable) objects to the log. GarbageReport.GarbageLogger('~garbage', fullReport=full, threaded=True, safeMode=safeMode, delOnly=delOnly, doneCallback=self.garbageReportDone) # this is coming back from the AI #self.setMagicWordResponse('garbage logged') elif wordIs('~guicreates'): base.printGuiCreates = True self.setMagicWordResponse('printing gui creation stacks') elif wordIs("~creategarbage"): GarbageReport._createGarbage() # this is coming back from the AI #self.setMagicWordResponse(senderId, 'leaked garbage created') elif wordIs('~leakTask'): def leakTask(task): return task.cont taskMgr.add(leakTask, uniqueName('leakedTask')) leakTask = None # this is coming back from the AI #self.setMagicWordResponse(senderId, 'leaked task created') elif wordIs('~leakmessage'): MessengerLeakDetector._leakMessengerObject() self.down_setMagicWordResponse(senderId, 'messenger leak object created') elif wordIs('~pstats'): args = word.split() hostname = None port = None if len(args) > 1: hostname = args[1] if len(args) > 2: port = int(args[2]) # make sure pstats is enabled base.wantStats = 1 Task.TaskManager.pStatsTasks = 1 result = base.createStats(hostname, port) connectionName = '%s' % hostname if port is not None: connectionName += ':%s' % port if result: response = 'connected client pstats to %s' % connectionName else: response = 'could not connect pstats to %s' % connectionName self.setMagicWordResponse(response) elif wordIs('~profile'): args = word.split() if len(args) > 1: num = int(args[1]) else: num = 5 session = taskMgr.getProfileSession('~profile') session.setLogAfterProfile(True) taskMgr.profileFrames(num, session) self.setMagicWordResponse('profiling %s client frames...' % num) elif wordIs('~frameprofile'): args = word.split() wasOn = bool(taskMgr.getProfileFrames()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileFrames(setting) self.setMagicWordResponse( 'frame profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~taskprofile'): args = word.split() wasOn = bool(taskMgr.getProfileTasks()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileTasks(setting) self.setMagicWordResponse( 'task profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~taskspikethreshold'): args = word.split() if len(args) > 1: threshold = float(args[1]) response = 'task spike threshold set to %ss' % threshold else: threshold = TaskProfiler.GetDefaultSpikeThreshold() response = 'task spike threshold reset to %ss' % threshold TaskProfiler.SetSpikeThreshold(threshold) self.setMagicWordResponse(response) elif wordIs('~logtaskprofiles'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.logTaskProfiles(name) response = 'logged task profiles%s' % choice( name, ' for %s' % name, '') self.setMagicWordResponse(response) elif wordIs('~taskprofileflush'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.flushTaskProfiles(name) response = 'flushed AI task profiles%s' % choice( name, ' for %s' % name, '') self.setMagicWordResponse(response) elif wordIs('~objectcount'): base.cr.printObjectCount() self.setMagicWordResponse( 'logging client distributed object count...') elif wordIs('~taskmgr'): print taskMgr self.setMagicWordResponse('logging client taskMgr...') elif wordIs('~jobmgr'): print jobMgr self.setMagicWordResponse('logging client jobMgr...') elif wordIs('~jobtime'): args = word.split() if len(args) > 1: time = float(args[1]) else: time = None response = '' if time is None: time = jobMgr.getDefaultTimeslice() response = 'reset client jobMgr timeslice to %s ms' % time else: response = 'set client jobMgr timeslice to %s ms' % time time = time / 1000. jobMgr.setTimeslice(time) self.setMagicWordResponse(response) elif wordIs('~detectleaks'): started = self.cr.startLeakDetector() self.setMagicWordResponse( choice( started, 'leak detector started', 'leak detector already started', )) elif wordIs('~taskthreshold'): args = word.split() if len(args) > 1.: threshold = float(args[1]) else: threshold = None response = '' if threshold is None: threshold = taskMgr.DefTaskDurationWarningThreshold response = 'reset task duration warning threshold to %s' % threshold else: response = 'set task duration warning threshold to %s' % threshold taskMgr.setTaskDurationWarningThreshold(threshold) self.setMagicWordResponse(response) elif wordIs('~messenger'): print messenger self.setMagicWordResponse('logging client messenger...') elif wordIs('~clientcrash'): # if we call notify.error directly, the magic word mgr will catch it # self.notify.error doesn't seem to work either DelayedCall( Functor(self.notify.error, '~clientcrash: simulating a client crash')) elif wordIs('~badDelete'): doId = 0 while doId in base.cr.doId2do: doId += 1 # location (0,0) is special, pass in (1,1) # deleteObjectLocation expects a DO, pass in a ScratchPad instead # we must delay the call because magicWordMgr is in a big try/except block DelayedCall( Functor(base.cr.deleteObjectLocation, ScratchPad(doId=doId), 1, 1)) self.setMagicWordResponse('doing bad delete') elif wordIs("~idTags"): messenger.send('nameTagShowAvId', []) base.idTags = 1 elif wordIs("~nameTags"): messenger.send('nameTagShowName', []) base.idTags = 0 elif wordIs("~hideNames"): # note do ~hideNames before ~hideGui if you want both off if NametagGlobals.getMasterNametagsVisible(): NametagGlobals.setMasterNametagsVisible(0) else: NametagGlobals.setMasterNametagsVisible(1) elif wordIs("~hideGui"): if aspect2d.isHidden(): aspect2d.show() else: aspect2d.hide() elif wordIs('~flush'): base.cr.doDataCache.flush() base.cr.cache.flush() self.setMagicWordResponse('client object and data caches flushed') elif wordIs('~prof'): import time ### set up ### name = 'default' p = Point3() ############## ts = time.time() for i in xrange(1000000): ### code to be timed ### p.set(1, 2, 3) ######################## tf = time.time() dt = tf - ts response = 'prof(%s): %s secs' % (name, dt) print response self.setMagicWordResponse(response) elif wordIs('~gptc'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcJob = self.cr.leakDetector.getPathsToContainers( '~gptc', args[1], Functor(self._handleGPTCfinished, args[1])) else: self.setMagicWordResponse('error') elif wordIs('~gptcn'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcnJob = self.cr.leakDetector.getPathsToContainersNamed( '~gptcn', args[1], Functor(self._handleGPTCNfinished, args[1])) else: self.setMagicWordResponse('error') else: # Not a magic word I know! return 0 return 1
def setProfileTasks(self, profileTasks): self._profileTasks.set(profileTasks) if not self._taskProfiler and profileTasks: from direct.task.TaskProfiler import TaskProfiler self._taskProfiler = TaskProfiler()
class TaskManager(): __module__ = __name__ notify = directNotify.newCategory('TaskManager') extendedExceptions = False MaxEpochSpeed = 1.0 / 30.0 def __init__(self): self.mgr = AsyncTaskManager.getGlobalPtr() self.resumeFunc = None self.globalClock = self.mgr.getClock() self.stepping = False self.running = False self.destroyed = False self.fKeyboardInterrupt = False self.interruptCount = 0 self._frameProfileQueue = Queue() self._profileFrames = None self._frameProfiler = None self._profileTasks = None self._taskProfiler = None self._taskProfileInfo = ScratchPad(taskId=None, profiled=False, session=None) return def finalInit(self): from direct.fsm.StatePush import StateVar self._profileTasks = StateVar(False) self.setProfileTasks(ConfigVariableBool('profile-task-spikes', 0).getValue()) self._profileFrames = StateVar(False) self.setProfileFrames(ConfigVariableBool('profile-frames', 0).getValue()) def destroy(self): self.notify.info('TaskManager.destroy()') self.destroyed = True self._frameProfileQueue.clear() self.mgr.cleanup() def setClock(self, clockObject): self.mgr.setClock(clockObject) self.globalClock = clockObject def invokeDefaultHandler(self, signalNumber, stackFrame): print '*** allowing mid-frame keyboard interrupt.' signal.signal(signal.SIGINT, signal.default_int_handler) raise KeyboardInterrupt def keyboardInterruptHandler(self, signalNumber, stackFrame): self.fKeyboardInterrupt = 1 self.interruptCount += 1 if self.interruptCount == 1: print '* interrupt by keyboard' elif self.interruptCount == 2: print '** waiting for end of frame before interrupting...' signal.signal(signal.SIGINT, self.invokeDefaultHandler) def getCurrentTask(self): return Thread.getCurrentThread().getCurrentTask() def hasTaskChain(self, chainName): return self.mgr.findTaskChain(chainName) != None def setupTaskChain(self, chainName, numThreads = None, tickClock = None, threadPriority = None, frameBudget = None, frameSync = None, timeslicePriority = None): chain = self.mgr.makeTaskChain(chainName) if numThreads is not None: chain.setNumThreads(numThreads) if tickClock is not None: chain.setTickClock(tickClock) if threadPriority is not None: chain.setThreadPriority(threadPriority) if frameBudget is not None: chain.setFrameBudget(frameBudget) if frameSync is not None: chain.setFrameSync(frameSync) if timeslicePriority is not None: chain.setTimeslicePriority(timeslicePriority) return def hasTaskNamed(self, taskName): return bool(self.mgr.findTask(taskName)) def getTasksNamed(self, taskName): return self.__makeTaskList(self.mgr.findTasks(taskName)) def getTasksMatching(self, taskPattern): return self.__makeTaskList(self.mgr.findTasksMatching(GlobPattern(taskPattern))) def getAllTasks(self): return self.__makeTaskList(self.mgr.getTasks()) def getTasks(self): return self.__makeTaskList(self.mgr.getActiveTasks()) def getDoLaters(self): return self.__makeTaskList(self.mgr.getSleepingTasks()) def __makeTaskList(self, taskCollection): l = [] for i in range(taskCollection.getNumTasks()): l.append(taskCollection.getTask(i)) return l def doMethodLater(self, delayTime, funcOrTask, name, extraArgs = None, sort = None, priority = None, taskChain = None, uponDeath = None, appendTask = False, owner = None): if delayTime < 0: pass task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath) task.setDelay(delayTime) self.mgr.add(task) return task def add(self, funcOrTask, name = None, sort = None, extraArgs = None, priority = None, uponDeath = None, appendTask = False, taskChain = None, owner = None): task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath) self.mgr.add(task) return task def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath): if isinstance(funcOrTask, AsyncTask): task = funcOrTask elif hasattr(funcOrTask, '__call__'): task = PythonTask(funcOrTask) else: self.notify.error('add: Tried to add a task that was not a Task or a func') if hasattr(task, 'setArgs'): if extraArgs is None: extraArgs = [] appendTask = True task.setArgs(extraArgs, appendTask) elif extraArgs is not None: self.notify.error('Task %s does not accept arguments.' % repr(task)) if name is not None: task.setName(name) if priority is not None and sort is None: task.setSort(priority) else: if priority is not None: task.setPriority(priority) if sort is not None: task.setSort(sort) if taskChain is not None: task.setTaskChain(taskChain) if owner is not None: task.setOwner(owner) if uponDeath is not None: task.setUponDeath(uponDeath) return task def remove(self, taskOrName): if isinstance(taskOrName, types.StringTypes): tasks = self.mgr.findTasks(taskOrName) return self.mgr.remove(tasks) elif isinstance(taskOrName, AsyncTask): return self.mgr.remove(taskOrName) elif isinstance(taskOrName, types.ListType): for task in taskOrName: self.remove(task) else: self.notify.error('remove takes a string or a Task') def removeTasksMatching(self, taskPattern): tasks = self.mgr.findTasksMatching(GlobPattern(taskPattern)) return self.mgr.remove(tasks) def step(self): self.fKeyboardInterrupt = 0 self.interruptCount = 0 signal.signal(signal.SIGINT, self.keyboardInterruptHandler) startFrameTime = self.globalClock.getRealTime() self.mgr.poll() nextTaskTime = self.mgr.getNextWakeTime() self.doYield(startFrameTime, nextTaskTime) signal.signal(signal.SIGINT, signal.default_int_handler) if self.fKeyboardInterrupt: raise KeyboardInterrupt def run(self): t = self.globalClock.getFrameTime() timeDelta = t - self.globalClock.getRealTime() self.globalClock.setRealTime(t) messenger.send('resetClock', [timeDelta]) if self.resumeFunc != None: self.resumeFunc() if self.stepping: self.step() else: self.running = True while self.running: try: if len(self._frameProfileQueue): numFrames, session, callback = self._frameProfileQueue.pop() def _profileFunc(numFrames = numFrames): self._doProfiledFrames(numFrames) session.setFunc(_profileFunc) session.run() _profileFunc = None if callback: callback() session.release() else: self.step() except KeyboardInterrupt: self.stop() except IOError as ioError: code, message = self._unpackIOError(ioError) if code == 4: self.stop() else: raise except Exception as e: if self.extendedExceptions: self.stop() print_exc_plus() else: if ExceptionVarDump.wantStackDumpLog and ExceptionVarDump.dumpOnExceptionInit: ExceptionVarDump._varDump__print(e) raise except: if self.extendedExceptions: self.stop() print_exc_plus() else: raise self.mgr.stopThreads() return def _unpackIOError(self, ioError): try: code, message = ioError except: code = 0 message = ioError return (code, message) def stop(self): self.running = False def __tryReplaceTaskMethod(self, task, oldMethod, newFunction): if not isinstance(task, PythonTask): return 0 method = task.getFunction() if type(method) == types.MethodType: function = method.im_func else: function = method if function == oldMethod: import new newMethod = new.instancemethod(newFunction, method.im_self, method.im_class) task.setFunction(newMethod) return 1 return 0 def replaceMethod(self, oldMethod, newFunction): numFound = 0 for task in self.getAllTasks(): numFound += self.__tryReplaceTaskMethod(task, oldMethod, newFunction) return numFound def popupControls(self): from direct.tkpanels import TaskManagerPanel return TaskManagerPanel.TaskManagerPanel(self) def getProfileSession(self, name = None): if name is None: name = 'taskMgrFrameProfile' from direct.showbase.ProfileSession import ProfileSession return ProfileSession(name) def profileFrames(self, num = None, session = None, callback = None): if num is None: num = 1 if session is None: session = self.getProfileSession() session.acquire() self._frameProfileQueue.push((num, session, callback)) return def _doProfiledFrames(self, numFrames): for i in xrange(numFrames): result = self.step() return result def getProfileFrames(self): return self._profileFrames.get() def getProfileFramesSV(self): return self._profileFrames def setProfileFrames(self, profileFrames): self._profileFrames.set(profileFrames) if not self._frameProfiler and profileFrames: from direct.task.FrameProfiler import FrameProfiler self._frameProfiler = FrameProfiler() def getProfileTasks(self): return self._profileTasks.get() def getProfileTasksSV(self): return self._profileTasks def setProfileTasks(self, profileTasks): self._profileTasks.set(profileTasks) if not self._taskProfiler and profileTasks: from direct.task.TaskProfiler import TaskProfiler self._taskProfiler = TaskProfiler() def logTaskProfiles(self, name = None): if self._taskProfiler: self._taskProfiler.logProfiles(name) def flushTaskProfiles(self, name = None): if self._taskProfiler: self._taskProfiler.flush(name) def _setProfileTask(self, task): if self._taskProfileInfo.session: self._taskProfileInfo.session.release() self._taskProfileInfo.session = None self._taskProfileInfo = ScratchPad(taskFunc=task.getFunction(), taskArgs=task.getArgs(), task=task, profiled=False, session=None) task.setFunction(self._profileTask) task.setArgs([self._taskProfileInfo], True) return def _profileTask(self, profileInfo, task): appendTask = False taskArgs = profileInfo.taskArgs if taskArgs and taskArgs[-1] == task: appendTask = True taskArgs = taskArgs[:-1] task.setArgs(taskArgs, appendTask) task.setFunction(profileInfo.taskFunc) from direct.showbase.ProfileSession import ProfileSession profileSession = ProfileSession('profiled-task-%s' % task.getName(), Functor(profileInfo.taskFunc, *profileInfo.taskArgs)) ret = profileSession.run() profileInfo.session = profileSession profileInfo.profiled = True return ret def _hasProfiledDesignatedTask(self): return self._taskProfileInfo.profiled def _getLastTaskProfileSession(self): return self._taskProfileInfo.session def _getRandomTask(self): now = globalClock.getFrameTime() avgFrameRate = globalClock.getAverageFrameRate() if avgFrameRate < 1e-05: avgFrameDur = 0.0 else: avgFrameDur = 1.0 / globalClock.getAverageFrameRate() next = now + avgFrameDur tasks = self.mgr.getTasks() i = random.randrange(tasks.getNumTasks()) task = tasks.getTask(i) while not isinstance(task, PythonTask) or task.getWakeTime() > next: tasks.removeTask(i) i = random.randrange(tasks.getNumTasks()) task = tasks.getTask(i) return task def __repr__(self): return str(self.mgr) def doYield(self, frameStartTime, nextScheduledTaskTime): pass def _runTests(self): pass# decompiled 0 files: 0 okay, 1 failed, 0 verify failed