from direct.showbase.DirectObject import DirectObject from otp.avatar.DistributedPlayer import DistributedPlayer from direct.task.Task import Task class TelemetryLimiter(DirectObject): TaskName = 'TelemetryLimiterEnforce' LeakDetectEventName = 'telemetryLimiter' def __init__(self): self._objs = {} self._task = taskMgr.add(self._enforceLimits, self.TaskName, priority=40) def destroy(self): taskMgr.remove(self._task) del self._objs def getNumObjs(self): return len(self._objs) def addObj(self, obj): id = obj.getTelemetryLimiterId() self._objs[id] = obj self.accept(self._getDummyEventName(obj), self._dummyEventHandler) if __astron__: def hasObj(self, obj): id = obj.getTelemetryLimiterId() return id in self._objs def _getDummyEventName(self, obj): return '%s-%s-%s-%s' % (self.LeakDetectEventName, obj.getTelemetryLimiterId(), id(obj), obj.__class__.__name__) def _dummyEventHandler(self, *args, **kargs): pass def removeObj(self, obj): id = obj.getTelemetryLimiterId() self._objs.pop(id) self.ignore(self._getDummyEventName(obj)) def _enforceLimits(self, task = None): for obj in self._objs.values(): obj.enforceTelemetryLimits() return Task.cont class TelemetryLimit: def __call__(self, obj): pass class RotationLimitToH(TelemetryLimit): def __init__(self, pConst = 0.0, rConst = 0.0): self._pConst = pConst self._rConst = rConst def __call__(self, obj): obj.setHpr(obj.getH(), self._pConst, self._rConst) class TLNull: def __init__(self, *limits): pass def destroy(self): pass class TLGatherAllAvs(DirectObject): def __init__(self, name, *limits): self._name = name self._avs = {} self._limits = makeList(limits) self._avId2limits = {} avs = base.cr.doFindAllInstances(DistributedPlayer) for av in avs: self._handlePlayerArrive(av) self.accept(DistributedPlayer.GetPlayerGenerateEvent(), self._handlePlayerArrive) if __astron__: self.accept(DistributedPlayer.GetPlayerDeleteEvent(), self._handlePlayerLeave) else: self.accept(DistributedPlayer.GetPlayerNetworkDeleteEvent(), self._handlePlayerLeave) def _handlePlayerArrive(self, av): if av is not localAvatar: self._avs[av.doId] = av limitList = [] for limit in self._limits: l = limit() limitList.append(l) av.addTelemetryLimit(l) self._avId2limits[av.doId] = limitList base.cr.telemetryLimiter.addObj(av) if __astron__: def _handlePlayerLeave(self, av): if av is not localAvatar and base.cr.telemetryLimiter.hasObj(av) and av.doId in self._avId2limits: base.cr.telemetryLimiter.removeObj(av) for limit in self._avId2limits[av.doId]: av.removeTelemetryLimit(limit) del self._avId2limits[av.doId] if av.doId in self._avs: del self._avs[av.doId] else: def _handlePlayerLeave(self, av): if av is not localAvatar: base.cr.telemetryLimiter.removeObj(av) for limit in self._avId2limits[av.doId]: av.removeTelemetryLimit(limit) del self._avId2limits[av.doId] del self._avs[av.doId] def destroy(self): self.ignoreAll() while len(self._avs): self._handlePlayerLeave(list(self._avs.values())[0]) del self._avs del self._limits del self._avId2limits