示例#1
0
 def __init__(self, fileName=None, prereqs=None):
     Effect.__init__(self, fileName)
     Effect._create(self, prereqs)
     self.timer = EventTimer()
     self.source = None
     self.target = None
     return
示例#2
0
    def __init__(self, fileName = None, maxDuration = 10.0, prereqs = None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.timers = {}
        for actorName in self.actors.keys():
            self.timers[actorName] = EventTimer()

        self.maxDuration = maxDuration
        if self.maxDuration < 0.0:
            WARNING_MSG('maxDuration was negative!  setting to 10', self.maxDuration)
            self.maxDuration = 10.0
示例#3
0
 def __init__(self, fileName = None, prereqs = None):
     Effect.__init__(self, fileName)
     Effect._create(self, prereqs)
     self.timer = EventTimer()
     self.source = None
     self.target = None
     return
示例#4
0
    def __init__(self, fileName = None, maxDuration = 10.0, prereqs = None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.timers = {}
        for actorName in self.actors.keys():
            self.timers[actorName] = EventTimer()

        self.maxDuration = maxDuration
        if self.maxDuration < 0.0:
            WARNING_MSG('maxDuration was negative!  setting to 10', self.maxDuration)
            self.maxDuration = 10.0
示例#5
0
class OneShot(Effect):
    """
    This class implements an Effect that has a simple one-play cycle.
    With this class, you call go( source, target ).  It will clean itself up
    and when completely finished, and its self.going flag will be reset.
    
    maxDuration is an important parameter, it makes sure that OneShots do
    not build up in the world.   In some cases, Effect files cannot work out
    their duration (e.g. if a continuously time-triggered particle effect is
    referenced in the effect.)  In these cases, maxDuration is used to cap the
    time the effect is in use.  If this behaviour is not desired, you should
    use FX.Persistent instead, and manage the lifetime of the effect yourself.
    
    This type of Effect does not keep a permanent assocation with any source.
    """
    def __init__(self, fileName=None, maxDuration=10.0, prereqs=None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.timers = {}
        for actorName in self.actors.keys():
            self.timers[actorName] = EventTimer()

        self.maxDuration = maxDuration
        if self.maxDuration < 0.0:
            WARNING_MSG('maxDuration was negative!  setting to 10',
                        self.maxDuration)
            self.maxDuration = 10.0

    def _playEvents(self,
                    eventTiming,
                    source,
                    target=None,
                    callbackFn=None,
                    **kargs):
        """
        This method plays all the events that match the
        TRANSFORM_DEPENDENT_EVENT timing flag.
        
        This first pass through ( eventTiming = 0 ) happens during the
        attach frame.  this is so particles can be cleared as they are attached
        (so they don't draw in their last position for one frame.)
        
        The second pass through ( eventTiming = 1 ) happens after
        the transforms have been set, usually the next frame.  This is
        so that particles etc. can be spawned at the correct location.
        
        The third pass through ( eventTiming =2 ) happens after
        the total duration of the effect is known.  This duration is put
        into the kargs.  This is for events that either begin some stage
        through the effect, or need to end at the correct time (for example
        turning off time triggered particles for a nice fade-out,
        or setting up a colour animation that is timed exactly.)
        """
        for actorName, event in self.events:
            if event.eventTiming() == eventTiming:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                duration = min(event.go(self, actor, source, target, **kargs),
                               self.maxDuration)
                if actorName != '':
                    if not self.lengths.has_key(actorName):
                        self.lengths[actorName] = duration
                    else:
                        self.lengths[actorName] = max(self.lengths[actorName],
                                                      duration)
                self.totalDuration = max(duration, self.totalDuration)

        return self.totalDuration

    def go(self, source, target=None, callbackFn=None, **kargs):
        """
        This method should be the only method called on this Effect. Once fully
        finished, the self.going flag will be reset, and you can call go()
        again.
        
        If you pass in a callback function, it will be called upon full completion
        of the effect.
        """
        if self.timer.going():
            return
        self.timer.reserve()
        self.lengths = {}
        self.totalDuration = 0.0
        for actorName, attacher in self.joints.items():
            attacher.attach(self.actors[actorName], source, target)

        self._playEvents(IMMEDIATE_EVENT, source, target, callbackFn, **kargs)
        BigWorld.callback(
            0.001, lambda: self._go2(source, target, callbackFn, **kargs))

    def _go2(self, source, target, callbackFn, **kargs):
        """
        This method is internal - once attached and have waited a frame, spawn
        all transform dependent events.
        """
        self._playEvents(TRANSFORM_DEPENDENT_EVENT, source, target, callbackFn,
                         **kargs)
        for actorName, duration in self.lengths.items():
            if duration <= 0.0:
                duration = self.maxDuration
                self.totalDuration = self.maxDuration
            self.timers[actorName].begin(
                duration, partial(self.detach, actorName, source, target))

        if self.totalDuration > self.maxDuration or self.totalDuration <= 0.0:
            WARNING_MSG(
                'using maxDuration for this effect. perhaps this was unexpected?',
                self, source, target)
            self.totalDuration = self.maxDuration
        kargs['totalDuration'] = self.totalDuration
        kargs['actorDurations'] = self.lengths
        self._playEvents(DURATION_DEPENDENT_EVENT, source, target, callbackFn,
                         **kargs)
        self.timer.begin(self.totalDuration,
                         lambda: self.stop(source, target, callbackFn))
        self.timer.release()

    def detach(self, actorName, source, target):
        """
        This method should be considered as private for the OneShot effect. It
        is called automatically in response to the effect ending.
        """
        self.joints[actorName].detach(self.actors[actorName], source, target)

    def stop(self, source, target, callbackFn):
        if callbackFn:
            callbackFn()

    def _extendTime(self, event, duration):
        for actorName, ev in self.events:
            if event == ev:
                self.timers[actorName].extend(duration)

        self.timer.extend(duration)
示例#6
0
class OneShot(Effect):
    """
    This class implements an Effect that has a simple one-play cycle.
    With this class, you call go( source, target ).  It will clean itself up
    and when completely finished, and its self.going flag will be reset.
    
    maxDuration is an important parameter, it makes sure that OneShots do
    not build up in the world.   In some cases, Effect files cannot work out
    their duration (e.g. if a continuously time-triggered particle effect is
    referenced in the effect.)  In these cases, maxDuration is used to cap the
    time the effect is in use.  If this behaviour is not desired, you should
    use FX.Persistent instead, and manage the lifetime of the effect yourself.
    
    This type of Effect does not keep a permanent assocation with any source.
    """

    def __init__(self, fileName = None, maxDuration = 10.0, prereqs = None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.timers = {}
        for actorName in self.actors.keys():
            self.timers[actorName] = EventTimer()

        self.maxDuration = maxDuration
        if self.maxDuration < 0.0:
            WARNING_MSG('maxDuration was negative!  setting to 10', self.maxDuration)
            self.maxDuration = 10.0

    def _playEvents(self, eventTiming, source, target = None, callbackFn = None, **kargs):
        """
        This method plays all the events that match the
        TRANSFORM_DEPENDENT_EVENT timing flag.
        
        This first pass through ( eventTiming = 0 ) happens during the
        attach frame.  this is so particles can be cleared as they are attached
        (so they don't draw in their last position for one frame.)
        
        The second pass through ( eventTiming = 1 ) happens after
        the transforms have been set, usually the next frame.  This is
        so that particles etc. can be spawned at the correct location.
        
        The third pass through ( eventTiming =2 ) happens after
        the total duration of the effect is known.  This duration is put
        into the kargs.  This is for events that either begin some stage
        through the effect, or need to end at the correct time (for example
        turning off time triggered particles for a nice fade-out,
        or setting up a colour animation that is timed exactly.)
        """
        for actorName, event in self.events:
            if event.eventTiming() == eventTiming:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                duration = min(event.go(self, actor, source, target, **kargs), self.maxDuration)
                if actorName != '':
                    if not self.lengths.has_key(actorName):
                        self.lengths[actorName] = duration
                    else:
                        self.lengths[actorName] = max(self.lengths[actorName], duration)
                self.totalDuration = max(duration, self.totalDuration)

        return self.totalDuration

    def go(self, source, target = None, callbackFn = None, **kargs):
        """
        This method should be the only method called on this Effect. Once fully
        finished, the self.going flag will be reset, and you can call go()
        again.
        
        If you pass in a callback function, it will be called upon full completion
        of the effect.
        """
        if self.timer.going():
            return
        self.timer.reserve()
        self.lengths = {}
        self.totalDuration = 0.0
        for actorName, attacher in self.joints.items():
            attacher.attach(self.actors[actorName], source, target)

        self._playEvents(IMMEDIATE_EVENT, source, target, callbackFn, **kargs)
        BigWorld.callback(0.001, lambda : self._go2(source, target, callbackFn, **kargs))

    def _go2(self, source, target, callbackFn, **kargs):
        """
        This method is internal - once attached and have waited a frame, spawn
        all transform dependent events.
        """
        self._playEvents(TRANSFORM_DEPENDENT_EVENT, source, target, callbackFn, **kargs)
        for actorName, duration in self.lengths.items():
            if duration <= 0.0:
                duration = self.maxDuration
                self.totalDuration = self.maxDuration
            self.timers[actorName].begin(duration, partial(self.detach, actorName, source, target))

        if self.totalDuration > self.maxDuration or self.totalDuration <= 0.0:
            WARNING_MSG('using maxDuration for this effect. perhaps this was unexpected?', self, source, target)
            self.totalDuration = self.maxDuration
        kargs['totalDuration'] = self.totalDuration
        kargs['actorDurations'] = self.lengths
        self._playEvents(DURATION_DEPENDENT_EVENT, source, target, callbackFn, **kargs)
        self.timer.begin(self.totalDuration, lambda : self.stop(source, target, callbackFn))
        self.timer.release()

    def detach(self, actorName, source, target):
        """
        This method should be considered as private for the OneShot effect. It
        is called automatically in response to the effect ending.
        """
        self.joints[actorName].detach(self.actors[actorName], source, target)

    def stop(self, source, target, callbackFn):
        if callbackFn:
            callbackFn()

    def _extendTime(self, event, duration):
        for actorName, ev in self.events:
            if event == ev:
                self.timers[actorName].extend(duration)

        self.timer.extend(duration)
示例#7
0
class Persistent(Effect):
    """
    This class implements an Effect that persist on an object.
    With this class, you must call attach(), then go(),stop(),go(),stop() as
    many times as you like, then detach().
    
    Once attached, there is a persistent association with the source.  Thus
    when calling go(), you need not pass in the source again.
    
    You can pass in a callback fn to go(), which is called back when the effect
    has properly finished one pass through for all its events.
    """
    def __init__(self, fileName=None, prereqs=None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.source = None
        self.target = None
        return

    def attach(self, source):
        """
        This method attaches the effect to the source.  The source may be a
        model or an entity, depending on the effect.  It is usually safe to
        pass in an Entity, since the Joints associated with the effect can
        find the appropriate model and/or node from an entity, however Joints
        cannot derive the entity given a model or a node.
        """
        self.source = source
        for actor, attacher in self.joints.items():
            attacher.attach(self.actors[actor], source)

    def go(self, target=None, callbackFn=None, **kargs):
        """
        This method starts the effect playing, once it is attached.  You may
        call go() and stop() any number of times in between attach() and
        detach() pairs.
        """
        self.totalDuration = 0.0
        self.target = target
        for actorName, event in self.events:
            if event.eventTiming() == 0:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                self.totalDuration = max(
                    self.totalDuration,
                    event.go(self, actor, self.source, target, **kargs))

        BigWorld.callback(0.001,
                          lambda: self._go2(target, callbackFn, **kargs))
        return

    def _go2(self, target=None, callbackFn=None, **kargs):
        for actorName, event in self.events:
            if event.eventTiming() > 0:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                self.totalDuration = max(
                    self.totalDuration,
                    event.go(self, actor, self.source, target, **kargs))

        if callbackFn:
            self.timer.begin(self.totalDuration + 0.001, callbackFn)
        return

    def stop(self):
        """
        This method stops the effect playing.  Note that it will do this
        gracefully, i.e. it allows the effect to die out rather than pop out.
        For this reason, a stopTime is returned and the effect should not
        be started again, nor should it be detached, until this time has been
        has been allowed to pass.
        """
        stopTime = 0.0
        for actorName, event in self.events:
            try:
                actor = self.actors[actorName]
            except KeyError:
                actor = None

            eventStopTime = event.stop(actor, self.source, self.target)
            stopTime = max(stopTime, eventStopTime)

        return stopTime

    def detach(self):
        """
        This method detaches the effect from the source, removing it and all
        its actors from the world.  The effect remembers where it was
        attached to begin with, so no arguments need be passed in.
        """
        for actor, attacher in self.joints.items():
            attacher.detach(self.actors[actor], self.source)

        self.source = None
        self.target = None
        return
示例#8
0
class Persistent(Effect):
    """
    This class implements an Effect that persist on an object.
    With this class, you must call attach(), then go(),stop(),go(),stop() as
    many times as you like, then detach().
    
    Once attached, there is a persistent association with the source.  Thus
    when calling go(), you need not pass in the source again.
    
    You can pass in a callback fn to go(), which is called back when the effect
    has properly finished one pass through for all its events.
    """

    def __init__(self, fileName = None, prereqs = None):
        Effect.__init__(self, fileName)
        Effect._create(self, prereqs)
        self.timer = EventTimer()
        self.source = None
        self.target = None
        return

    def attach(self, source):
        """
        This method attaches the effect to the source.  The source may be a
        model or an entity, depending on the effect.  It is usually safe to
        pass in an Entity, since the Joints associated with the effect can
        find the appropriate model and/or node from an entity, however Joints
        cannot derive the entity given a model or a node.
        """
        self.source = source
        for actor, attacher in self.joints.items():
            attacher.attach(self.actors[actor], source)

    def go(self, target = None, callbackFn = None, **kargs):
        """
        This method starts the effect playing, once it is attached.  You may
        call go() and stop() any number of times in between attach() and
        detach() pairs.
        """
        self.totalDuration = 0.0
        self.target = target
        for actorName, event in self.events:
            if event.eventTiming() == 0:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                self.totalDuration = max(self.totalDuration, event.go(self, actor, self.source, target, **kargs))

        BigWorld.callback(0.001, lambda : self._go2(target, callbackFn, **kargs))
        return

    def _go2(self, target = None, callbackFn = None, **kargs):
        for actorName, event in self.events:
            if event.eventTiming() > 0:
                try:
                    actor = self.actors[actorName]
                except:
                    actor = None

                self.totalDuration = max(self.totalDuration, event.go(self, actor, self.source, target, **kargs))

        if callbackFn:
            self.timer.begin(self.totalDuration + 0.001, callbackFn)
        return

    def stop(self):
        """
        This method stops the effect playing.  Note that it will do this
        gracefully, i.e. it allows the effect to die out rather than pop out.
        For this reason, a stopTime is returned and the effect should not
        be started again, nor should it be detached, until this time has been
        has been allowed to pass.
        """
        stopTime = 0.0
        for actorName, event in self.events:
            try:
                actor = self.actors[actorName]
            except KeyError:
                actor = None

            eventStopTime = event.stop(actor, self.source, self.target)
            stopTime = max(stopTime, eventStopTime)

        return stopTime

    def detach(self):
        """
        This method detaches the effect from the source, removing it and all
        its actors from the world.  The effect remembers where it was
        attached to begin with, so no arguments need be passed in.
        """
        for actor, attacher in self.joints.items():
            attacher.detach(self.actors[actor], self.source)

        self.source = None
        self.target = None
        return