Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
f1de09e0bf

+ 9 - 0
direct/src/interval/AnimInterval.py

@@ -7,6 +7,15 @@ class AnimInterval(Interval):
     # Name counter
     animNum = 1
     # Class methods
+    # Interval used to play an animation.  If loop = 0, animation is
+    # played only once and the pose of the anim depends on t passed
+    # into the setT method every frame.  If loop = 1, the animation is
+    # started and plays on its own and stopped when t > duration or
+    # IVAL_STOP event occurs.  If no duration is specified, interval
+    # duration defaults to be equal to the length of the animation.
+    # Note: if loop == 0 and duration > anim duration then the animation
+    # will play once and then nothing will happen for the remainder of the
+    # interval
     def __init__(self, animControl, loop = 0, duration = 0.0, name=None):
         """__init__(name)
         """

+ 49 - 12
direct/src/interval/FunctionInterval.py

@@ -18,9 +18,12 @@ class FunctionInterval(Interval):
 	    name = 'FunctionInterval-%d' % FunctionInterval.functionIntervalNum
 	    FunctionInterval.functionIntervalNum += 1
         # Initialize superclass
-        # Set openEnded true if calls after end time cause interval
-        # function to be called
+        # Set openEnded true if IVAL_INIT calls after end time cause interval
+        # function to be called.  If false, IVAL_INIT calls have no effect
+        # Event, Accept, Ignore intervals default to fOpenEnded = 0
+        # Parent, Pos, Hpr, etc intervals default to fOpenEnded = 1
 	Interval.__init__(self, name, duration = 0.0, openEnded = openEnded)
+    
     def updateFunc(self, t, event = IVAL_NONE):
 	""" updateFunc(t, event)
 	    Go to time t
@@ -44,25 +47,29 @@ class EventInterval(FunctionInterval):
 ### FunctionInterval subclass for accepting hooks ###
 class AcceptInterval(FunctionInterval):
     # Initialization
-    def __init__(self, dirObj, event, function, name):
+    def __init__(self, dirObj, event, function, name = None):
         """__init__(dirObj, event, function, name)
         """
         def acceptFunc(dirObj = dirObj, event = event, function = function):
-            print "accepting..."
             dirObj.accept(event, function)
+        # Determine name
+        if (name == None):
+            name = 'Accept-' + event
         # Create function interval
 	FunctionInterval.__init__(self, acceptFunc, name = name,
                                   openEnded = 0)
 
-### FunctionInterval subclass for throwing events ###
+### FunctionInterval subclass for ignoring events ###
 class IgnoreInterval(FunctionInterval):
     # Initialization
-    def __init__(self, dirObj, event, name):
+    def __init__(self, dirObj, event, name = None):
         """__init__(dirObj, event, name)
         """
         def ignoreFunc(dirObj = dirObj, event = event):
-            print "ignoring..."
             dirObj.ignore(event)
+        # Determine name
+	if (name == None):
+	    name = 'Ignore-' + event
         # Create function interval
 	FunctionInterval.__init__(self, ignoreFunc, name = name,
                                   openEnded = 0)
@@ -188,7 +195,7 @@ class PosHprInterval(FunctionInterval):
         FunctionInterval.__init__(self, posHprFunc, name = name)
 
 class PosHprScaleInterval(FunctionInterval):
-    # PosHprInterval counter
+    # PosHprScaleInterval counter
     posHprScaleIntervalNum = 1
     # Initialization
     def __init__(self, nodePath, pos, hpr, scale, duration = 0.0,
@@ -212,19 +219,49 @@ class PosHprScaleInterval(FunctionInterval):
 
 """
 SAMPLE CODE
+
 from IntervalGlobal import *
 
 ### Using lambdas and functions ###
 # Using a lambda
 i1 = FunctionInterval(lambda: base.transitions.fadeOut())
 i2 = FunctionInterval(lambda: base.transitions.fadeIn())
+
+def caughtIt():
+    print 'Caught here-is-an-event'
+
+class DummyAcceptor(DirectObject):
+    pass
+
+da = DummyAcceptor()
+i3 = AcceptInterval(da, 'here-is-an-event', caughtIt)
+
+i4 = EventInterval('here-is-an-event')
+
+i5 = IgnoreInterval(da, 'here-is-an-event')
+
 # Using a function
-def printHello():
-    print 'hello'
+def printDone():
+    print 'done'
+
+i6 = FunctionInterval(printDone)
 
-i3 = FunctionInterval(printHello)
 # Create track
-t1 = Track([(0.0, i1), (2.0, i2), (4.0, i3)], name = 'demo')
+t1 = Track([
+    # Fade out
+    (0.0, i1),
+    # Fade in
+    (2.0, i2),
+    # Accept event
+    (4.0, i3),
+    # Throw it,
+    (5.0, i4),
+    # Ignore event
+    (6.0, i5),
+    # Throw event again and see if ignore worked
+    (7.0, i4),
+    # Print done
+    (8.0, i6)], name = 'demo')
 
 # Play track
 t1.play()

+ 19 - 5
direct/src/interval/Interval.py

@@ -16,8 +16,7 @@ class Interval(DirectObject):
     notify = directNotify.newCategory("Interval")
     #notify.setDebug(1)
 
-    # special methods
-    
+    # Class methods
     def __init__(self, name, duration, openEnded = 1):
         """__init__(name, duration)
         """
@@ -65,9 +64,13 @@ class Interval(DirectObject):
         self.prev_t = self.curr_t
 
     def updateFunc(self, t, event = IVAL_NONE):
+        """ updateFunc(t, event)
+        """
+        # Subclasses define this function
         pass
 
     def setTHook(self, t):
+        # Used by control panel to update scale
         pass
 
     def setFinalT(self):
@@ -79,7 +82,7 @@ class Interval(DirectObject):
         """ play(t0, duration)
         """
         # Kill ongoing play task
-        self.stop()
+        taskMgr.removeTasksNamed(self.name + '-play')
         # Start new one
 	self.offset = t0
         self.startT = self.clock.getFrameTime()
@@ -93,12 +96,15 @@ class Interval(DirectObject):
             # Otherwise use min of interval duration and offset + play duration
             self.endTime = min(self.duration, self.offset + duration)
 	assert(t0 <= self.endTime)
+        # Spawn task
         taskMgr.spawnMethodNamed(self.__playTask, self.name + '-play')
 
     def stop(self):
         """ stop()
         """
+        # Kill task
         taskMgr.removeTasksNamed(self.name + '-play')
+        # And stop freerunning (e.g. sound and anim) intervals
         self.setT(self.curr_t, event = IVAL_STOP)
 	return self.curr_t
 
@@ -108,6 +114,7 @@ class Interval(DirectObject):
         t = self.clock.getFrameTime()
         te = self.offset + ((t - self.startT) * self.scale)
         if (te < self.endTime):
+            # If first call, init intervals
 	    if (self.firstTime):
 		self.setT(te, event = IVAL_INIT)
 		self.firstTime = 0
@@ -127,6 +134,9 @@ class Interval(DirectObject):
 	return (space + self.name + ' dur: %.2f' % self.duration)
 
     def popupControls(self):
+        """ popupControls()
+            Popup control panel for interval.
+        """
         import fpformat
         import string
         # I moved this here because Toontown does not ship Tk
@@ -146,11 +156,14 @@ class Interval(DirectObject):
             # INIT interval
             s.setT(es.get(), event = IVAL_INIT)
         es.onPress = onPress
+        # To make sure you stop free running intervals
         es.onRelease = lambda s=self: s.stop()
+        # To update scale and execute intervals with IVAL_INIT
         es.onReturnRelease = lambda s=self, es = es: s.setT(es.get(),
                                                             event = IVAL_INIT)
         es.pack(expand = 1, fill = X)
         f = Frame(tl)
+        # Jump to start and end
         def toStart(s=self, es=es):
             s.stop()
             s.setT(0.0, event = IVAL_INIT)
@@ -158,6 +171,7 @@ class Interval(DirectObject):
             s.stop()
             s.setT(s.getDuration(), event = IVAL_INIT)
         jumpToStart = Button(tl, text = '<<', command = toStart)
+        # Stop/play buttons
         stop = Button(tl, text = 'Stop',
                       command = lambda s=self: s.stop())
         play = Button(
@@ -169,11 +183,11 @@ class Interval(DirectObject):
         stop.pack(side = LEFT, expand = 1, fill = X)
         jumpToEnd.pack(side = LEFT, expand = 1, fill = X)
         f.pack(expand = 1, fill = X)
-        # Add hook to update slider on changes in curr_t
+        # Add function to update slider during setT calls
         def update(t,es=es):
             es.set(t, fCommand = 0)
         self.setTHooks.append(update)
-        # Clear out hook on destroy
+        # Clear out function on destroy
         def onDestroy(e, s=self, u=update):
             if u in s.setTHooks:
                 s.setTHooks.remove(u)

+ 99 - 0
direct/src/interval/IntervalTest.py

@@ -72,3 +72,102 @@ def handleWaterDone():
     print 'water is done'
 
 messenger.accept('water-is-done', 1, handleWaterDone)
+
+
+### Using lambdas and functions ###
+# Using a lambda
+i1 = FunctionInterval(lambda: base.transitions.fadeOut())
+i2 = FunctionInterval(lambda: base.transitions.fadeIn())
+
+def caughtIt():
+    print 'Caught here-is-an-event'
+
+class DummyAcceptor(DirectObject):
+    pass
+
+da = DummyAcceptor()
+i3 = AcceptInterval(da, 'here-is-an-event', caughtIt)
+
+i4 = EventInterval('here-is-an-event')
+
+i5 = IgnoreInterval(da, 'here-is-an-event')
+
+# Using a function
+def printDone():
+    print 'done'
+
+i6 = FunctionInterval(printDone)
+
+# Create track
+t1 = Track([
+    # Fade out
+    (0.0, i1),
+    # Fade in
+    (2.0, i2),
+    # Accept event
+    (4.0, i3),
+    # Throw it,
+    (5.0, i4),
+    # Ignore event
+    (6.0, i5),
+    # Throw event again and see if ignore worked
+    (7.0, i4),
+    # Print done
+    (8.0, i6)], name = 'demo')
+
+print(t1)
+
+### Specifying interval start times during track construction ###
+# Interval start time can be specified relative to three different points:
+# PREVIOUS_END
+# PREVIOUS_START
+# TRACK_START
+
+startTime = 0.0
+def printStart():
+    global startTime
+    startTime = globalClock.getFrameTime()
+    print 'Start'
+
+def printPreviousStart():
+    global startTime
+    currTime = globalClock.getFrameTime()
+    print 'PREVIOUS_END %0.2f' % (currTime - startTime)
+
+def printPreviousEnd():
+    global startTime
+    currTime = globalClock.getFrameTime()
+    print 'PREVIOUS_END %0.2f' % (currTime - startTime)
+
+def printTrackStart():
+    global startTime
+    currTime = globalClock.getFrameTime()
+    print 'TRACK_START %0.2f' % (currTime - startTime)
+
+i1 = FunctionInterval(printStart)
+# Just to take time
+i2 = LerpPosInterval(camera, 2.0, Point3(0,10,5))
+# This will be relative to end of camera move
+i3 = FunctionInterval(printPreviousEnd)
+# Just to take time
+i4 = LerpPosInterval(camera, 2.0, Point3(0,0,5))
+# This will be relative to the start of the camera move
+i5 = FunctionInterval(printPreviousStart)
+# This will be relative to track start
+i6 = FunctionInterval(printTrackStart)
+# Create the track, if you don't specify offset type in tuple it defaults to
+# relative to TRACK_START (first entry below)
+t2 = Track([(0.0, i1),                 # i1 start at t = 0, duration = 0.0
+           (1.0, i2, TRACK_START),    # i2 start at t = 1, duration = 2.0
+           (2.0, i3, PREVIOUS_END),   # i3 start at t = 5, duration = 0.0
+           (1.0, i4, PREVIOUS_END),   # i4 start at t = 6, duration = 2.0
+           (3.0, i5, PREVIOUS_START), # i5 start at t = 9, duration = 0.0
+           (10.0, i6, TRACK_START)],  # i6 start at t = 10, duration = 0.0
+          name = 'startTimeDemo')
+
+print(t2)
+
+# Play tracks
+# mtrack.play()
+# t1.play()
+# t2.play()

+ 11 - 6
direct/src/interval/LerpInterval.py

@@ -9,18 +9,20 @@ class LerpInterval(Interval):
     def __init__(self, name, duration, functorFunc, blendType='noBlend'):
         """__init__(name, duration, functorFunc, blendType)
         """
+        # Record instance variables
         self.lerp = None
 	self.functorFunc = functorFunc
 	self.blendType = self.getBlend(blendType)
+        # Initialize superclass
 	Interval.__init__(self, name, duration)
     def updateFunc(self, t, event = IVAL_NONE):
 	""" updateFunc(t, event)
 	"""
-        # First check to see if we need to create the lerp
+        # Check to see if we need to create the lerp
 	if (event == IVAL_INIT):
 	    self.lerp = Lerp.Lerp(self.functorFunc(), self.duration, 
                                   self.blendType)
-        # Now evaluate the lerp
+        # Evaluate the lerp if its been created
         if self.lerp:
             self.lerp.setT(t)
     def getBlend(self, blendType):
@@ -51,7 +53,6 @@ class LerpPosInterval(LerpInterval):
 	def functorFunc(self=self, node=node, pos=pos, startPos=startPos,
 			other=other):
             import PosLerpFunctor
-
 	    assert(not node.isEmpty())
             if (other != None):
             	# lerp wrt other
@@ -227,7 +228,8 @@ class LerpPosHprScaleInterval(LerpInterval):
 	LerpInterval.__init__(self, name, duration, functorFunc, blendType)
 
 # Class used to execute a function over time.  Function can access fromData
-# and toData to perform blend
+# and toData to perform blend.  If fromData and toData not specified, will
+# execute the given function passing in values ranging from 0 to 1
 class LerpFunctionInterval(Interval):
     # Interval counter
     lerpFunctionIntervalNum = 1
@@ -252,21 +254,24 @@ class LerpFunctionInterval(Interval):
 	""" updateFunc(t, event)
 	"""
         # Evaluate the function
-        if (t == self.duration):
+        if (t >= self.duration):
             # Set to end value
 	    self.function(self.toData)            
         else:
-            # In the middle of the lerp, compute appropriate value
+            # In the middle of the lerp, compute appropriate blended value
             try:
                 bt = self.blendType(t/self.duration)
                 data = (self.fromData * (1 - bt)) + (self.toData * bt)
+                # Evaluate function
                 self.function(data)
             except ZeroDivisionError:
+                # Zero duration, just use endpoint
                 self.function(self.toData)
     def getBlend(self, blendType):
         """__getBlend(self, string)
         Return the C++ blend class corresponding to blendType string
         """
+        # Note, this is temporary until blend functions get exposed
         import LerpBlendHelpers
         def easeIn(t):
             x = t*t

+ 15 - 11
direct/src/interval/MultiTrack.py

@@ -4,26 +4,26 @@ from Interval import *
 from Track import *
 
 class MultiTrack(Interval):
-
+    # Name counter
     multiTrackNum = 1
-
-    # special methods
-    
+    # Class methods
     def __init__(self, trackList, name=None):
         """__init__(trackList, name)
         """
+        # Record track list
+	self.tlist = trackList
 	if (name == None):
-	    n = 'MultiTrack-%d' % MultiTrack.multiTrackNum
+	    name = 'MultiTrack-%d' % MultiTrack.multiTrackNum
 	    MultiTrack.multiTrackNum = MultiTrack.multiTrackNum + 1
-	else:
-	    n = name
-	self.tlist = trackList
+        # Duration is max of all track durations
 	duration = self.__computeDuration()
-	Interval.__init__(self, n, duration)
-
+        # Initialize superclass
+	Interval.__init__(self, name, duration)
+    
+    # Access track at given index
     def __getitem__(self, item):
         return self.tlist[item]
-
+    
     def __computeDuration(self):
 	""" __computeDuration()
 	    Returns the duration of the longest Track 
@@ -43,11 +43,15 @@ class MultiTrack(Interval):
             tEnd = track.getDuration()
             # Compare time with track's end times
             if (t > tEnd):
+                # If t > tEnd, only call if just crossing over
+                # or this is an IVAL_INIT event
                 if (self.prev_t < tEnd) or (event == IVAL_INIT):
                     track.setT(t, event)
             else:
+                # Update track
                 track.setT(t, event)
 
+    # Print out representation of MultiTrack
     def __repr__(self, indent=0):
 	""" __repr__(indent)
 	"""

+ 21 - 14
direct/src/interval/SoundInterval.py

@@ -7,36 +7,43 @@ class SoundInterval(Interval):
     # Name counter
     soundNum = 1
     # Class methods
-    def __init__(self, sound, loop=0, name=None):
+    # Create a sound interval
+    # If loop = 0, sound will play once, duration of the interval
+    # equals the duration of the sound
+    # If loop = 1, the sound will loop for the specified duration
+    # If no duration is specified, sound will loop for the duration
+    # of the sound, i.e. it will only play once.....usually, there
+    # seems to be some timing in the audio such that the stop doesn't
+    # kill the looping sound until the next time around if duration
+    # of the interval equals duration of the sound
+    def __init__(self, sound, loop = 0, duration = 0.0, name = None):
         """__init__(sound, loop, name)
         """
+        # Record instance variables
 	self.sound = sound
 	self.loop = loop
-	self.isPlaying = 0
+        # If no duration given use sound's duration as interval's duration
+        if duration == 0.0:
+            duration = self.sound.length()
         # Generate unique name if necessary
 	if (name == None):
 	    name = 'Sound-%d' % SoundInterval.soundNum
 	    SoundInterval.soundNum += 1
-        # Calculate duration
-	duration = self.sound.length()
         # Initialize superclass
 	Interval.__init__(self, name, duration)
-
     def updateFunc(self, t, event = IVAL_NONE):
 	""" updateFunc(t, event)
         Go to time t
 	"""
-        if (t == self.duration) or (event == IVAL_STOP):
-            # Stop sound if necessary
-	    if (self.isPlaying == 1):
-		self.isPlaying = 0
-		AudioManager.stop(self.sound)
+        # Update sound based on current time
+        if (t >= self.getDuration()) or (event == IVAL_STOP):
+            # If end of sound reached or stop event received, stop sound
+            AudioManager.stop(self.sound)
         elif (event == IVAL_INIT):
-            # Set flag
-	    self.isPlaying = 1
-            # If its within a 20th of a second of the start,
+            # IVAL_INIT event, start new sound
+            # If its within a 10th of a second of the start,
             # start at the beginning
-            if (t < 0.05):
+            if (t < 0.1):
                 t = 0.0
             # Start sound
             AudioManager.play(self.sound, t)

+ 31 - 19
direct/src/interval/Track.py

@@ -1,7 +1,6 @@
 """Track module: contains the Track class"""
 
 from Interval import *
-
 import types
 
 PREVIOUS_END = 1
@@ -33,9 +32,12 @@ class Track(Interval):
         # Initialize superclass
 	Interval.__init__(self, name, duration)
 
+    # Access interval at given index
     def __getitem__(self, item):
         return self.ilist[item]
 
+    # Create a list of this track's intervals, recording time
+    # and time type (relative to track start, previous start, previous end
     def __buildIlist(self, intervalList):
 	self.ilist = []
 	for i in intervalList:
@@ -43,39 +45,42 @@ class Track(Interval):
                 self.ilist.append([i, 0.0, PREVIOUS_END, 0.0, 0.0])
             elif (isinstance(i, types.ListType) or
                   isinstance(i, types.TupleType)):
-                t0 = i[0]
+                itime = i[0]
                 ival = i[1]
                 try:
                     type = i[2]
                 except IndexError:
                     type = TRACK_START
-                self.ilist.append([ival, t0, type, 0.0, 0.0])
+                self.ilist.append([ival, itime, type, 0.0, 0.0])
             else:
                 print 'Track.__buildIlist: Invalid intervallist entry'
 
+    # Compute duration of the track and precompute start and end time of
+    # each interval
     def __computeDuration(self):
 	""" __computeDuration()
 	"""
 	duration = 0.0
 	prev = None
         for idata in self.ilist:
-	    ival = idata[IDATA_IVAL]
-	    t0 = idata[IDATA_TIME]
-	    type = idata[IDATA_TYPE]
-	    assert(t0 >= 0.0)
+            ival = idata[IDATA_IVAL]
+            itime = idata[IDATA_TIME]
+            type = idata[IDATA_TYPE]
+	    assert(itime >= 0.0)
             # Compute fill time, time between end of last interval and
-            # start of this one
-	    fillTime = t0 
+            # start of this one.  Depend on interval type
+	    fillTime = itime 
 	    if (type == PREVIOUS_END):
                 pass
 	    elif (type == PREVIOUS_START):
 		if (prev != None):
-		    fillTime = t0 - prev.getDuration()
+		    fillTime = itime - prev.getDuration()
 	    elif (type == TRACK_START):
-		fillTime = t0 - duration
+		fillTime = itime - duration
 	    else:
 		Interval.notify.error(
 			'Track.__computeDuration(): unknown type: %d' % type)
+            # Check for overlap
 	    if (fillTime < 0.0):
 		Interval.notify.error(
 			'Track.__computeDuration(): overlap detected')
@@ -83,22 +88,25 @@ class Track(Interval):
             idata[IDATA_START] = duration + fillTime
             # Compute end time of interval
             idata[IDATA_END] = idata[IDATA_START] + ival.getDuration()
-            # Keep track of current duration
+            # Keep track of cumulative duration
 	    duration = idata[IDATA_END]
 	    prev = ival
 	return duration
 
-    def setIntervalStartTime(self, name, t0, type=TRACK_START):
-	""" setIntervalStartTime(name, t0, type)
+    def setIntervalStartTime(self, name, itime, type=TRACK_START):
+	""" setIntervalStartTime(name, itime, type)
 	"""
 	found = 0
+        # Check for interval in current interval list
         for idata in self.ilist:
+            # If found, update time and type
 	    if (idata[IDATA_IVAL].getName() == name):
-                idata[IDATA_TIME] = t0
+                idata[IDATA_TIME] = itime
                 idata[IDATA_TYPE] = type
 		found = 1
 		break
 	if (found):
+            # And recompute duration
 	    self.duration = self.__computeDuration()	
 	else:
 	    Interval.notify.warning(
@@ -107,6 +115,7 @@ class Track(Interval):
     def getIntervalStartTime(self, name):
 	""" getIntervalStartTime(name)
 	"""
+        # Search for interval of given name
 	for idata in self.ilist:
 	    if (idata[IDATA_IVAL].getName() == name):
 		return idata[IDATA_START]
@@ -117,6 +126,7 @@ class Track(Interval):
     def __getIntervalStartTime(self, interval):
 	""" __getIntervalStartTime(interval)
 	"""
+        # Search for given interval
 	for idata in self.ilist:
 	    if (idata[IDATA_IVAL] == interval):
 		return idata[IDATA_START]
@@ -127,6 +137,7 @@ class Track(Interval):
     def getIntervalEndTime(self, name):
 	""" getIntervalEndTime(name)
 	"""
+        # Search for interval of given name
 	for idata in self.ilist:
 	    if (idata[IDATA_IVAL].getName() == name):	
 		return idata[IDATA_END]
@@ -152,8 +163,7 @@ class Track(Interval):
             currentInterval = None
             # First entry, re-init instance variables
             if (event == IVAL_INIT):
-                # Initialize prev_t to max t of track
-                #self.prev_t = self.getDuration()
+                # Initialize prev_t to 0.0
                 self.prev_t = 0.0
                 # Clear record of currentInterval
                 self.currentInterval = None
@@ -166,7 +176,7 @@ class Track(Interval):
             # start of an interval ((prev_t > tStart) and (t < tStart))
             # then execute that interval at its start value
 	    for ival, itime, itype, tStart, tEnd in self.ilist:
-                # Compare time with ival's start/end times
+                # Compare time with each ival's start/end times
                 if (t < tStart):
                     if (self.prev_t > tStart) and (event != IVAL_STOP):
                         # We just crossed the start of this interval
@@ -200,11 +210,13 @@ class Track(Interval):
             # Record current interval (may be None)
             self.currentInterval = currentInterval
 
+    # Create a printable representation of the track
     def __repr__(self, indent=0):
 	""" __repr__(indent)
 	"""
 	str = Interval.__repr__(self, indent) + '\n'
-	for idata in self.ilist:	
+	for idata in self.ilist:
+            # Tack on start and end time for this interval
 	    str = (str + idata[IDATA_IVAL].__repr__(indent+1) +
                    (' start: %0.2f end: %0.2f' %
                     (idata[IDATA_START], idata[IDATA_END])) + '\n'