Parallel and sequence with animations

hello everyone
i’m trying to use the Parallel() function to at the same time play an animation and play some particle visual effects from a file

my code looks like this:

def TAE(t, wp, TAE):
    global list_anim
    list_anim.clear()
    config = configparser.RawConfigParser()
    config.read('TAE/' + str(TAE) + '.txt')
    object_data = config.items(str(wp))
    print(t.getAnimNames())

    for i in object_data:


        data = i[1].split("\n")
        taefull = data[1].split(" || ")
        anim = data[0].split(",")
        ani_name = anim[0]
        # get anim duration
        dur = (t.getNumFrames(ani_name))
        # get framerate
        frameR = (t.getFrameRate(ani_name))
        # frames from anim
        k = dur / frameR
        ## create principal parallel

        p = ParallelEndTogether(t.actorInterval(ani_name, startFrame=1, endFrame=dur))

        if anim[1] == "0":
            break

        for i in taefull:
            # create track
            track = Sequence()
            # cycle for searching functions
            for j in taefull:
                print(j)
                if j.split(",")[0] == "W":
                    d_t=(float(j.split(",")[2]) - float(j.split(",")[1])) * k
                    track.append(Wait(d_t))

                elif j.split(",")[0] == "A":
                    track.append(Wait(float(j.split(",")[1])))
                    track.append(loadmultiVFX(t, j.split(",")[2], j.split(",")[3]))

                # if j.split(",")[0] == "B":
                #     track.append(funcsound())
                #     track.append(Wait(j.split(",")[3]))

                elif j.split(",")[0] == "C":
                    track.append(Wait(float(j.split(",")[1])))
                    track.append(cleanallvfx())
                p.append(track)
    list_anim.append(p)


def TAEstart(n):
    list_anim[n].start()

but for some reason my function for spawning the particles can’t be appended to it
giving me this error:

track.append(loadmultiVFX(t, j.split(“,”)[2], j.split(“,”)[3]))
File “C:\Panda3D-1.10.11-x64\direct\interval\MetaInterval.py”, line 130, in append
assert self.validateComponent(ival)
AssertionError

but here says than i should be able to just append it
how can i do it?

What do the methods “loadmultiVFX” and “cleanallvfx” return? You’re adding those return-values into the Sequence named “track”, and I’m wondering whether said return-values are valid Intervals (or Sequences or Parallels).

If they’re not such valid things, then it may be that they’re resulting in an invalid Sequence, which the parallel is thus rejecting.

1 Like
def loadmultiVFX(t, filename, tag):
    j = 0
    global lvfx, max_vfx
    for i in list_dum:
        if i.getTag('ID') != tag:
            pass
        else:
            if lvfx >= max_vfx:
                lvfx = 0
            if max_vfx != len(list_vfx):
                list_vfx.append(ParticleEffect())
                list_vfx[-1].loadConfig(Filename(filename))
                list_vfx[-1].start(t)
                list_vfx[-1].reparentTo(i)
                lvfx += 1
  
            else:
                print(list_vfx)
                print(f" lafx={lvfx},j={j} ")
                print(f'cleaning {list_vfx[lvfx]}')
                list_vfx[lvfx].disable()
                list_vfx[lvfx].loadConfig(Filename(filename))
                list_vfx[lvfx].start(t)
                list_vfx[lvfx].reparentTo(i)
                print(f"vfx{list_vfx[lvfx]} \nadded particle to {i}")
                lvfx += 1
            j += 1

def cleanallvfx():
    global lvfx
    lvfx = 0
    for i in list_vfx:
        i.disable()

they don’t return anything per say
they modify some global variables and disable the particles

Ah. In which case you’re then passing “None” (the return-value of a function that returns nothing) into your Sequence, which presumably isn’t a valid thing to have, and is thus I imagine resulting in the sequence being found invalid by the Parallel.

Are you perhaps trying to have those methods themselves (as opposed to their return-values) be added to the Sequence?

If so, then my answer has two parts:

First, one passes in a method or function (again, as opposed to its return-value) as a parameter by passing in the function with no brackets or parameters. For example:

def meow():
    print ("Meow!")

# A slightly-pointless method that should nevertheless
# hopefully demonstrate the passing-in of functions/methods
def callAMethod(someMethod):
    # Call the method! :D
    someFunction()

# Now, we want to have "callAMethod" call the "meow" method...

# The following >doesn't< work:
#  It passes in the return-value of "meow", which
# is "None" (as "meow" doesn't return anything):
callAMethod(meow())

# Note that the above >calls "meow"< when
#  specifying a parameter to "callAMethod"

# The following >does< (or should) work:
#  It passes in >meow itself<, not its return-value
callAMethod(meow) # <-- Note the lack of brackets after "meow"

# Note that the above >doesn't< call "meow" when
#  specifying a parameter to "callAMethod".

Now, that’s the first issue. The second is that you’re just passing the method directly into the Sequence–and I daresay that Sequence doesn’t know what to do with such a thing.

In order to have a Sequence (or Parallel) run an arbitrary method, we use a special Interval called a “Func”. This simply takes a function/method and then, as instructed by a Sequence or Parallel, calls that function/method.

Something like this:

def meow():
    print ("Meow!")

mySequence = Sequence()

myFunc = Func(meow)
mySequence.append(myFunc)

mySequence.start()

(This is what is happening in the post to which you linked, I believe: the code posted there passes the method itself into a Func-object, which is added to a Sequence.)

2 Likes

then…hmmmmm
how can i set my values needed for the function inside the Func-object?
is something like:

myFunc =  Func(loadvfx(a,b,c))

posible?

Again, that would pass in the return-value of “loadvfx”, not the function itself.

I believe that the constructor for “Func” allows you to pass in parameters to be passed to the method that it controls.

See this manual page for more.

1 Like

yeah… i just found the way
Thank you very much

myfunc = Func(loadmultiVFX,extraArgs=[t, j.split(",")[2], j.split(",")[3]])
                    track.append(myfunc)
1 Like