Wait function

I was wondering if anyone has a function they made/have that you can use that is like
Wait(5) and it waits five seconds. I looked around and everyone was using domethodlater and I used it a lot and I realized how sloppy my coding looks having like 10 different domethodlaters all stacked up. I’d really appreciate it. Also, I must say just from using the search button I am gaining A LOT of knowledge :slight_smile:

I’d suggest using Sequences and Intervals, they are realy useful =)
panda3d.org/manual/index.php/Intervals
and the following pages…

There is also a Wait(x) Interval =)

blenderkid

Can you give me a small example so I can base off of it?

Ok,

there are endless possibilities, so it would be good to know what exacty you want to do. =)

but here is an example

def myFunction(x,y):
   #..do_something..
   pass

seq = Sequence()
seq.append( LerpPosInterval( myModel, 5, (5,0,0), startPos=(0,0,0)))
  # -> Moves myModel from (0,0,0) to (5,0,0) in 5 seconds
seq.append(Wait(time))
  # -> Waits "time" seconds
seq.append( Func( myFunction( arg1,arg2 ) )
  # -> executes myFuntion with the 2 arguments
seq.start() -> Starts the sequence and all intervals are played after each other.

You can add a Lerp interval for example to change position/rotation/scale…

panda3d.org/manual/index.php/Lerp_Intervals

You can add a Wait interval…
That creates a pause without blocking your program.

I added a simple function which has 2 args and does nothing so far… ^^
You can instead add a LerpFunc Interval which calls the function several times and gives it a time argument

Here are actor animation intervals… (not used in the litte code sniplet above)

panda3d.org/manual/index.php/Actor_Intervals

There are sound intervals too, but as far as I don’t know what you need the information I give are rather useless ^^

panda3d.org/manual/index.php/Sound_Intervals

And there are motionpath and particle intervals which all can be added into the sequence

Instead of sequences which play the intervals after each other you can use Parallels, which play all intervals at once. Use them exactly the same way as Sequences.

I hope that helped at least a bit =)

blenderkid

I need to do something like this (and thanks for your time) :slight_smile:
def ontime():
#FUNCTIONS
Wait(5)
#FUNCTIONS
ect…

then just do:

def onTime():
  seq = Sequence()
  seq.append(Func(yourfunctions1))
  seq.append(Wait(5))
  seq.append(Func(yourfunctions2))
  seq.start()

blenderkid

That gives me errors and skips right to the 2nd append.

thats what its supposed to do. If you really want to wait 5 seconds, have no frames render, and have the application not respond to user input at all, you can wait 5 seconds (there are ways to do it), but thats really something you should never do. What you should do is schedule something to happen 5 seconds from now, and let other stuff run until then. Thats what the code you’ve been given does.

There is also doMethodLater() panda3d.org/reference/python … 444eb9c82f

Its possible to work with sequences, tasks and such in an organized manner, but it takes some getting used to.

Well, potentially you could do a generator/task hack with a generator thats called with a yield None in a tight loop to wait, called from a task every frame, and it would come really close to threaded waiting without the issues. Seems quite clever and perhaps what you want. Maybe I should write up some example code for doing it. This idea need further investigation.

Edit: Tutorial with generator based fake thread:

from math import pi, sin, cos
 
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from panda3d.core import Point3,ClockObject
 
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
 
        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
 
        
 
        # Load and transform the panda actor.
        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.reparentTo(self.render)
        # Loop its animation.
        self.pandaActor.loop("walk")
 
        # Create the four lerp intervals needed for the panda to
        # walk back and forth.
        pandaPosInterval1 = self.pandaActor.posInterval(13,
                                                        Point3(0, -10, 0),
                                                        startPos=Point3(0, 10, 0))
        pandaPosInterval2 = self.pandaActor.posInterval(13,
                                                        Point3(0, 10, 0),
                                                        startPos=Point3(0, -10, 0))
        pandaHprInterval1 = self.pandaActor.hprInterval(3,
                                                        Point3(180, 0, 0),
                                                        startHpr=Point3(0, 0, 0))
        pandaHprInterval2 = self.pandaActor.hprInterval(3,
                                                        Point3(0, 0, 0),
                                                        startHpr=Point3(180, 0, 0))
 
        # Create and play the sequence that coordinates the intervals.
        self.pandaPace = Sequence(pandaPosInterval1,
                                  pandaHprInterval1,
                                  pandaPosInterval2,
                                  pandaHprInterval2,
                                  name="pandaPace")
        self.pandaPace.loop()
        
        self.disableMouse()
        
        
        ###### Generator + Task -->> Thread like thing
        def fakeThread(camera,task):
            clock=ClockObject()
            t=0
            def tick():
                clock.tick()
                return clock.getDt()
            while True:
                dt=tick()
                t+=dt
                yield Task.cont
                camSpeed=8*(sin(t/2)+.5)
                camera.setH(camera,camSpeed*dt)
                camera.setPos(0,0,0)
                camera.setPos(camera,0,-20,3)
                 

        # Define a procedure to move the camera.
        def spinCameraTask(self): return fakeThread.next()
        
        # Add the spinCameraTask procedure to the task manager.
        camTask=self.taskMgr.add(spinCameraTask, "SpinCameraTask")
        
        fakeThread=fakeThread(self.camera,camTask)
        


 
app = MyApp()
app.run()

Also, make sure you are doing Func(myfunction) and not Func(myfunction()). This is a common error. The first form stores a reference to myfunction and will call it when the interval reaches that point. The second form calls myfunction right on the spot, and stores None (or whatever myfunction returned), which is almost certainly not what you wanted to happen.

David

But it takes 2 argument’s… It needs to be like
(‘yo’) for example… How would I do what you are saying while filling in the argument.

Func(myfunction, extraArgs = ['yo'])

This will call myfunction(‘yo’) at the time the interval is played.

David

def onTime():
    seq = Sequence()
    seq.append(Func(function, extraArgs = ['yo'])
    seq.append(Wait(5))
    seq.append(Func(function, extraArgs = ['yo2']) 
    seq.start()

I keep getting an error…

SyntaxError: invalid syntax
   File "<string>", line 4
      seq.append(Wait(5))
        ^

seq.append(Func(function, extraArgs = [‘yo’]) <<<— Try having enough “)”.
What are you doing with ‘Func’ anyway?

Maybe:
seq.append(function, extraArgs = [‘yo’])
is what you want?

No, Func is correct: that’s the correct way to wrap a function call up in an interval, as we discussed above. (You can’t add a Python function directly to a Sequence.)

But, you do need to have the correct number of parens. :slight_smile:

David

Code:

def onTime():
    from direct.interval.IntervalGlobal import *
    setanim = baseline.char.setAnim
    seq = Sequence()
    seq.append(Func(setanim, extraArgs = ['run']))
    seq.append(Wait(5))
    seq.append(Func(setanim, extraArgs = ['jog']))
    seq.start()
onTime()

Error:

TyperError: baseline.char.setAnim takes at least 2 arguments (1 given) 

So it’s not detecting the ‘run’ or ‘jog’… Why is this did I mess something up yet again ? I’m sorry for being so hard to worth with :frowning: I appreciate all you do…

I don’t know what you mean. It says it wants 2 arguments, but you appear to have given it only 1: the string ‘run’, for instance, which is only 1 argument. It’s your function, isn’t it? What should be the second argument? Add it to the list, e.g. extraArgs = [‘run’, 1].

baseline.char.setAnim(‘run’) works… so why wouldn’t what I tried?

It should. Maybe there’s something else. Is this error message coming from a different part of the code, for instance?

What is baseline.char.setAnim? Is it a method, or a standalone function? How many parameters does it actually require?

David

setAnim could be expecting an instance as the 1st arg.

Func(baseline.char.setAnim, baseline.char, "run")

hi,

there is no need for the “extraArgs”.
Try

seq.append(Func(setanim,"yo"))

That should work, but it “should” also work with extraArgs =/

ynjh_jo could be right too, I don’t know the function…

blenderkid