Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
0fd177564e

+ 73 - 0
direct/src/directdevices/DirectJoybox.py

@@ -61,6 +61,8 @@ class DirectJoybox(PandaObject):
         # Pick initial mode
         # Pick initial mode
         self.updateFunc = self.joyboxFly
         self.updateFunc = self.joyboxFly
         self.modeName = 'Joe Mode'
         self.modeName = 'Joe Mode'
+        # Auxiliary data
+        self.auxData = []
         # Button registry
         # Button registry
         self.addButtonEvents()
         self.addButtonEvents()
         # Spawn update task
         # Spawn update task
@@ -206,6 +208,12 @@ class DirectJoybox(PandaObject):
         self.modifier = [1,1,1,-1,-1,0]
         self.modifier = [1,1,1,-1,-1,0]
         self.setMode(self.joyboxFly, 'Joe Mode')
         self.setMode(self.joyboxFly, 'Joe Mode')
 
 
+    def lucMode(self):
+        self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
+                        R_TWIST, L_TWIST, L_LEFT_RIGHT]
+        self.modifier = [1,1,1,-1,-1,0]
+        self.setMode(self.joyboxFly, 'Luc Mode')
+
     def driveMode(self):
     def driveMode(self):
         self.mapping = [L_LEFT_RIGHT, R_FWD_BACK, R_TWIST,
         self.mapping = [L_LEFT_RIGHT, R_FWD_BACK, R_TWIST,
                         R_LEFT_RIGHT, L_FWD_BACK, NULL_AXIS]
                         R_LEFT_RIGHT, L_FWD_BACK, NULL_AXIS]
@@ -242,6 +250,71 @@ class DirectJoybox(PandaObject):
         self.modifier = [1,1,-1,-1,-1, 1]
         self.modifier = [1,1,-1,-1,-1, 1]
         self.setMode(self.joyboxFly, 'Walkthru Mode')
         self.setMode(self.joyboxFly, 'Walkthru Mode')
 
 
+    def spaceMode(self):
+        self.setMode(self.spaceFly, 'Space Mode')
+
+    def spaceFly(self):
+        # Do nothing if no nodePath selected
+        if self.nodePath == None:
+            return
+        hprScale = (self.analogs.normalizeChannel(L_SLIDE, 0.1, 100) *
+                    DirectJoybox.hprMultiplier)
+        posScale = (self.analogs.normalizeChannel(R_SLIDE, 0.1, 100) *
+                    DirectJoybox.xyzMultiplier)
+        dr = -1 * hprScale * self.aList[R_TWIST] * self.deltaTime
+        dp = -1 * hprScale * self.aList[R_FWD_BACK] * self.deltaTime
+        dh = -1 * hprScale * self.aList[R_LEFT_RIGHT] * self.deltaTime
+        self.nodePath.setHpr(self.nodePath, dh, dp, dr)
+        dy = posScale * self.aList[L_FWD_BACK] * self.deltaTime
+        self.nodePath.setY(self.nodePath, dy)
+
+    def planetMode(self, auxData = []):
+        self.auxData = auxData
+        self.setMode(self.planetFly, 'Space Mode')
+
+    def planetFly(self):
+        # Do nothing if no nodePath selected
+        if self.nodePath == None:
+            return
+        hprScale = (self.analogs.normalizeChannel(L_SLIDE, 0.1, 100) *
+                    DirectJoybox.hprMultiplier)
+        posScale = (self.analogs.normalizeChannel(R_SLIDE, 0.1, 100) *
+                    DirectJoybox.xyzMultiplier)
+        dr = -1 * hprScale * self.aList[R_TWIST] * self.deltaTime
+        dp = -1 * hprScale * self.aList[R_FWD_BACK] * self.deltaTime
+        dh = -1 * hprScale * self.aList[R_LEFT_RIGHT] * self.deltaTime
+        self.nodePath.setHpr(self.nodePath, dh, dp, dr)
+        dy = posScale * self.aList[L_FWD_BACK] * self.deltaTime
+        dPos = VBase3(0,dy,0)
+        for planet, radius in self.auxData:
+            # Are we within min radius?
+            # How far above planet are we?
+            np2planet = Vec3(self.nodePath.getPos(planet))
+            # Compute dist
+            offsetDist = np2planet.length()
+            # Too high, never mind
+            if offsetDist > (1.2 * radius):
+                pass
+            else:
+                # Getting close, slow things down
+                # Compute normal vector through node Path
+                oNorm = Vec3()
+                oNorm.assign(np2planet)
+                oNorm.normalize()
+                # Xform fly vec to planet space
+                dPlanet = self.nodePath.getMat(planet).xformVec(Vec3(0, dy, 0))
+                # Compute radial component of fly vec
+                radialComponent = oNorm * oNorm.dot(dPlanet)
+                # If within transition zone, begin subtracting radial component
+                above = offsetDist - radius
+                sf = max(1.0 - (max(above, 0.0)/(0.2 * radius)), 0.0)
+                if offsetDist < radius:
+                    dPlanet -= radialComponent * (sf * sf)
+                # Convert back to node path space
+                dPos.assign(planet.getMat(self.nodePath).xformVec(dPlanet))
+        # Set pos accordingly
+        self.nodePath.setPos(self.nodePath, dPos)
+
     def orbitMode(self):
     def orbitMode(self):
         self.setMode(self.orbitFly, 'Orbit Mode')
         self.setMode(self.orbitFly, 'Orbit Mode')
 
 

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

@@ -23,9 +23,16 @@ BOAT_END = boatTrack.getIntervalEndTime('boatpath')
 
 
 # Make the dock lerp up so that it's up when the boat reaches the end of
 # Make the dock lerp up so that it's up when the boat reaches the end of
 # its mopath
 # its mopath
+<<<<<<< IntervalTest.py
+dockLerp = LerpPosHprInterval('lerp', dock,
+                              Point3(0, 0, -5),
+                              hpr = Vec3(0, 0, 0),
+                              5.0)
+=======
 pos = Point3(0, 0, -5)
 pos = Point3(0, 0, -5)
 hpr = Vec3(0, 0, 0)
 hpr = Vec3(0, 0, 0)
 dockLerp = LerpPosHprInterval(dock, 5.0, pos, hpr, name='dock-lerp')
 dockLerp = LerpPosHprInterval(dock, 5.0, pos, hpr, name='dock-lerp')
+>>>>>>> 1.12
 # We need the dock's state to be defined before the lerp
 # We need the dock's state to be defined before the lerp
 dockPos = PosHprInterval(dock, dock.getPos(), dock.getHpr(), 1.0, 'dockpos')
 dockPos = PosHprInterval(dock, dock.getPos(), dock.getHpr(), 1.0, 'dockpos')
 dockUpTime = BOAT_END - dockLerp.getDuration()
 dockUpTime = BOAT_END - dockLerp.getDuration()

+ 114 - 180
direct/src/tkpanels/MopathRecorder.py

@@ -110,8 +110,7 @@ class MopathRecorder(AppShell, PandaObject):
         self.keyframeHook = 'f10'
         self.keyframeHook = 'f10'
         # Curve fitter object
         # Curve fitter object
         self.lastPos = Point3(0)
         self.lastPos = Point3(0)
-        self.xyzCurveFitter = CurveFitter()
-        self.hprCurveFitter = CurveFitter()
+        self.curveFitter = CurveFitter()
         # Curve variables
         # Curve variables
         # Number of ticks per parametric unit
         # Number of ticks per parametric unit
         self.numTicks = 1
         self.numTicks = 1
@@ -119,16 +118,16 @@ class MopathRecorder(AppShell, PandaObject):
         # This just affects the visual appearance of the curve
         # This just affects the visual appearance of the curve
         self.numSegs = 40
         self.numSegs = 40
         # The nurbs curves
         # The nurbs curves
-        self.xyzNurbsCurve = None
-        self.hprNurbsCurve = None
+        self.curveCollection = None
         # Curve drawers
         # Curve drawers
-        self.xyzNurbsCurveDrawer = NurbsCurveDrawer(NurbsCurve())
-        self.xyzNurbsCurveDrawer.setNumSegs(self.numSegs)
-        self.xyzNurbsCurveDrawer.setShowHull(0)
-        self.xyzNurbsCurveDrawer.setShowCvs(0)
-        self.xyzNurbsCurveDrawer.setNumTicks(0)
+        self.nurbsCurveDrawer = NurbsCurveDrawer()
+        self.nurbsCurveDrawer.setCurves(ParametricCurveCollection())
+        self.nurbsCurveDrawer.setNumSegs(self.numSegs)
+        self.nurbsCurveDrawer.setShowHull(0)
+        self.nurbsCurveDrawer.setShowCvs(0)
+        self.nurbsCurveDrawer.setNumTicks(0)
         self.curveNodePath = self.recorderNodePath.attachNewNode(
         self.curveNodePath = self.recorderNodePath.attachNewNode(
-            self.xyzNurbsCurveDrawer.getGeomNode())
+            self.nurbsCurveDrawer.getGeomNode())
         # Playback variables
         # Playback variables
         self.playbackTime = 0.0
         self.playbackTime = 0.0
         self.loopPlayback = 1
         self.loopPlayback = 1
@@ -677,23 +676,23 @@ class MopathRecorder(AppShell, PandaObject):
             self.tangentGroup.hide()
             self.tangentGroup.hide()
 
 
     def curveEditTask(self,state):
     def curveEditTask(self,state):
-        if self.xyzNurbsCurve != None:
+        if self.curveCollection != None:
             # Update curve position
             # Update curve position
             if self.manipulandumId == self.playbackMarker.id():
             if self.manipulandumId == self.playbackMarker.id():
                 # Show playback marker
                 # Show playback marker
                 self.playbackMarker.getChild(0).show()
                 self.playbackMarker.getChild(0).show()
                 pos = Point3(0)
                 pos = Point3(0)
+                hpr = Point3(0)
                 pos = self.playbackMarker.getPos(self.nodePathParent)
                 pos = self.playbackMarker.getPos(self.nodePathParent)
-                self.xyzNurbsCurve.adjustPoint(
+                hpr = self.playbackMarker.getHpr(self.nodePathParent)
+                self.curveCollection.getXyzCurve().adjustPoint(
                     self.playbackTime,
                     self.playbackTime,
                     pos[0], pos[1], pos[2])
                     pos[0], pos[1], pos[2])
-                hpr = Point3(0)
-                hpr = self.playbackMarker.getHpr(self.nodePathParent)
-                self.hprNurbsCurve.adjustPoint(
+                self.curveCollection.getHprCurve().adjustPoint(
                     self.playbackTime,
                     self.playbackTime,
                     hpr[0], hpr[1], hpr[2])
                     hpr[0], hpr[1], hpr[2])
-                self.hprNurbsCurve.recompute()
-                self.xyzNurbsCurveDrawer.draw()
+                # Note: this calls recompute on the curves
+                self.nurbsCurveDrawer.draw()
             # Update tangent
             # Update tangent
             if self.manipulandumId == self.tangentMarker.id():
             if self.manipulandumId == self.tangentMarker.id():
                 # If manipulating marker, update tangent
                 # If manipulating marker, update tangent
@@ -706,16 +705,18 @@ class MopathRecorder(AppShell, PandaObject):
                     self.playbackMarker.getMat(
                     self.playbackMarker.getMat(
                     self.nodePathParent).xformVec(tan))
                     self.nodePathParent).xformVec(tan))
                 # Update nurbs curve
                 # Update nurbs curve
-                self.xyzNurbsCurve.adjustTangent(
+                self.curveCollection.getXyzCurve().adjustTangent(
                     self.playbackTime,
                     self.playbackTime,
                     tan2Curve[0], tan2Curve[1], tan2Curve[2])
                     tan2Curve[0], tan2Curve[1], tan2Curve[2])
-                self.xyzNurbsCurveDrawer.draw()
+                # Note: this calls recompute on the curves
+                self.nurbsCurveDrawer.draw()
             else:
             else:
                 # Show playback marker
                 # Show playback marker
                 self.playbackMarker.getChild(0).show()
                 self.playbackMarker.getChild(0).show()
                 # Update tangent marker line
                 # Update tangent marker line
                 tan = Point3(0)
                 tan = Point3(0)
-                self.xyzNurbsCurve.getTangent(self.playbackTime, tan)
+                self.curveCollection.getXyzCurve().getTangent(
+                    self.playbackTime, tan)
                 # Transform this point to playback marker space
                 # Transform this point to playback marker space
                 tan.assign(
                 tan.assign(
                     self.nodePathParent.getMat(
                     self.nodePathParent.getMat(
@@ -758,18 +759,16 @@ class MopathRecorder(AppShell, PandaObject):
     def savePointSet(self):
     def savePointSet(self):
         # Use curve to compute default point set at 30 fps
         # Use curve to compute default point set at 30 fps
         # Keep a handle on the original curve
         # Keep a handle on the original curve
-        xyzCurve = self.xyzNurbsCurve
-        hprCurve = self.hprNurbsCurve
+        curveCollection = self.curveCollection
         # Sample curves
         # Sample curves
-        self.maxT = self.xyzNurbsCurve.getMaxT()
+        self.maxT = self.curveCollection.getMaxT()
         self.setNumSamples(self.maxT * 30.0)
         self.setNumSamples(self.maxT * 30.0)
         self.sampleCurve()
         self.sampleCurve()
         # Restore curves to those loaded in
         # Restore curves to those loaded in
-        self.xyzNurbsCurve = xyzCurve
-        self.hprNurbsCurve = hprCurve
+        self.curveCollection = curveCollection
         # Redraw
         # Redraw
-        self.xyzNurbsCurveDrawer.setCurve(self.xyzNurbsCurve)
-        self.xyzNurbsCurveDrawer.draw()
+        self.nurbsCurveDrawer.setCurves(self.curveCollection)
+        self.nurbsCurveDrawer.draw()
 
 
     def createNewPointSet(self):
     def createNewPointSet(self):
         self.pointSetName = self.name + '-ps-' + `self.pointSetCount`
         self.pointSetName = self.name + '-ps-' + `self.pointSetCount`
@@ -790,12 +789,10 @@ class MopathRecorder(AppShell, PandaObject):
         self.pointSet = self.pointSetDict.get(name, None)
         self.pointSet = self.pointSetDict.get(name, None)
         # Reload points into curve fitter
         # Reload points into curve fitter
         # Reset curve fitters
         # Reset curve fitters
-        self.xyzCurveFitter.reset()
-        self.hprCurveFitter.reset()
+        self.curveFitter.reset()
         for time, pos, hpr in self.pointSet:
         for time, pos, hpr in self.pointSet:
             # Add it to the curve fitters
             # Add it to the curve fitters
-            self.xyzCurveFitter.addPoint(time, pos )
-            self.hprCurveFitter.addPoint(time, hpr)
+            self.curveFitter.addXyzHpr(time, pos, hpr)
         # Compute curve
         # Compute curve
         self.computeCurves()
         self.computeCurves()
 
 
@@ -806,15 +803,15 @@ class MopathRecorder(AppShell, PandaObject):
             self.curveNodePath.hide()
             self.curveNodePath.hide()
         
         
     def setKnotVis(self):
     def setKnotVis(self):
-        self.xyzNurbsCurveDrawer.setShowKnots(
+        self.nurbsCurveDrawer.setShowKnots(
             self.getVariable('Style', 'Show Knots').get())
             self.getVariable('Style', 'Show Knots').get())
 
 
     def setCvVis(self):
     def setCvVis(self):
-        self.xyzNurbsCurveDrawer.setShowCvs(
+        self.nurbsCurveDrawer.setShowCvs(
             self.getVariable('Style', 'Show CVs').get())
             self.getVariable('Style', 'Show CVs').get())
         
         
     def setHullVis(self):
     def setHullVis(self):
-        self.xyzNurbsCurveDrawer.setShowHull(
+        self.nurbsCurveDrawer.setShowHull(
             self.getVariable('Style', 'Show Hull').get())
             self.getVariable('Style', 'Show Hull').get())
         
         
     def setTraceVis(self):
     def setTraceVis(self):
@@ -831,33 +828,33 @@ class MopathRecorder(AppShell, PandaObject):
 
 
     def setNumSegs(self, value):
     def setNumSegs(self, value):
         self.numSegs = int(value)
         self.numSegs = int(value)
-        self.xyzNurbsCurveDrawer.setNumSegs(self.numSegs)
+        self.nurbsCurveDrawer.setNumSegs(self.numSegs)
         
         
     def setNumTicks(self, value):
     def setNumTicks(self, value):
-        self.xyzNurbsCurveDrawer.setNumTicks(float(value))
+        self.nurbsCurveDrawer.setNumTicks(float(value))
         
         
     def setTickScale(self, value):
     def setTickScale(self, value):
-        self.xyzNurbsCurveDrawer.setTickScale(float(value))
+        self.nurbsCurveDrawer.setTickScale(float(value))
 
 
     def setPathColor(self, color):
     def setPathColor(self, color):
-        self.xyzNurbsCurveDrawer.setColor(
+        self.nurbsCurveDrawer.setColor(
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
-        self.xyzNurbsCurveDrawer.draw()
+        self.nurbsCurveDrawer.draw()
 
 
     def setKnotColor(self, color):
     def setKnotColor(self, color):
-        self.xyzNurbsCurveDrawer.setKnotColor(
+        self.nurbsCurveDrawer.setKnotColor(
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
 
 
     def setCvColor(self, color):
     def setCvColor(self, color):
-        self.xyzNurbsCurveDrawer.setCvColor(
+        self.nurbsCurveDrawer.setCvColor(
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
 
 
     def setTickColor(self, color):
     def setTickColor(self, color):
-        self.xyzNurbsCurveDrawer.setTickColor(
+        self.nurbsCurveDrawer.setTickColor(
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
 
 
     def setHullColor(self, color):
     def setHullColor(self, color):
-        self.xyzNurbsCurveDrawer.setHullColor(
+        self.nurbsCurveDrawer.setHullColor(
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
             color[0]/255.0,color[1]/255.0,color[2]/255.0)
 
 
     def setStartStopHook(self, event = None):
     def setStartStopHook(self, event = None):
@@ -881,11 +878,9 @@ class MopathRecorder(AppShell, PandaObject):
     def reset(self):
     def reset(self):
         self.pointSet = []
         self.pointSet = []
         self.hasPoints = 0
         self.hasPoints = 0
-        self.xyzNurbsCurve = None
-        self.hprNurbsCurve = None
-        self.xyzCurveFitter.reset()
-        self.hprCurveFitter.reset()
-        self.xyzNurbsCurveDrawer.hide()
+        self.curveCollection = None
+        self.curveFitter.reset()
+        self.nurbsCurveDrawer.hide()
         
         
     def setSamplingMode(self, mode):
     def setSamplingMode(self, mode):
         self.samplingMode = mode
         self.samplingMode = mode
@@ -921,10 +916,9 @@ class MopathRecorder(AppShell, PandaObject):
             taskMgr.removeTasksNamed(self.name + '-recordTask')
             taskMgr.removeTasksNamed(self.name + '-recordTask')
             taskMgr.removeTasksNamed(self.name + '-curveEditTask')
             taskMgr.removeTasksNamed(self.name + '-curveEditTask')
             # Remove old curve
             # Remove old curve
-            self.xyzNurbsCurveDrawer.hide()
+            self.nurbsCurveDrawer.hide()
             # Reset curve fitters
             # Reset curve fitters
-            self.xyzCurveFitter.reset()
-            self.hprCurveFitter.reset()
+            self.curveFitter.reset()
             # Update sampling mode button if necessary
             # Update sampling mode button if necessary
             if self.samplingMode == 'Continuous':
             if self.samplingMode == 'Continuous':
                 self.disableKeyframeButton()
                 self.disableKeyframeButton()
@@ -1073,8 +1067,7 @@ class MopathRecorder(AppShell, PandaObject):
         # Add it to the point set
         # Add it to the point set
         self.pointSet.append([time, pos, hpr])
         self.pointSet.append([time, pos, hpr])
         # Add it to the curve fitters
         # Add it to the curve fitters
-        self.xyzCurveFitter.addPoint(time, pos )
-        self.hprCurveFitter.addPoint(time, hpr)
+        self.curveFitter.addXyzHpr(time, pos, hpr)
         # Update trace now if recording keyframes
         # Update trace now if recording keyframes
         if (self.samplingMode == 'Keyframe'):
         if (self.samplingMode == 'Keyframe'):
             self.trace.reset()
             self.trace.reset()
@@ -1084,24 +1077,18 @@ class MopathRecorder(AppShell, PandaObject):
 
 
     def computeCurves(self):
     def computeCurves(self):
         # Check to make sure curve fitters have points
         # Check to make sure curve fitters have points
-        if ((self.xyzCurveFitter.getNumSamples() == 0) or
-            (self.hprCurveFitter.getNumSamples() == 0)):
+        if (self.curveFitter.getNumSamples() == 0):
             print 'MopathRecorder.computeCurves: Must define curve first'
             print 'MopathRecorder.computeCurves: Must define curve first'
             return
             return
         # Create curves
         # Create curves
         # XYZ
         # XYZ
-        self.xyzCurveFitter.sortPoints()
-        self.xyzCurveFitter.computeTangents(1)
-        self.xyzNurbsCurve = self.xyzCurveFitter.makeNurbs()
-        self.xyzNurbsCurve.setCurveType(PCTXYZ)
-        self.xyzNurbsCurveDrawer.setCurve(self.xyzNurbsCurve)
-        self.xyzNurbsCurveDrawer.draw()
-        # HPR
-        self.hprCurveFitter.sortPoints()
-        self.hprCurveFitter.wrapHpr()
-        self.hprCurveFitter.computeTangents(1)
-        self.hprNurbsCurve = self.hprCurveFitter.makeNurbs()
-        self.hprNurbsCurve.setCurveType(PCTHPR)
+        self.curveFitter.sortPoints()
+        self.curveFitter.wrapHpr()
+        self.curveFitter.computeTangents(1)
+        # This is really a collection
+        self.curveCollection = self.curveFitter.makeNurbs()
+        self.nurbsCurveDrawer.setCurves(self.curveCollection)
+        self.nurbsCurveDrawer.draw()
         # Update widget based on new curve
         # Update widget based on new curve
         self.updateWidgets()
         self.updateWidgets()
 
 
@@ -1113,11 +1100,11 @@ class MopathRecorder(AppShell, PandaObject):
         self.trace.show()
         self.trace.show()
 
 
     def updateWidgets(self):
     def updateWidgets(self):
-        if not self.xyzNurbsCurve:
+        if not self.curveCollection:
             return
             return
         self.fAdjustingValues = 1
         self.fAdjustingValues = 1
         # Widgets depending on max T
         # Widgets depending on max T
-        maxT = '%.2f' % self.xyzNurbsCurve.getMaxT()
+        maxT = '%.2f' % self.curveCollection.getMaxT()
         # Playback controls
         # Playback controls
         self.getWidget('Playback', 'Time').configure(max = maxT)
         self.getWidget('Playback', 'Time').configure(max = maxT)
         self.getVariable('Resample', 'Path Duration').set(maxT)
         self.getVariable('Resample', 'Path Duration').set(maxT)
@@ -1150,7 +1137,7 @@ class MopathRecorder(AppShell, PandaObject):
         widget.set(float(maxT))
         widget.set(float(maxT))
         self.maxT = float(maxT)
         self.maxT = float(maxT)
         # Widgets depending on number of samples
         # Widgets depending on number of samples
-        numSamples = self.xyzCurveFitter.getNumSamples()
+        numSamples = self.curveFitter.getNumSamples()
         widget = self.getWidget('Resample', 'Points Between Samples')
         widget = self.getWidget('Resample', 'Points Between Samples')
         widget.configure(max=numSamples)
         widget.configure(max=numSamples)
         widget = self.getWidget('Resample', 'Num. Samples')
         widget = self.getWidget('Resample', 'Num. Samples')
@@ -1240,8 +1227,9 @@ class MopathRecorder(AppShell, PandaObject):
                     self.playbackMarker.show()
                     self.playbackMarker.show()
                     # Initialize tangent marker position
                     # Initialize tangent marker position
                     tan = Point3(0)
                     tan = Point3(0)
-                    if self.xyzNurbsCurve != None:
-                        self.xyzNurbsCurve.getTangent(self.playbackTime, tan)
+                    if self.curveCollection != None:
+                        self.curveCollection.getXyzCurve().getTangent(
+                            self.playbackTime, tan)
                     self.tangentMarker.setPos(tan)
                     self.tangentMarker.setPos(tan)
                 else:
                 else:
                     self.playbackMarker.hide()
                     self.playbackMarker.hide()
@@ -1288,20 +1276,17 @@ class MopathRecorder(AppShell, PandaObject):
         self.loopPlayback = self.getVariable('Playback', 'Loop').get()
         self.loopPlayback = self.getVariable('Playback', 'Loop').get()
 
 
     def playbackGoTo(self, time):
     def playbackGoTo(self, time):
-        if (self.xyzNurbsCurve == None) and (self.hprNurbsCurve == None):
+        if self.curveCollection == None:
             return
             return
         self.playbackTime = CLAMP(time, 0.0, self.maxT)
         self.playbackTime = CLAMP(time, 0.0, self.maxT)
-        if self.xyzNurbsCurve != None:
+        if self.curveCollection != None:
             pos = Point3(0)
             pos = Point3(0)
-            self.xyzNurbsCurve.getPoint(self.playbackTime, pos)
-            self.playbackNodePath.setPos(self.nodePathParent, pos)
-        if self.hprNurbsCurve != None:
             hpr = Point3(0)
             hpr = Point3(0)
-            self.hprNurbsCurve.getPoint(self.playbackTime, hpr)
-            self.playbackNodePath.setHpr(self.nodePathParent, hpr)
+            self.curveCollection.evaluate(self.playbackTime, pos, hpr)
+            self.playbackNodePath.setPosHpr(self.nodePathParent, pos, hpr)
 
 
     def startPlayback(self):
     def startPlayback(self):
-        if (self.xyzNurbsCurve == None) and (self.hprNurbsCurve == None):
+        if self.curveCollection == None:
             return
             return
         # Kill any existing tasks
         # Kill any existing tasks
         self.stopPlayback()
         self.stopPlayback()
@@ -1360,7 +1345,7 @@ class MopathRecorder(AppShell, PandaObject):
 
 
     def jumpToEndOfPlayback(self):
     def jumpToEndOfPlayback(self):
         self.stopPlayback()
         self.stopPlayback()
-        if self.xyzNurbsCurve != None:
+        if self.curveCollection != None:
             self.getWidget('Playback', 'Time').set(self.maxT)
             self.getWidget('Playback', 'Time').set(self.maxT)
 
 
     def startStopPlayback(self):
     def startStopPlayback(self):
@@ -1373,69 +1358,49 @@ class MopathRecorder(AppShell, PandaObject):
         self.desampleFrequency = frequency
         self.desampleFrequency = frequency
         
         
     def desampleCurve(self):
     def desampleCurve(self):
-        if ((self.xyzCurveFitter.getNumSamples() == 0) or
-            (self.hprCurveFitter.getNumSamples() == 0)):
+        if (self.curveFitter.getNumSamples() == 0):
             print 'MopathRecorder.desampleCurve: Must define curve first'
             print 'MopathRecorder.desampleCurve: Must define curve first'
             return
             return
         # NOTE: This is destructive, points will be deleted from curve fitter
         # NOTE: This is destructive, points will be deleted from curve fitter
-        self.xyzCurveFitter.desample(self.desampleFrequency)
-        self.hprCurveFitter.desample(self.desampleFrequency)
+        self.curveFitter.desample(self.desampleFrequency)
         self.computeCurves()
         self.computeCurves()
         # Get new point set based on newly created curve
         # Get new point set based on newly created curve
         self.createNewPointSet()
         self.createNewPointSet()
-        for i in range(self.xyzCurveFitter.getNumSamples()):
-            time = self.xyzCurveFitter.getSampleT(i)
-            pos = Point3(self.xyzCurveFitter.getSamplePoint(i))
-            hpr = Point3(self.hprCurveFitter.getSamplePoint(i))
+        for i in range(self.curveFitter.getNumSamples()):
+            time = self.curveFitter.getSampleT(i)
+            pos = Point3(self.curveFitter.getSampleXyz(i))
+            hpr = Point3(self.curveFitter.getSampleHpr(i))
             self.pointSet.append([time, pos, hpr])
             self.pointSet.append([time, pos, hpr])
 
 
     def setNumSamples(self, numSamples):
     def setNumSamples(self, numSamples):
         self.numSamples = int(numSamples)
         self.numSamples = int(numSamples)
         
         
     def sampleCurve(self, even = 'None Given'):
     def sampleCurve(self, even = 'None Given'):
-        if (self.xyzNurbsCurve == None) and (self.hprNurbsCurve == None):
+        if self.curveCollection == None:
             print 'MopathRecorder.sampleCurve: Must define curve first'
             print 'MopathRecorder.sampleCurve: Must define curve first'
             return
             return
         # Reset curve fitters
         # Reset curve fitters
-        self.xyzCurveFitter.reset()
-        self.hprCurveFitter.reset()
+        self.curveFitter.reset()
         # Get new data points based on given curve
         # Get new data points based on given curve
         if even == 'None Given':
         if even == 'None Given':
             even = self.fEven
             even = self.fEven
-        self.xyzCurveFitter.sample(
-            self.xyzNurbsCurve, self.numSamples, even)
-        if self.fForward:
-            # Use xyz curve tangent
-            tanPt = Point3(0)
-            lookAtCS = self.playbackMarker.attachNewNode('lookAt')
-        # Now sample the hprNurbsCurve using the same delta T
-        for i in range(self.numSamples):
-            t = self.maxT * (i / float(self.numSamples - 1))
-            hpr = Point3(0)
-            if self.fForward:
-                # Use xyz curve tangent
-                self.xyzNurbsCurve.getTangent(t, tanPt)
-                # Transform this point to playback marker space
-                tanPt.assign(
-                    self.nodePathParent.getMat(
-                    self.playbackMarker).xformVec(tanPt))
-                lookAtCS.lookAt(tanPt, Z_AXIS)
-                hpr = lookAtCS.getHpr(self.nodePathParent)
-            else:
-                # Sample existing hpr curve
-                self.hprNurbsCurve.getPoint(t, hpr)
-            self.hprCurveFitter.addPoint(t, hpr)
-        # Clean up
+        # Make even if necessary
+        if even:
+            # Note: segments_per_unit = 2 seems to give a good fit
+            self.curveCollection.makeEven(self.maxT, 2)
+        # Face forward if necessary
         if self.fForward:
         if self.fForward:
-            lookAtCS.removeNode()
+            # MRM: To be added, face forward
+            pass
+        self.curveFitter.sample(self.curveCollection, self.numSamples)
         # Now recompute curves
         # Now recompute curves
         self.computeCurves()
         self.computeCurves()
         # Get new point set based on newly created curve
         # Get new point set based on newly created curve
         self.createNewPointSet()
         self.createNewPointSet()
-        for i in range(self.xyzCurveFitter.getNumSamples()):
-            time = self.xyzCurveFitter.getSampleT(i)
-            pos = Point3(self.xyzCurveFitter.getSamplePoint(i))
-            hpr = Point3(self.hprCurveFitter.getSamplePoint(i))
+        for i in range(self.curveFitter.getNumSamples()):
+            time = self.curveFitter.getSampleT(i)
+            pos = Point3(self.curveFitter.getSampleXyz(i))
+            hpr = Point3(self.curveFitter.getSampleHpr(i))
             self.pointSet.append([time, pos, hpr])
             self.pointSet.append([time, pos, hpr])
 
 
     def setEven(self):
     def setEven(self):
@@ -1449,33 +1414,28 @@ class MopathRecorder(AppShell, PandaObject):
         self.setPathDurationTo(newMaxT)
         self.setPathDurationTo(newMaxT)
         
         
     def setPathDurationTo(self, newMaxT):
     def setPathDurationTo(self, newMaxT):
+        # Compute scale factor
         sf = newMaxT/self.maxT
         sf = newMaxT/self.maxT
-        # Scale xyz curve knots
-        for i in range(self.xyzNurbsCurve.getNumKnots()):
-            self.xyzNurbsCurve.setKnot(i, sf * self.xyzNurbsCurve.getKnot(i))
-        self.xyzNurbsCurve.recompute()
-        # Scale hpr curve knots
-        for i in range(self.hprNurbsCurve.getNumKnots()):
-            self.hprNurbsCurve.setKnot(i, sf * self.hprNurbsCurve.getKnot(i))
-        self.hprNurbsCurve.recompute()
+        # Scale curve collection
+        self.curveCollection.resetMaxT(newMaxT)
         # Scale point set
         # Scale point set
         # Save handle to old point set
         # Save handle to old point set
         oldPointSet = self.pointSet
         oldPointSet = self.pointSet
         # Create new point set
         # Create new point set
         self.createNewPointSet()
         self.createNewPointSet()
         # Reset curve fitters
         # Reset curve fitters
-        self.xyzCurveFitter.reset()
-        self.hprCurveFitter.reset()
+        self.curveFitter.reset()
         # Now scale values
         # Now scale values
         for time, pos, hpr in oldPointSet:
         for time, pos, hpr in oldPointSet:
             newTime = time * sf
             newTime = time * sf
             # Update point set
             # Update point set
             self.pointSet.append([newTime, Point3(pos), Point3(hpr)])
             self.pointSet.append([newTime, Point3(pos), Point3(hpr)])
             # Add it to the curve fitters
             # Add it to the curve fitters
-            self.xyzCurveFitter.addPoint(newTime, pos )
-            self.hprCurveFitter.addPoint(newTime, hpr)
+            self.curveFitter.addXyzHpr(newTime, pos, hpr)
+        # Update widgets
+        self.updateWidgets()
         # Compute curve
         # Compute curve
-        self.computeCurves()
+        #self.computeCurves()
 
 
     def setRecordStart(self,value):
     def setRecordStart(self,value):
         self.recordStart = value
         self.recordStart = value
@@ -1601,8 +1561,7 @@ class MopathRecorder(AppShell, PandaObject):
         self.pointSet[0:0] = self.prePoints
         self.pointSet[0:0] = self.prePoints
         for time, pos, hpr in self.prePoints:
         for time, pos, hpr in self.prePoints:
             # Add it to the curve fitters
             # Add it to the curve fitters
-            self.xyzCurveFitter.addPoint(time, pos )
-            self.hprCurveFitter.addPoint(time, hpr)
+            self.curveFitter.addXyzHpr(time, pos, hpr)
         # And post points
         # And post points
         # What is end time of pointSet?
         # What is end time of pointSet?
         endTime = self.pointSet[-1][0]
         endTime = self.pointSet[-1][0]
@@ -1611,8 +1570,7 @@ class MopathRecorder(AppShell, PandaObject):
             # Add it to point set
             # Add it to point set
             self.pointSet.append([adjustedTime, pos, hpr])
             self.pointSet.append([adjustedTime, pos, hpr])
             # Add it to the curve fitters
             # Add it to the curve fitters
-            self.xyzCurveFitter.addPoint(adjustedTime, pos)
-            self.hprCurveFitter.addPoint(adjustedTime, hpr)
+            self.curveFitter.addXyzHpr(adjustedTime, pos, hpr)
 
 
     def setCropFrom(self,value):
     def setCropFrom(self,value):
         self.cropFrom = value
         self.cropFrom = value
@@ -1650,15 +1608,12 @@ class MopathRecorder(AppShell, PandaObject):
         self.createNewPointSet()
         self.createNewPointSet()
         # Copy over points between from/to
         # Copy over points between from/to
         # Reset curve fitters
         # Reset curve fitters
-        self.xyzCurveFitter.reset()
-        self.hprCurveFitter.reset()
+        self.curveFitter.reset()
         # Add start point
         # Add start point
         pos = Point3(0)
         pos = Point3(0)
-        self.xyzNurbsCurve.getPoint(self.cropFrom, pos)
-        self.xyzCurveFitter.addPoint(0.0, pos)
         hpr = Point3(0)
         hpr = Point3(0)
-        self.hprNurbsCurve.getPoint(self.cropFrom, hpr)
-        self.hprCurveFitter.addPoint(0.0, hpr)
+        self.curveCollection.evaluate(self.cropFrom, pos, hpr)
+        self.curveFitter.addXyzHpr(0.0, pos, hpr)
         # Get points within bounds
         # Get points within bounds
         for time, pos, hpr in oldPoints:
         for time, pos, hpr in oldPoints:
             # Is it within the time?
             # Is it within the time?
@@ -1666,17 +1621,14 @@ class MopathRecorder(AppShell, PandaObject):
                 (time < self.cropTo)):
                 (time < self.cropTo)):
                 # Add it to the curve fitters
                 # Add it to the curve fitters
                 t = time - self.cropFrom
                 t = time - self.cropFrom
-                self.xyzCurveFitter.addPoint(t, pos )
-                self.hprCurveFitter.addPoint(t, hpr)
+                self.curveFitter.addXyzHpr(t, pos, hpr)
                 # And the point set
                 # And the point set
                 self.pointSet.append([t, pos, hpr])
                 self.pointSet.append([t, pos, hpr])
         # Add last point
         # Add last point
         pos = Vec3(0)
         pos = Vec3(0)
-        self.xyzNurbsCurve.getPoint(self.cropTo, pos)
-        self.xyzCurveFitter.addPoint(self.cropTo - self.cropFrom, pos)
         hpr = Vec3(0)
         hpr = Vec3(0)
-        self.hprNurbsCurve.getPoint(self.cropTo, hpr)
-        self.hprCurveFitter.addPoint(self.cropTo - self.cropFrom, hpr)
+        self.curveCollection.evaluate(self.cropTo, pos, hpr)
+        self.curveFitter.addXyzHpr(self.cropTo - self.cropFrom, pos, hpr)
         # Compute curve
         # Compute curve
         self.computeCurves()
         self.computeCurves()
 
 
@@ -1704,34 +1656,17 @@ class MopathRecorder(AppShell, PandaObject):
             parent = self.parent)
             parent = self.parent)
         if mopathFilename:
         if mopathFilename:
             self.reset()
             self.reset()
-            nodePath = loader.loadModel(mopathFilename)
-            if nodePath:
-                self.extractCurves(nodePath)
-                if ((self.xyzNurbsCurve != None) and 
-                    (self.hprNurbsCurve != None)):
-                    # Save a pointset for this curve
-                    self.savePointSet()
-                else:
-                    if (self.xyzNurbsCurve != None):
-                        print 'Mopath Recorder: HPR Curve not found'
-                    elif (self.hprNurbsCurve != None):
-                        print 'Mopath Recorder: XYZ Curve not found'
-                    else:
-                        print 'Mopath Recorder: No Curves found'
-                    self.reset()
-
-    def extractCurves(self, nodePath):
-        node = nodePath.node()
-        if isinstance(node, ParametricCurve):
-            if node.getCurveType() == PCTXYZ:
-                self.xyzNurbsCurve = node
-            elif node.getCurveType() == PCTHPR:
-                self.hprNurbsCurve = node
-        else:
-            # Iterate over children if any
-            for child in nodePath.getChildrenAsList():
-                self.extractCurves(child)
-            
+            nodePath = loader.loadModel(Filename(mopathFilename))
+            self.curveCollection = ParametricCurveCollection()
+            # MRM: Add error check
+            self.curveCollection.addCurves(nodePath.node())
+            nodePath.removeNode()
+            if self.curveCollection:
+                # Save a pointset for this curve
+                self.savePointSet()
+            else:
+                self.reset()
+
     def saveCurveToFile(self):
     def saveCurveToFile(self):
         # Use first directory in model path
         # Use first directory in model path
         mPath = getModelPath()
         mPath = getModelPath()
@@ -1755,8 +1690,7 @@ class MopathRecorder(AppShell, PandaObject):
             title = 'Save Nurbs Curve as',
             title = 'Save Nurbs Curve as',
             parent = self.parent)
             parent = self.parent)
         if mopathFilename:
         if mopathFilename:
-            self.xyzNurbsCurve.writeEgg(mopathFilename)
-            self.hprNurbsCurve.writeEgg(mopathFilename)
+            self.curveCollection.writeEgg(Filename(mopathFilename))
 
 
     def followTerrain(self, height = 1.0):
     def followTerrain(self, height = 1.0):
         self.iRay.rayCollisionNodePath.reparentTo(self['nodePath'])
         self.iRay.rayCollisionNodePath.reparentTo(self['nodePath'])

+ 1 - 1
direct/src/tkpanels/ParticlePanel.py

@@ -1403,7 +1403,7 @@ class ParticlePanel(AppShell):
             color = renderer.getColor() * 255.0
             color = renderer.getColor() * 255.0
             texture = renderer.getTexture()
             texture = renderer.getTexture()
 	    if (texture != None):
 	    if (texture != None):
-		self.rendererSpriteTexture = texture.getName()
+		self.rendererSpriteTexture.set(texture.getName())
             self.getVariable('Sprite Renderer', 'X Scale').set(
             self.getVariable('Sprite Renderer', 'X Scale').set(
                 renderer.getXScaleFlag())
                 renderer.getXScaleFlag())
             self.getVariable('Sprite Renderer', 'Y Scale').set(
             self.getVariable('Sprite Renderer', 'Y Scale').set(