Some related topics :
discourse.panda3d.org/viewtopic.php?t=2579
discourse.panda3d.org/viewtopic.php?t=2116
I took different route than those.
main.py :
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import *
from direct.gui.OnscreenText import OnscreenText
from direct.directutil.Mopath import Mopath
from direct.actor.Actor import Actor
from direct.task import Task
import direct.directbase.DirectStart
import os,sys, random
from PRtest_smileyClass import Smiley
from PRtest_pandaClass import Panda
import PauseResume as PR
unstoppable_namePrefix='unstoppable-'
class World(DirectObject):
def __init__(self):
camera.setPos(10.00, -40.00, 15.00)
camera.setHpr(18.43, -21.57, 0.00)
mat=Mat4(camera.getMat())
mat.invertInPlace()
base.mouseInterfaceNode.setMat(mat)
self.accept('escape',sys.exit)
self.accept('enter',self.printTask_n_IvalMgr)
self.accept('space',self.toggleSceneActive)
self.isPaused=0
lilsmi=loader.loadModel('misc/lilsmiley')
lilsmi.reparentTo(aspect2d)
lilsmi.getChild(0).setScale(.2)
lilsmi.getChild(0).setAlphaScale(.5)
taskMgr.add( self.moveLilsmi, unstoppable_namePrefix+'moveLilsmi',
extraArgs=[lilsmi,lilsmi.getChild(0)] )
OnscreenText('unstoppable\ntask',parent=lilsmi,scale=.05,pos=(0,-.15),fg=(1,1,1,1))
lilsmi2=loader.loadModel('misc/lilsmiley').copyTo(aspect2d)
lilsmi2.getChild(0).setScale(.2)
OnscreenText('unstoppable\ninterval',parent=lilsmi2,scale=.05,pos=(0,-.15),fg=(1,1,1,1))
Sequence( lilsmi2.posInterval(5,Point3(-.9,0,.9),Point3(.9,0,.9)),
lilsmi2.posInterval(5,Point3(.9,0,.9),Point3(-.9,0,.9)),
name=unstoppable_namePrefix+'smiIval').loop()
barDuration=2
OT=OnscreenText('doLater 0',scale=.075,fg=(1,1,1,1),align=TextNode.ARight,mayChange=1)
OT.index=0
NodePath(OT).setPos(render2d,.95,0,-.95)
T=taskMgr.doMethodLater(barDuration,self.updateText,'updateText',[OT])
CM=CardMaker('')
card=render2d.attachNewNode(CM.generate())
card.setPos(-1,0,-1)
card.scaleInterval(barDuration,Vec3(2,1,.04),Vec3(1e-5,1,.04)).loop()
## create smileys
self.smileys=Smiley()
#### create pandas
num=7
self.pandas=[Panda() for p in xrange(num)]
# Ralph
ralphLoc='../samples/Roaming-Ralph/models/'
self.Ralph = Actor(ralphLoc+'ralph',{'walk':ralphLoc+'ralph-walk','run':ralphLoc+'ralph-run'})
# self.Ralph.enableBlend()
# interpolate frames
# self.Ralph.find('**/+Character').node().getBundle(0).setFrameBlendFlag(1)
# self.Ralph.setControlEffect('walk', .5)
# self.Ralph.setControlEffect('run', .5)
# self.Ralph.loop('run')
self.Ralph.loop('walk')
self.Ralph.reparentTo(render)
self.Ralph.setPos(-2,-15,0)
# self.Ralph.setTag('nopause','') # to exclude this actor from getting paused
# Eve
eveLoc='../samples/Looking-and-Gripping/models/'
self.Eve = Actor(eveLoc+'eve', {'walk' : eveLoc+'eve_walk'})
self.Eve.reparentTo(render)
self.Eve.setPos(2,-15,0)
self.Eve.actorInterval("walk", playRate = 2).loop()
# self.Eve.setTag('nopause','') # to exclude this actor from getting paused
# motion path interval
np=render2d.attachNewNode('')
child=np.attachNewNode('')
LS=LineSegs()
NC=NurbsCurve()
NC.setOrder(2)
num=100
degInc=360./num
for v in range(num):
np.setR(-v*degInc)
child.setX(.6+.3*random.random())
x, z = child.getX(render2d),child.getZ(render2d)
NC.appendCv(x,0,z)
LS.drawTo(x,0,z)
if v==0: ox,oz=x,z
LS.drawTo(ox,0,oz)
NC.recompute()
render2d.attachNewNode(LS.create())
s=loader.loadModel('misc/lilsmiley')
s.reparentTo(render2d)
s.setScale(.07)
Sequence(
s.colorScaleInterval(.5,Vec4(0,0,0,1)),
s.colorScaleInterval(.5,Vec4(1)),
# to make it not pausable
# name=unstoppable_namePrefix+'colorscale-%s'%id(s)
).loop()
mp=Mopath('mp1')
mp.loadNodePath(NodePath(NC))
mpi=MopathInterval( mp, s, duration=30,
# to make it not pausable
# name=unstoppable_namePrefix+'mopath-%s'%id(mp)
)
mpi.loop()
# pausable sound
# s1=loader.loadSfx('/use/your/own/sound/file')
# s1.setVolume(.7)
# s1.setLoop(1)
# # s1.setPausable(0) # to make it not pausable
# s1.play()
# background sound that keeps playing
# s2=loader.loadSfx('/use/your/own/sound/file')
# s2.setVolume(.3)
# s2.setLoop(1)
# s2.setPausable(0) # to make it not pausable
# s2.play()
# movie texture
# movie='../samples/Media-Player/PandaSneezes.avi'
# movTex=loader.loadTexture(movie)
# movTexUV=movTex.getTexScale()
# CM=CardMaker('')
# CM.setFrameFullscreenQuad()
# CM.setUvRange(movTex)
# card=render.attachNewNode(CM.generate())
# card.setTwoSided(1)
# scale=8
# card.setScale(movTexUV[0]*scale,1,movTexUV[1]*scale)
# card.setPos(-15,5,2)
# card.setTexture(movTex)
# playAudioToo=1 # play audio ?
# pausable=1
# if playAudioToo:
# mA=loader.loadSfx(movie)
# mA.setLoop(1)
# mA.play()
# mA.setPausable(pausable) # to make it pausable or not
# movTex.synchronizeTo(mA)
# else:
# movTex.play()
# movTex.setPausable(pausable) # to make it pausable or not
# RTT
textParent=NodePath('')
text = OnscreenText(parent=textParent,text="You can't\npause me\nHO HO HO")
b3=text.getTightBounds()
bHalf=(b3[0]+b3[1])*.5
b=(b3[1]-b3[0])*.5
ratio=b[0]/b[2]
b.setZ(b[0]) if ratio>1 else b.setX(b[2])
b*=1.05 # give a little gap from the border, to avoid artifact on texture's small mip level
textBuffer = base.win.makeTextureBuffer('text buffer', 512,512)
textBuffer.setClearColor(Vec4(1))
textCam = base.makeCamera2d(textBuffer)
textCam.reparentTo(textParent)
textCam.setPos(bHalf) # put it exactly at text's center
textCam.setScale(b[0],1,b[2]) # auto-zoom in to text
self.textTexture = textBuffer.getTexture()
self.textTexture.setMinfilter(Texture.FTLinearMipmapLinear)
base.graphicsEngine.renderFrame()
base.graphicsEngine.removeWindow(textBuffer)
self.setupLights()
self.loadFloor()
self.loadColliders()
taskMgr.doMethodLater(3,self.spawnNewPanda,'spawnNewPanda')
def spawnNewPanda(self,t):
p=Panda().pandaModel
p.setY(-10)
p.colorScaleInterval(3,Vec4(0,.7,0,1),Vec4(1)).start()
p.setTag('nopause','') # to exclude this actor from getting paused
proj = LensNode('proj')
proj.setLens(OrthographicLens())
proj=p.attachNewNode(proj)
proj.setScale(4)
proj.setZ(4.7)
p.projectTexture(TextureStage(''),self.textTexture,proj)
taskMgr.doMethodLater(3,p.cleanup,'removeNewPanda',extraArgs=[])
return Task.again
def setupLights(self):
ambientLight = AmbientLight( 'ambientLight' )
ambientLight.setColor( Vec4(.3, 0.3, 0.3, 1) )
self.ambientLight=render.attachNewNode( ambientLight )
render.setLight(self.ambientLight)
directionalLight = DirectionalLight( 'directionalLight1' )
directionalLight.setDirection( Vec3( 0, 2, -1 ) )
directionalLight.setColor( Vec4( .7, .7, .7, 1 ) )
self.directionalLight=render.attachNewNode( directionalLight )
render.setLight(self.directionalLight)
def loadFloor(self):
self.floorBit=BitMask32.bit(1)
self.sphereBit=BitMask32.bit(2)
self.offBit=BitMask32.allOff()
self.floor=loader.loadModel('misc/rgbCube')
self.floor.reparentTo(render)
self.floor.setScale(18,18,.2)
self.floor.setR(25)
self.floor.flattenLight()
box=loader.loadModel('box')
box.reparentTo(self.floor)
box.setScale(7,5,.5)
box.setPos(-4,2,1.5)
box.setR(-25)
self.floor.flattenLight()
self.floor.setPos(-5,-10,-7)
self.floor.setCollideMask(self.floorBit)
box.setCollideMask(self.floorBit|self.sphereBit)
self.floor.setLightOff(1)
self.floor.hprInterval(3,Vec3(360,0,0)).loop()
def loadColliders(self):
base.cTrav=CollisionTraverser()
base.cTrav.setRespectPrevTransform(1)
self.arrows=[]
for c in xrange(5):
arrow=loader.loadModel('misc/Spotlight')
arrow.reparentTo(render)
arrow.setP(90)
arrow.setScale(.3)
arrow.setColor(.5+.5*random.random(),.5+.5*random.random(),.5+.5*random.random())
arrow.flattenStrong()
arrow.setPos(self.floor,random.uniform(-4,4),random.uniform(-4,4),10)
rayNP = arrow.attachCollisionRay('', 0,0,2, 0,0,-1, self.floorBit,self.offBit)
rayNP.show()
sphereNP = arrow.attachCollisionSphere('', 0,0,1.5, .7, self.sphereBit,self.sphereBit)
# sphereNP.show()
CHgravity = CollisionHandlerGravity()
CHgravity.addCollider(rayNP,arrow)
CHpusher= CollisionHandlerPusher()
CHpusher.addCollider(sphereNP,arrow)
base.cTrav.addCollider(rayNP,CHgravity)
base.cTrav.addCollider(sphereNP,CHpusher)
self.arrows.append([arrow,CHgravity])
taskMgr.add(self.moveArrows, 'move arrows')
def moveArrows(self,task):
dt=globalClock.getDt()
if dt>.2: return Task.cont
speed=10*dt
for a,CHG in self.arrows:
if CHG.isOnGround():
a.setH(a,random.uniform(-20,20))
lastPos=a.getPos()
a.setFluidY(a,speed)
pos=a.getPos(self.floor)
if not ( (-5 < pos[0] < 5) and (-5 < pos[1] < 5) ):
a.setFluidPos(lastPos)
a.headsUp(self.floor) # looks at floor while stays upright
a.setFluidY(a,speed)
return Task.cont
def moveLilsmi(self,np,geom):
dt=globalClock.getDt()
if dt>.2: return Task.cont
geom.setR(geom,random.uniform(-10,10))
speed=1.5*dt
np.setZ(geom,speed)
if np.getDistance(aspect2d)>.5:
geom.setR(geom,180)
np.setZ(geom,speed)
return Task.cont
def updateText(self,text):
text.index+=1
text['text']='doLater %s'%text.index
return Task.again
def printTask_n_IvalMgr(self):
print taskMgr
print taskMgr.getTasksNamed('move arrows')
print ivalMgr
def toggleSceneActive(self):
self.isPaused=not self.isPaused
if self.isPaused:
PR.pause( allAnims=0,
allAudios=0,
allMovies=0,
collision=1,
excludedTaskNamePrefix=unstoppable_namePrefix,
excludedIvalNamePrefix=unstoppable_namePrefix,
)
else:
PR.resume()
if __name__=='__main__':
World()
run()
PRtest_pandaClass.py :
from direct.actor.Actor import Actor
from random import random, uniform
class Panda:
def __init__(self):
self.pandaModel=Actor('panda',{'walk':'panda-walk'})
self.pandaModel.reparentTo(render)
scale=.2+random()*.7
self.pandaModel.setScale(scale)
self.pandaModel.setPos(uniform(-5,5),uniform(-2,6),0)
self.pandaModel.setColorScale(scale,scale,scale,1)
self.pandaModel.setPlayRate(1./scale,'walk')
self.pandaModel.setP(1/(.8*scale*scale))
self.pandaModel.loop('walk')
self.other=[]
PRtest_smileyClass.py :
from pandac.PandaModules import Vec3
from direct.interval.IntervalGlobal import LerpFunc
from math import pi, sin
class Smiley:
def __init__(self):
scale=.8
num=int(10/scale)
self.smileys=[]
self.moves = [0 for i in xrange(num)]
self.roll = [0 for i in xrange(num)]
for s in xrange(num):
smi=loader.loadModel('smiley')
smi.reparentTo(render)
smi.setScale(scale)
smi.setPos((-(num-1)*.5+s)*scale*2,-6,scale*1.25)
self.smileys.append(smi)
self.moves[s] = LerpFunc(
self.oscilateSmiley,
duration = 2,
fromData = 0,
toData = 2*pi,
extraArgs=[self.smileys[s], pi*(s%2)]
)
self.moves[s].loop()
self.roll[s]=self.smileys[s].hprInterval(3.,Vec3(720,0,360))
self.roll[s].loop()
def oscilateSmiley(self, rad, np, offset):
np.setZ(sin(rad + offset) *.9)
PauseResume.py :
__all__ = []
import sys,time
importTime = time.clock()
PRmodules = [k for k in sys.modules.keys() if k.find(__name__)>-1]
PRmodulesTime = [sys.modules[m].importTime for m in PRmodules]
PRmodulesTime.sort()
PRmod1stImport = [sys.modules[m] for m in PRmodules if sys.modules[m].importTime==PRmodulesTime[0]][0]
# print PRmodules,PRmodulesTime
if len(PRmodules)>1:
for k in PRmodules:
if importTime==sys.modules[k].importTime:
sys.modules[k] = PRmod1stImport
print 'WARNING : PauseResume module was ALREADY IMPORTED,\n using the 1st imported one.'
break
else:
import os
from direct.task import Task
directModulesDir=os.path.abspath(os.path.join(os.path.dirname(sys.modules[Task.__name__].__file__),os.pardir))
from pandac.extension_native_helpers import Dtool_funcToMethod
from pandac.PandaModules import AnimControl, AudioSound, MovieTexture, NodePath, PandaSystem, AsyncTaskManager
from direct.interval.IntervalGlobal import ivalMgr
from myMessenger import Messenger
atLeast16=PandaSystem.getMajorVersion()*10+PandaSystem.getMinorVersion()>=16
taskFunc=lambda t: t.getFunction() if atLeast16 else t.__call__
taskFuncNameQuery=lambda t: 'getFunction' if atLeast16 else '__call__'
taskXArgs=lambda t: t.getArgs() if atLeast16 else t.extraArgs
taskXArgsName=lambda t: 'getArgs' if atLeast16 else 'extraArgs'
taskWakeT=lambda t: t.getDelay() if atLeast16 else t.wakeTime
PRmsg = Messenger()
IDE_ivalsName = 'IDE_IVALS_'
IDE_tasksName = 'IDE_TASKS_'
PAUSED_TASKCHAIN_NAME = 'YNJH paused tasks'
isPaused = 0
resumeLocked = 0
# keeps the original C++ functions
AnimControl__origPlay=AnimControl.play
AnimControl__origLoop=AnimControl.loop
AnimControl__origPingpong=AnimControl.pingpong
AnimControl__origStop=AnimControl.stop
AudioSound__origPlay=AudioSound.play
AudioSound__origStop=AudioSound.stop
MovieTexture__origPlay=MovieTexture.play
MovieTexture__origStop=MovieTexture.stop
# defines the new method wrappers for intercepting messages
# ANIMATIONS ################################################################
def newAnimPlay(self):
PRmsg.accept('pauseAllAnims',self,pauseAnim,[self,0])
PRmsg.accept('pauseNotTaggedAnims',self,pauseAnim,[self])
AnimControl__origPlay(self)
Dtool_funcToMethod(newAnimPlay,AnimControl,'play')
del newAnimPlay
def newAnimLoop(self,restart=1,_from=None,_to=None):
PRmsg.accept('pauseAllAnims',self,pauseAnim,[self,0])
PRmsg.accept('pauseNotTaggedAnims',self,pauseAnim,[self])
if _from is not None and _to is not None :
AnimControl__origLoop(self,restart,_from,_to)
else:
AnimControl__origLoop(self,restart)
Dtool_funcToMethod(newAnimLoop,AnimControl,'loop')
del newAnimLoop
def newAnimPingpong(self,restart=1,_from=None,_to=None):
PRmsg.accept('pauseAllAnims',self,pauseAnim,[self,0])
PRmsg.accept('pauseNotTaggedAnims',self,pauseAnim,[self])
if _from is not None and _to is not None :
AnimControl__origPingpong(self,restart,_from,_to)
else:
AnimControl__origPingpong(self,restart)
Dtool_funcToMethod(newAnimPingpong,AnimControl,'pingpong')
del newAnimPingpong
def newAnimStop(self):
for e in PRmsg.getAllAccepting(self):
PRmsg.ignore(e,self)
AnimControl__origStop(self)
Dtool_funcToMethod(newAnimStop,AnimControl,'stop')
del newAnimStop
def pauseAnim(self,respectTag=1):
if respectTag:
part=self.getPart()
for n in xrange(part.getNumNodes()):
if NodePath(part.getNode(n)).hasNetTag('nopause'):
return
PRmsg.ignore('pauseAllAnims',self)
PRmsg.ignore('pauseNotTaggedAnims',self)
PRmsg.accept('resumeAllAnims',self,resumeAnim,[self,self.getPlayRate()])
self.setPlayRate(0)
def resumeAnim(self,PR):
PRmsg.ignore('resumeAllAnims',self)
PRmsg.accept('pauseAllAnims',self,pauseAnim,[self,0])
PRmsg.accept('pauseNotTaggedAnims',self,pauseAnim,[self])
self.setPlayRate(PR)
# AUDIO SOUNDS ##############################################################
notPausableSounds = []
invulnerableSounds = []
def newAudioPlay(self):
PRmsg.accept('pauseAllSounds',self,pauseAudio,[self,0])
PRmsg.accept('pausePausableSounds',self,pauseAudio,[self])
AudioSound__origPlay(self)
newAudioPlay.__doc__=AudioSound__origPlay.__doc__
Dtool_funcToMethod(newAudioPlay,AudioSound,'play')
del newAudioPlay
def newAudioStop(self):
for e in PRmsg.getAllAccepting(self):
PRmsg.ignore(e,self)
AudioSound__origStop(self)
newAudioStop.__doc__=AudioSound__origStop.__doc__
Dtool_funcToMethod(newAudioStop,AudioSound,'stop')
del newAudioStop
def setPausable(self,status):
if self in notPausableSounds:
notPausableSounds.remove(self)
if not status:
notPausableSounds.append(self)
Dtool_funcToMethod(setPausable,AudioSound)
del setPausable
def setInvulnerable(self,status):
if self in invulnerableSounds:
if status:
return
else:
invulnerableSounds.remove(self)
elif status:
invulnerableSounds.append(self)
Dtool_funcToMethod(setInvulnerable,AudioSound)
del setInvulnerable
def pauseAudio(self,respectTag=1):
if self in invulnerableSounds:
return
if respectTag:
if self in notPausableSounds:
return
PRmsg.ignore('pauseAllSounds',self)
PRmsg.ignore('pausePausableSounds',self)
PRmsg.accept('resumeAllSounds',self,resumeAudio,[self])
AudioSound__origStop(self)
self.setTime(self.getTime())
def resumeAudio(self):
PRmsg.ignore('resumeAllSounds',self)
PRmsg.accept('pauseAllSounds',self,pauseAudio,[self,0])
PRmsg.accept('pausePausableSounds',self,pauseAudio,[self])
AudioSound__origPlay(self)
# MOVIE TEXTURES ############################################################
notPausableMovies = []
def newMoviePlay(self):
PRmsg.accept('pauseAllMovies',self,pauseMovie,[self,0])
PRmsg.accept('pausePausableMovies',self,pauseMovie,[self])
MovieTexture__origPlay(self)
newMoviePlay.__doc__=MovieTexture__origPlay.__doc__
Dtool_funcToMethod(newMoviePlay,MovieTexture,'play')
del newMoviePlay
def newMovieStop(self):
for e in PRmsg.getAllAccepting(self):
PRmsg.ignore(e,self)
MovieTexture__origStop(self)
newMovieStop.__doc__=MovieTexture__origStop.__doc__
Dtool_funcToMethod(newMovieStop,MovieTexture,'stop')
del newMovieStop
def setPausable(self,status):
if self in notPausableMovies:
notPausableMovies.remove(self)
if not status:
notPausableMovies.append(self)
Dtool_funcToMethod(setPausable,MovieTexture)
del setPausable
def pauseMovie(self,respectTag=1):
if respectTag:
if self in notPausableMovies:
return
PRmsg.ignore('pauseAllMovies',self)
PRmsg.ignore('pausePausableMovies',self)
PRmsg.accept('resumeAllMovies',self,resumeMovie,[self])
MovieTexture__origStop(self)
def resumeMovie(self):
PRmsg.ignore('resumeAllMovies',self)
PRmsg.accept('pauseAllMovies',self,pauseMovie,[self,0])
PRmsg.accept('pausePausableMovies',self,pauseMovie,[self])
self.restart()
# INTERVALS #################################################################
def pauseIvals(excludeNamePrefix=''):
global pausedIvals
pausedIvals=ivalMgr.getIntervalsMatching('*')
excluded=[]
for i in pausedIvals:
if ( (excludeNamePrefix and i.getName().find(excludeNamePrefix)==0) or
i.getName().find(IDE_ivalsName)==0
):
excluded.append(i)
else:
#~ print 'PAUSED IVAL:',i.getName()
i.pause()
for e in excluded:
pausedIvals.remove(e)
def resumeIvals():
for i in pausedIvals:
i.resume()
# TASKS #####################################################################
def pauseTasks(excludedTaskNamePrefix,noCollision):
global unneededTasks
if not AsyncTaskManager.getGlobalPtr().findTaskChain(PAUSED_TASKCHAIN_NAME):
taskMgr.setupTaskChain(PAUSED_TASKCHAIN_NAME,
frameBudget=0) # frameBudget=0 doesn't allow any task to run
unneededTasksName=[]
# collects unneeded tasks
if noCollision:
unneededTasksName+=['collisionLoop','resetPrevTransform']
unneededTasks=[ taskMgr.getTasksNamed(tn)[0] for tn in unneededTasksName]
# collects all scene's tasks
for t in taskMgr.getTasks(): # ordinary tasks
if ( t and hasattr(t,taskFuncNameQuery(t)) and t.name.find(IDE_tasksName)!=0 and
( not excludedTaskNamePrefix or
(excludedTaskNamePrefix and t.name.find(excludedTaskNamePrefix))
)
):
func=taskFunc(t)
mod=func.__module__
# python-based intervals
if mod.find('direct.interval')==0:
if not (func.im_class.__name__=='ActorInterval' and\
func.im_self.actor.hasNetTag('nopause')):
unneededTasks.append(t)
t.interval.pause()
elif mod not in sys.modules or sys.modules[mod].__file__.find(directModulesDir)<0:
unneededTasks.append(t)
currT=globalClock.getFrameTime()
for t in taskMgr.getDoLaters(): # doLater tasks
if ( t and hasattr(t,taskFuncNameQuery(t)) and
( not excludedTaskNamePrefix or
(excludedTaskNamePrefix and t.name.find(excludedTaskNamePrefix)) )
):
unneededTasks.append(t)
# I need to alter the wakeTime during task resume,
# so I have to save the remaining time.
# Just save it as its attribute, nobody would notice :D
t.remainingTime=t.wakeTime-currT
# "pauses" tasks
for t in unneededTasks:
t.ORIG_extraArgs=taskXArgs(t) if hasattr(t,taskXArgsName(t)) else None
if hasattr(t,taskFuncNameQuery(t)):
t.ORIG_call=taskFunc(t)
t.ORIG_priority=t._priority if hasattr(t,'_priority') else t.getSort()
# only active tasks can be moved to other chain, so removes doLater
# tasks since they are in sleeping state
if hasattr(t,'remainingTime'): # doLater tasks
t.remove()
else: # ordinary tasks
t.lastactivetime=-t.time if hasattr(t,'time') else 0
try:
t.setTaskChain(PAUSED_TASKCHAIN_NAME)
except:
pass
def resumeTasks():
# restarts tasks
for t in unneededTasks:
if hasattr(t,'interval'): # it must be python-based intervals
t.interval.resume()
if hasattr(t,'ORIG_call'):
if atLeast16:
t.setFunction(t.ORIG_call)
else:
t.__call__=t.ORIG_call
else:
if hasattr(t,'remainingTime'): # doLater tasks
tempDelay=t.remainingTime-(globalClock.getRealTime()-globalClock.getFrameTime())
if hasattr(t,'uponDeath'):
uponDeath=t.uponDeath
else:
uponDeath=None
# no need to pass appendTask, since if it's already true,
# the task is already appended to extraArgs
newTask=taskMgr.doMethodLater( tempDelay, t.ORIG_call,
t.name, priority=t.ORIG_priority,
extraArgs=t.ORIG_extraArgs,
uponDeath=uponDeath)
# restore the original delayTime
if hasattr(t,'remainingTime'):
newTask.delayTime=t.delayTime
else: # ordinary tasks
t.setDelay(t.lastactivetime)
t.setTaskChain('default')
# very important to avoid assertion error on resume
t.clearDelay()
def pause( allAnims=0,allAudios=0,allMovies=0,collision=1,
excludedTaskNamePrefix='',excludedIvalNamePrefix='',
lowerLevelOperation=1
):
'''
allAnims : pause all animations or only the not "nopause" tagged ones
allAudios : pause all audio sounds or only the pausable ones
allMovies : pause all movies or only the pausable ones
collision : pause collision detection or not
excludedTaskNamePrefix : do not pause tasks with this name prefix
excludedIvalNamePrefix : do not pause intervals with this name prefix
lowerLevelOperation : <DO NOT use this>
'''
global isPaused,resumeLocked
if isPaused:
print 'WARNING : SCENE IS ALREADY PAUSED !'
return isPaused
PRmsg.send('pauseAllAnims') if allAnims else PRmsg.send('pauseNotTaggedAnims')
PRmsg.send('pauseAllSounds') if allAudios else PRmsg.send('pausePausableSounds')
PRmsg.send('pauseAllMovies') if allMovies else PRmsg.send('pausePausableMovies')
pauseIvals(excludedIvalNamePrefix)
pauseTasks(excludedTaskNamePrefix,collision)
base.disableParticles()
isPaused=1
resumeLocked=lowerLevelOperation
# print 'PR:',isPaused
return isPaused
def resume(lowerLevelOperation=1):
global isPaused,resumeLocked
if resumeLocked and not lowerLevelOperation:
# print 'WARNING : RESUME IS LOCKED'
return 2
if not isPaused:
print 'WARNING : SCENE IS ALREADY RESUMED'
return isPaused
PRmsg.send('resumeAllAnims') # resume all animations
PRmsg.send('resumeAllSounds') # resume all audio
PRmsg.send('resumeAllMovies') # resume all movie
resumeIvals()
resumeTasks()
base.enableParticles()
isPaused=0
# print 'PR:',isPaused
return isPaused
NOTE :
myMessenger module is the old Messenger.py, you can use 1.5’s, because 1.6’s wants python-only receiver object.
panda3d.cvs.sf.net/viewvc/panda3 … iew=markup
Use SPACE to toggle pause/resume, ENTER to investigate taskMgr & ivalMgr.
One issue about doLater tasks :
I don’t know what I missed, it’s hard to get it right. The doLater task’s wakeTime is reached to soon if I do pause/resume rapidly.