diff --git a/direct/src/tkpanels/MopathRecorder.py b/direct/src/tkpanels/MopathRecorder.py index 5d44a9bf8f..101685837d 100644 --- a/direct/src/tkpanels/MopathRecorder.py +++ b/direct/src/tkpanels/MopathRecorder.py @@ -21,7 +21,7 @@ class MopathRecorder(AppShell, PandaObject): # Override class variables here appname = 'Mopath Recorder Panel' frameWidth = 450 - frameHeight = 600 + frameHeight = 510 usecommandarea = 0 usestatusarea = 0 count = 0 @@ -117,6 +117,8 @@ class MopathRecorder(AppShell, PandaObject): self.controlStart = 0.0 self.controlStop = 0.0 self.refineStop = 0.0 + self.cropFrom = 0.0 + self.cropTo = 0.0 self.fAdjustingValues = 0 # Set up event hooks self.undoEvents = [('undo', self.undoHook), @@ -286,9 +288,9 @@ class MopathRecorder(AppShell, PandaObject): self.mainNotebook = Pmw.NoteBook(interior) self.mainNotebook.pack(fill = BOTH, expand = 1) self.recordPage = self.mainNotebook.add('Record') + self.resamplePage = self.mainNotebook.add('Resample') self.refinePage = self.mainNotebook.add('Refine') - # Put this here so it isn't called right away - self.mainNotebook['raisecommand'] = self.updateInfo + self.cropPage = self.mainNotebook.add('Crop') ## RECORD PAGE ## recordFrame = Frame(self.recordPage, relief = SUNKEN, @@ -385,21 +387,15 @@ class MopathRecorder(AppShell, PandaObject): # This gets the widgets to spread out self.gridFrame.grid_columnconfigure(1,weight = 1) recordFrame.pack(fill = X, pady = 2) - # Desample - desampleFrame = Frame( - self.recordPage, relief = SUNKEN, borderwidth = 2) - Label(desampleFrame, text = 'DESAMPLE CURVE', - font=('MSSansSerif', 12, 'bold')).pack() - widget = self.createEntryScale( - desampleFrame, 'Resample', 'Points Between Samples', - 'Recompute curve using every nth point', - resolution = 1, max = 100, command = self.setDesampleFrequency) - widget.component('hull')['relief'] = RIDGE - widget.onRelease = widget.onReturnRelease = self.desampleCurve - desampleFrame.pack(fill = X, expand = 0, pady = 2) + + ## RESAMPLE PAGE + label = Label(self.resamplePage, text = 'RESAMPLE CURVE', + font=('MSSansSerif', 12, 'bold')) + label.pack(fill = X) + # Resample resampleFrame = Frame( - self.recordPage, relief = SUNKEN, borderwidth = 2) + self.resamplePage, relief = SUNKEN, borderwidth = 2) label = Label(resampleFrame, text = 'RESAMPLE CURVE', font=('MSSansSerif', 12, 'bold')).pack() widget = self.createEntryScale( @@ -414,6 +410,18 @@ class MopathRecorder(AppShell, PandaObject): self.setEven, self.fEven, side = LEFT, fill = BOTH, expand = 0) resampleFrame.pack(fill = X, expand = 0, pady = 2) + # Desample + desampleFrame = Frame( + self.resamplePage, relief = SUNKEN, borderwidth = 2) + Label(desampleFrame, text = 'DESAMPLE CURVE', + font=('MSSansSerif', 12, 'bold')).pack() + widget = self.createEntryScale( + desampleFrame, 'Resample', 'Points Between Samples', + 'Recompute curve using every nth point', + resolution = 1, max = 100, command = self.setDesampleFrequency) + widget.component('hull')['relief'] = RIDGE + widget.onRelease = widget.onReturnRelease = self.desampleCurve + desampleFrame.pack(fill = X, expand = 0, pady = 2) ## REFINE PAGE ## refineFrame = Frame(self.refinePage, relief = SUNKEN, @@ -421,6 +429,16 @@ class MopathRecorder(AppShell, PandaObject): label = Label(refineFrame, text = 'REFINE CURVE', font=('MSSansSerif', 12, 'bold')) label.pack(fill = X) + + frame = Frame(refineFrame) + widget = self.createCheckbutton( + frame, 'Refine Page', 'Refining Path', + ('On: Next record session refines current path ' + + 'Off: Next record session records a new path'), + self.toggleRefine, 0, + side = LEFT, expand = 0) + frame.pack(expand = 1, fill = X) + widget = self.createEntryScale(refineFrame, 'Refine Page', 'Refine From', 'Begin time of refine pass', @@ -448,31 +466,35 @@ class MopathRecorder(AppShell, PandaObject): widget.onRelease = widget.onReturnRelease = self.getPostPoints refineFrame.pack(fill = X) - frame = Frame(refineFrame) - widget = self.createCheckbutton( - self.frame, 'Refine Page', 'Refining Path', - ('On: Next record session refines current path ' + - 'Off: Next record session records a new path'), - self.toggleRefine, 0, - side = LEFT, fill = BOTH, expand = 1) - widget.pack_forget() - widget.grid(row=0, column=0, sticky = NSEW) - widget.configure(relief = RAISED, borderwidth = 2, - anchor = CENTER, width = 10) - widget = self.createButton( - frame, 'Refine Page', 'Start Refining', - 'Start refining path using current refining settings', - self.startRefining, - side = LEFT, expand = 1) - widget.pack_forget() - widget.grid(row=0, column=1, sticky = NSEW) - frame.pack(expand = 1, fill = x) + + ## CROP PAGE ## + cropFrame = Frame(self.cropPage, relief = SUNKEN, + borderwidth = 2) + label = Label(cropFrame, text = 'CROP CURVE', + font=('MSSansSerif', 12, 'bold')) + label.pack(fill = X) + + widget = self.createEntryScale( + cropFrame, + 'Crop Page', 'Crop From', + 'Delete all curve points before this time', + resolution = 0.01, + command = self.setCropFrom) + + widget = self.createEntryScale( + cropFrame, + 'Crop Page', 'Crop To', + 'Delete all curve points after this time', + resolution = 0.01, + command = self.setCropTo) + + self.createButton(cropFrame, 'Crop Page', 'Crop Curve', + 'Crop curve to specified from to times', + self.cropCurve, fill = NONE) + cropFrame.pack(fill = X) self.mainNotebook.setnaturalsize() - def updateInfo(self, page = 'System'): - pass - def pushUndo(self, fResetRedo = 1): direct.pushUndo([self['nodePath']]) @@ -676,7 +698,7 @@ class MopathRecorder(AppShell, PandaObject): self.prePoints = [] self.postPoints = [] # Reset flag - self.fRefine = 0 + self.setRefineFlag(0) # Compute curve self.computeCurves() # Now you can change record modes @@ -765,6 +787,7 @@ class MopathRecorder(AppShell, PandaObject): def updateCurveInfo(self): if not self.xyzNurbsCurve: return + self.fAdjustingValues = 1 # Widgets depending on max T maxT = '%.2f' % self.xyzNurbsCurve.getMaxT() self.getWidget('Playback', 'Time').configure(max = maxT) @@ -781,12 +804,19 @@ class MopathRecorder(AppShell, PandaObject): widget = self.getWidget('Refine Page', 'Refine To') widget.configure(max = maxT) widget.set(float(maxT)) + widget = self.getWidget('Crop Page', 'Crop From') + widget.configure(max = maxT) + widget.set(float(0.0)) + widget = self.getWidget('Crop Page', 'Crop To') + widget.configure(max = maxT) + widget.set(float(maxT)) self.maxT = float(maxT) # Widgets depending on number of samples numSamples = self.xyzCurveFitter.getNumSamples() self.getWidget('Resample', 'Points Between Samples')['max'] = ( numSamples) self.getWidget('Resample', 'Num. Samples')['max'] = 3 * numSamples + self.fAdjustingValues = 0 def selectRecordNodePathNamed(self, name): nodePath = None @@ -1038,8 +1068,12 @@ class MopathRecorder(AppShell, PandaObject): # Update info self.updateCurveInfo() + def toggleRefine(self): + self.fRefine = self.getVariable('Refine Page', 'Refining Path').get() + def setRefineFlag(self, val = 1): self.fRefine = val + self.getVariable('Refine Page', 'Refining Path').set(val) def setRefineStart(self,value): self.refineStart = value @@ -1055,6 +1089,8 @@ class MopathRecorder(AppShell, PandaObject): self.refineStart) if self.refineStart > self.refineStop: self.getWidget('Refine Page', 'Refine To').set(self.refineStart) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) self.fAdjustingValues = 0 def getPrePoints(self): @@ -1085,6 +1121,8 @@ class MopathRecorder(AppShell, PandaObject): if self.controlStart > self.refineStop: self.getWidget('Refine Page', 'Refine To').set( self.controlStart) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) self.fAdjustingValues = 0 def setControlStop(self, value): @@ -1102,6 +1140,8 @@ class MopathRecorder(AppShell, PandaObject): if self.controlStop > self.refineStop: self.getWidget('Refine Page', 'Refine To').set( self.controlStop) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) self.fAdjustingValues = 0 def setRefineStop(self, value): @@ -1119,6 +1159,8 @@ class MopathRecorder(AppShell, PandaObject): if self.refineStop < self.controlStop: self.getWidget('Refine Page', 'Control Stop').set( self.refineStop) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) self.fAdjustingValues = 0 def getPostPoints(self): @@ -1152,6 +1194,57 @@ class MopathRecorder(AppShell, PandaObject): self.xyzCurveFitter.addPoint(adjustedTime, pos) self.hprCurveFitter.addPoint(adjustedTime, hpr) + def setCropFrom(self,value): + self.cropFrom = value + # Someone else is adjusting values, let them take care of it + if self.fAdjustingValues: + return + self.fAdjustingValues = 1 + if self.cropFrom > self.cropTo: + self.getWidget('Crop Page', 'Crop To').set( + self.cropFrom) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) + self.fAdjustingValues = 0 + + def setCropTo(self,value): + self.cropTo = value + # Someone else is adjusting values, let them take care of it + if self.fAdjustingValues: + return + self.fAdjustingValues = 1 + if self.cropTo < self.cropFrom: + self.getWidget('Crop Page', 'Crop From').set( + self.cropTo) + # Move playback node path to specified time + self.getWidget('Playback', 'Time').set(value) + self.fAdjustingValues = 0 + + def cropCurve(self): + # Keep handle on old points + oldPoints = self.pointSet + # Create new point set + self.createNewPointSet() + # Copy over points between from/to + # Reset curve fitters + self.xyzCurveFitter.reset() + self.hprCurveFitter.reset() + # Set flag + self.fHasPoints = 0 + for time, pos, hpr in oldPoints: + # Is it within the time? + if ((time > self.cropFrom) & + (time < self.cropTo)): + # Add it to the curve fitters + t = time - self.cropFrom + self.xyzCurveFitter.addPoint(t, pos ) + self.hprCurveFitter.addPoint(t, hpr) + # And the point set + self.pointSet.append([t, pos, hpr]) + self.fHasPoints = 1 + # Compute curve + self.computeCurves() + ## WIDGET UTILITY FUNCTIONS ## def addWidget(self, widget, category, text): self.widgetDict[category + '-' + text] = widget @@ -1183,11 +1276,11 @@ class MopathRecorder(AppShell, PandaObject): return (frame, label, entry) def createButton(self, parent, category, text, balloonHelp, command, - side = 'top', expand = 0): + side = 'top', expand = 0, fill = X): widget = Button(parent, text = text) # Do this after the widget so command isn't called on creation widget['command'] = command - widget.pack(side = side, fill = X, expand = expand) + widget.pack(side = side, fill = fill, expand = expand) self.bind(widget, balloonHelp) self.widgetDict[category + '-' + text] = widget return widget