mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
*** empty log message ***
This commit is contained in:
parent
512b33c7ae
commit
caeaf79805
@ -292,7 +292,7 @@ class DirectJoybox(PandaObject):
|
|||||||
np2planet = Vec3(self.nodePath.getPos(planet))
|
np2planet = Vec3(self.nodePath.getPos(planet))
|
||||||
# Compute dist
|
# Compute dist
|
||||||
offsetDist = np2planet.length()
|
offsetDist = np2planet.length()
|
||||||
# Too high, never mind
|
# Above threshold, leave velocity vec as is
|
||||||
if offsetDist > (1.2 * radius):
|
if offsetDist > (1.2 * radius):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -304,12 +304,17 @@ class DirectJoybox(PandaObject):
|
|||||||
# Xform fly vec to planet space
|
# Xform fly vec to planet space
|
||||||
dPlanet = self.nodePath.getMat(planet).xformVec(Vec3(0, dy, 0))
|
dPlanet = self.nodePath.getMat(planet).xformVec(Vec3(0, dy, 0))
|
||||||
# Compute radial component of fly vec
|
# Compute radial component of fly vec
|
||||||
radialComponent = oNorm * oNorm.dot(dPlanet)
|
dotProd = oNorm.dot(dPlanet)
|
||||||
# If within transition zone, begin subtracting radial component
|
if dotProd < 0:
|
||||||
|
# Trying to fly below radius, compute radial component
|
||||||
|
radialComponent = oNorm * dotProd
|
||||||
|
# How far above?
|
||||||
above = offsetDist - radius
|
above = offsetDist - radius
|
||||||
|
# Set sf accordingly
|
||||||
sf = max(1.0 - (max(above, 0.0)/(0.2 * radius)), 0.0)
|
sf = max(1.0 - (max(above, 0.0)/(0.2 * radius)), 0.0)
|
||||||
if offsetDist < radius:
|
# Subtract scaled radial component
|
||||||
dPlanet -= radialComponent * (sf * sf)
|
dPlanet -= radialComponent * (sf * sf)
|
||||||
|
#dPlanet -= radialComponent
|
||||||
# Convert back to node path space
|
# Convert back to node path space
|
||||||
dPos.assign(planet.getMat(self.nodePath).xformVec(dPlanet))
|
dPos.assign(planet.getMat(self.nodePath).xformVec(dPlanet))
|
||||||
# Set pos accordingly
|
# Set pos accordingly
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from PandaObject import *
|
from PandaObject import *
|
||||||
|
from DirectUtil import *
|
||||||
from DirectCameraControl import *
|
from DirectCameraControl import *
|
||||||
from DirectManipulation import *
|
from DirectManipulation import *
|
||||||
from DirectSelection import *
|
from DirectSelection import *
|
||||||
|
81
direct/src/directtools/DirectUtil.py
Normal file
81
direct/src/directtools/DirectUtil.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
from PandaObject import *
|
||||||
|
|
||||||
|
## Background Color ##
|
||||||
|
def setBackgroundColor(r,g,b):
|
||||||
|
base.win.getGsg().setColorClearValue(VBase4(r, g, b, 1.0))
|
||||||
|
|
||||||
|
def lerpBackgroundColor(r,g,b,duration):
|
||||||
|
def lerpColor(state):
|
||||||
|
dt = globalClock.getDt()
|
||||||
|
state.time += dt
|
||||||
|
sf = state.time / state.duration
|
||||||
|
if sf >= 1.0:
|
||||||
|
setBackgroundColor(state.ec[0], state.ec[1], state.ec[2])
|
||||||
|
return Task.done
|
||||||
|
else:
|
||||||
|
r = sf * state.ec[0] + (1 - sf) * state.sc[0]
|
||||||
|
g = sf * state.ec[1] + (1 - sf) * state.sc[1]
|
||||||
|
b = sf * state.ec[2] + (1 - sf) * state.sc[2]
|
||||||
|
setBackgroundColor(r,g,b)
|
||||||
|
return Task.cont
|
||||||
|
taskMgr.removeTasksNamed('lerpBackgroundColor')
|
||||||
|
t = taskMgr.spawnMethodNamed(lerpColor, 'lerpBackgroundColor')
|
||||||
|
t.time = 0.0
|
||||||
|
t.duration = duration
|
||||||
|
t.sc = base.win.getGsg().getColorClearValue()
|
||||||
|
t.ec = VBase4(r,g,b,1)
|
||||||
|
|
||||||
|
Q_EPSILON = 1e-10
|
||||||
|
|
||||||
|
def qSlerp(startQuat, endQuat, t):
|
||||||
|
startQ = Quat(startQuat)
|
||||||
|
destQuat = Quat.identQuat()
|
||||||
|
# Calc dot product
|
||||||
|
cosOmega = (startQ.getI() * endQuat.getI() +
|
||||||
|
startQ.getJ() * endQuat.getJ() +
|
||||||
|
startQ.getK() * endQuat.getK() +
|
||||||
|
startQ.getR() * endQuat.getR())
|
||||||
|
# If the above dot product is negative, it would be better to
|
||||||
|
# go between the negative of the initial and the final, so that
|
||||||
|
# we take the shorter path.
|
||||||
|
if ( cosOmega < 0.0 ):
|
||||||
|
cosOmega *= -1
|
||||||
|
startQ.setI(-1 * startQ.getI())
|
||||||
|
startQ.setJ(-1 * startQ.getJ())
|
||||||
|
startQ.setK(-1 * startQ.getK())
|
||||||
|
startQ.setR(-1 * startQ.getR())
|
||||||
|
if ((1.0 + cosOmega) > Q_EPSILON):
|
||||||
|
# usual case
|
||||||
|
if ((1.0 - cosOmega) > Q_EPSILON):
|
||||||
|
# usual case
|
||||||
|
omega = math.acos(cosOmega)
|
||||||
|
sinOmega = math.sin(omega)
|
||||||
|
startScale = math.sin((1.0 - t) * omega)/sinOmega
|
||||||
|
endScale = math.sin(t * omega)/sinOmega
|
||||||
|
else:
|
||||||
|
# ends very close
|
||||||
|
startScale = 1.0 - t
|
||||||
|
endScale = t
|
||||||
|
destQuat.setI(startScale * startQ.getI() +
|
||||||
|
endScale * endQuat.getI())
|
||||||
|
destQuat.setJ(startScale * startQ.getJ() +
|
||||||
|
endScale * endQuat.getJ())
|
||||||
|
destQuat.setK(startScale * startQ.getK() +
|
||||||
|
endScale * endQuat.getK())
|
||||||
|
destQuat.setR(startScale * startQ.getR() +
|
||||||
|
endScale * endQuat.getR())
|
||||||
|
else:
|
||||||
|
# ends nearly opposite
|
||||||
|
destQuat.setI(-startQ.getJ())
|
||||||
|
destQuat.setJ(startQ.getI())
|
||||||
|
destQuat.setK(-startQ.getR())
|
||||||
|
destQuat.setR(startQ.getK())
|
||||||
|
startScale = math.sin((0.5 - t) * math.pi)
|
||||||
|
endScale = math.sin(t * math.pi)
|
||||||
|
destQuat.setI(startScale * startQ.getI() +
|
||||||
|
endScale * endQuat.getI())
|
||||||
|
destQuat.setJ(startScale * startQ.getJ() +
|
||||||
|
endScale * endQuat.getJ())
|
||||||
|
destQuat.setK(startScale * startQ.getK() +
|
||||||
|
endScale * endQuat.getK())
|
||||||
|
return destQuat
|
@ -6,8 +6,10 @@ from Tkinter import *
|
|||||||
from AppShell import *
|
from AppShell import *
|
||||||
from DirectGeometry import *
|
from DirectGeometry import *
|
||||||
from DirectSelection import *
|
from DirectSelection import *
|
||||||
|
from DirectUtil import *
|
||||||
from tkFileDialog import *
|
from tkFileDialog import *
|
||||||
import os
|
import os
|
||||||
|
import string
|
||||||
import Pmw
|
import Pmw
|
||||||
import Dial
|
import Dial
|
||||||
import Floater
|
import Floater
|
||||||
@ -26,7 +28,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Override class variables here
|
# Override class variables here
|
||||||
appname = 'Mopath Recorder Panel'
|
appname = 'Mopath Recorder Panel'
|
||||||
frameWidth = 450
|
frameWidth = 450
|
||||||
frameHeight = 535
|
frameHeight = 550
|
||||||
usecommandarea = 0
|
usecommandarea = 0
|
||||||
usestatusarea = 0
|
usestatusarea = 0
|
||||||
count = 0
|
count = 0
|
||||||
@ -47,8 +49,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
|
|
||||||
self.initialiseoptions(MopathRecorder)
|
self.initialiseoptions(MopathRecorder)
|
||||||
|
|
||||||
self.selectRecordNodePathNamed('marker')
|
self.selectNodePathNamed('camera')
|
||||||
self.selectPlaybackNodePathNamed('marker')
|
|
||||||
|
|
||||||
def appInit(self):
|
def appInit(self):
|
||||||
self.name = self['name']
|
self.name = self['name']
|
||||||
@ -56,16 +57,22 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.widgetDict = {}
|
self.widgetDict = {}
|
||||||
self.variableDict = {}
|
self.variableDict = {}
|
||||||
# Initialize state
|
# Initialize state
|
||||||
|
# The active node path
|
||||||
|
self.nodePath = self['nodePath']
|
||||||
|
self.playbackNodePath = self.nodePath
|
||||||
|
# The active node path's parent
|
||||||
|
self.nodePathParent = render
|
||||||
|
# Top level node path
|
||||||
self.recorderNodePath = direct.group.attachNewNode(self.name)
|
self.recorderNodePath = direct.group.attachNewNode(self.name)
|
||||||
|
# Temp CS for use in refinement/path extension
|
||||||
self.tempCS = self.recorderNodePath.attachNewNode(
|
self.tempCS = self.recorderNodePath.attachNewNode(
|
||||||
'mopathRecorderTempCS')
|
'mopathRecorderTempCS')
|
||||||
self.nodePathParent = render
|
# Marker for use in playback
|
||||||
self.playbackMarker = loader.loadModel('models/directmodels/smiley')
|
self.playbackMarker = loader.loadModel('models/directmodels/smiley')
|
||||||
|
self.playbackMarker.setName('Playback Marker')
|
||||||
self.playbackMarker.reparentTo(self.recorderNodePath)
|
self.playbackMarker.reparentTo(self.recorderNodePath)
|
||||||
self.playbackMarker.hide()
|
self.playbackMarker.hide()
|
||||||
self.playbackMarker.setName('Playback Marker')
|
# Tangent marker
|
||||||
# ID of selected object
|
|
||||||
self.manipulandumId = None
|
|
||||||
self.tangentGroup = self.playbackMarker.attachNewNode('Tangent Group')
|
self.tangentGroup = self.playbackMarker.attachNewNode('Tangent Group')
|
||||||
self.tangentGroup.hide()
|
self.tangentGroup.hide()
|
||||||
self.tangentMarker = loader.loadModel('models/directmodels/sphere')
|
self.tangentMarker = loader.loadModel('models/directmodels/sphere')
|
||||||
@ -79,22 +86,17 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.tangentLines.moveTo(0,0,0)
|
self.tangentLines.moveTo(0,0,0)
|
||||||
self.tangentLines.drawTo(0,0,0)
|
self.tangentLines.drawTo(0,0,0)
|
||||||
self.tangentLines.create()
|
self.tangentLines.create()
|
||||||
|
# Active node path dictionary
|
||||||
|
self.nodePathDict = {}
|
||||||
|
self.nodePathDict['marker'] = self.playbackMarker
|
||||||
|
self.nodePathDict['camera'] = direct.camera
|
||||||
|
self.nodePathDict['widget'] = direct.widget
|
||||||
|
self.nodePathDict['mopathRecorderTempCS'] = self.tempCS
|
||||||
|
self.nodePathNames = ['marker', 'camera', 'selected']
|
||||||
|
# ID of selected object
|
||||||
|
self.manipulandumId = None
|
||||||
self.trace = LineNodePath(self.recorderNodePath)
|
self.trace = LineNodePath(self.recorderNodePath)
|
||||||
self.playbackNodePath = None
|
self.oldPlaybackNodePath = None
|
||||||
self.lastPlaybackNodePath = None
|
|
||||||
# For node path selectors
|
|
||||||
self.recNodePathDict = {}
|
|
||||||
self.recNodePathDict['marker'] = self.playbackMarker
|
|
||||||
self.recNodePathDict['camera'] = direct.camera
|
|
||||||
self.recNodePathDict['widget'] = direct.widget
|
|
||||||
self.recNodePathDict['mopathRecorderTempCS'] = self.tempCS
|
|
||||||
self.recNodePathNames = ['marker', 'camera', 'selected']
|
|
||||||
self.pbNodePathDict = {}
|
|
||||||
self.pbNodePathDict['marker'] = self.playbackMarker
|
|
||||||
self.pbNodePathDict['camera'] = direct.camera
|
|
||||||
self.pbNodePathDict['widget'] = direct.widget
|
|
||||||
self.pbNodePathDict['mopathRecorderTempCS'] = self.tempCS
|
|
||||||
self.pbNodePathNames = ['marker', 'camera', 'selected']
|
|
||||||
# Count of point sets recorded
|
# Count of point sets recorded
|
||||||
self.pointSet = []
|
self.pointSet = []
|
||||||
self.prePoints = []
|
self.prePoints = []
|
||||||
@ -126,15 +128,15 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.nurbsCurveDrawer.setShowHull(0)
|
self.nurbsCurveDrawer.setShowHull(0)
|
||||||
self.nurbsCurveDrawer.setShowCvs(0)
|
self.nurbsCurveDrawer.setShowCvs(0)
|
||||||
self.nurbsCurveDrawer.setNumTicks(0)
|
self.nurbsCurveDrawer.setNumTicks(0)
|
||||||
|
self.nurbsCurveDrawer.setTickScale(5.0)
|
||||||
self.curveNodePath = self.recorderNodePath.attachNewNode(
|
self.curveNodePath = self.recorderNodePath.attachNewNode(
|
||||||
self.nurbsCurveDrawer.getGeomNode())
|
self.nurbsCurveDrawer.getGeomNode())
|
||||||
|
useDirectRenderStyle(self.curveNodePath)
|
||||||
# Playback variables
|
# Playback variables
|
||||||
self.playbackTime = 0.0
|
self.playbackTime = 0.0
|
||||||
self.loopPlayback = 1
|
self.loopPlayback = 1
|
||||||
self.playbackSF = 1.0
|
self.playbackSF = 1.0
|
||||||
# Sample variables
|
# Sample variables
|
||||||
self.fEven = 0
|
|
||||||
self.fForward = 0
|
|
||||||
self.desampleFrequency = 1
|
self.desampleFrequency = 1
|
||||||
self.numSamples = 100
|
self.numSamples = 100
|
||||||
self.recordStart = 0.0
|
self.recordStart = 0.0
|
||||||
@ -186,7 +188,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
'Recorder', 'command',
|
'Recorder', 'command',
|
||||||
'Save current curve as a new point set',
|
'Save current curve as a new point set',
|
||||||
label = 'Save Point Set',
|
label = 'Save Point Set',
|
||||||
command = self.savePointSet)
|
command = self.extractPointSetFromCurveCollection)
|
||||||
self.menuBar.addmenuitem(
|
self.menuBar.addmenuitem(
|
||||||
'Recorder', 'command',
|
'Recorder', 'command',
|
||||||
'Toggle widget visability',
|
'Toggle widget visability',
|
||||||
@ -198,7 +200,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
label = 'Toggle Widget Mode',
|
label = 'Toggle Widget Mode',
|
||||||
command = direct.manipulationControl.toggleObjectHandlesMode)
|
command = direct.manipulationControl.toggleObjectHandlesMode)
|
||||||
|
|
||||||
self.createComboBox(self.menuFrame, 'Mopath', 'Point Set',
|
self.createComboBox(self.menuFrame, 'Mopath', 'History',
|
||||||
'Select input points to fit curve to', '',
|
'Select input points to fit curve to', '',
|
||||||
self.selectPointSetNamed, expand = 1)
|
self.selectPointSetNamed, expand = 1)
|
||||||
|
|
||||||
@ -221,17 +223,28 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.bind(self.redoButton, 'Redo last operation')
|
self.bind(self.redoButton, 'Redo last operation')
|
||||||
|
|
||||||
# Record button
|
# Record button
|
||||||
frame = Frame(interior, relief = SUNKEN, borderwidth = 2)
|
mainFrame = Frame(interior, relief = SUNKEN, borderwidth = 2)
|
||||||
widget = self.createCheckbutton(
|
frame = Frame(mainFrame)
|
||||||
frame, 'Recording', 'Record',
|
# Active node path
|
||||||
'On: path is being recorded', self.toggleRecord, 0,
|
# Button to select active node path
|
||||||
side = LEFT, fill = BOTH, expand = 1)
|
widget = self.createButton(frame, 'Recording', 'Node Path:',
|
||||||
widget.configure(foreground = 'Red', relief = RAISED, borderwidth = 2,
|
'Select Active Mopath Node Path',
|
||||||
anchor = CENTER, width = 16)
|
lambda s = self: direct.select(s.nodePath),
|
||||||
widget = self.createButton(frame, 'Recording', 'Add Keyframe',
|
side = LEFT, expand = 0)
|
||||||
'Add Keyframe To Current Path',
|
widget['relief'] = FLAT
|
||||||
self.addKeyframe,
|
self.nodePathMenu = Pmw.ComboBox(
|
||||||
side = LEFT, expand = 1)
|
frame, entry_width = 20,
|
||||||
|
selectioncommand = self.selectNodePathNamed,
|
||||||
|
scrolledlist_items = self.nodePathNames)
|
||||||
|
self.nodePathMenu.selectitem('camera')
|
||||||
|
self.nodePathMenuEntry = (
|
||||||
|
self.nodePathMenu.component('entryfield_entry'))
|
||||||
|
self.nodePathMenuBG = (
|
||||||
|
self.nodePathMenuEntry.configure('background')[3])
|
||||||
|
self.nodePathMenu.pack(side = LEFT, fill = X, expand = 1)
|
||||||
|
self.bind(self.nodePathMenu,
|
||||||
|
'Select active node path used for recording and playback')
|
||||||
|
# Recording type
|
||||||
self.recordingType = StringVar()
|
self.recordingType = StringVar()
|
||||||
self.recordingType.set('New Curve')
|
self.recordingType.set('New Curve')
|
||||||
widget = self.createRadiobutton(
|
widget = self.createRadiobutton(
|
||||||
@ -249,35 +262,29 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
'Recording', 'Extend',
|
'Recording', 'Extend',
|
||||||
('Next record session extends existing path'),
|
('Next record session extends existing path'),
|
||||||
self.recordingType, 'Extend', expand = 0)
|
self.recordingType, 'Extend', expand = 0)
|
||||||
frame.pack(expand = 1, fill = X, pady = 3)
|
frame.pack(fill = X, expand = 1)
|
||||||
|
|
||||||
|
frame = Frame(mainFrame)
|
||||||
|
widget = self.createCheckbutton(
|
||||||
|
frame, 'Recording', 'Record',
|
||||||
|
'On: path is being recorded', self.toggleRecord, 0,
|
||||||
|
side = LEFT, fill = BOTH, expand = 1)
|
||||||
|
widget.configure(foreground = 'Red', relief = RAISED, borderwidth = 2,
|
||||||
|
anchor = CENTER, width = 16)
|
||||||
|
widget = self.createButton(frame, 'Recording', 'Add Keyframe',
|
||||||
|
'Add Keyframe To Current Path',
|
||||||
|
self.addKeyframe,
|
||||||
|
side = LEFT, expand = 1)
|
||||||
|
frame.pack(fill = X, expand = 1)
|
||||||
|
|
||||||
|
mainFrame.pack(expand = 1, fill = X, pady = 3)
|
||||||
|
|
||||||
# Playback controls
|
# Playback controls
|
||||||
playbackFrame = Frame(interior, relief = SUNKEN,
|
playbackFrame = Frame(interior, relief = SUNKEN,
|
||||||
borderwidth = 2)
|
borderwidth = 2)
|
||||||
Label(playbackFrame, text = 'PLAYBACK CONTROLS',
|
Label(playbackFrame, text = 'PLAYBACK CONTROLS',
|
||||||
font=('MSSansSerif', 12, 'bold')).pack(fill = X)
|
font=('MSSansSerif', 12, 'bold')).pack(fill = X)
|
||||||
# Playback modifiers
|
# Main playback control slider
|
||||||
frame = Frame(playbackFrame)
|
|
||||||
# Playback node path
|
|
||||||
self.pbNodePathMenu = Pmw.ComboBox(
|
|
||||||
frame, labelpos = W, label_text = 'Playback Node Path:',
|
|
||||||
entry_width = 20,
|
|
||||||
selectioncommand = self.selectPlaybackNodePathNamed,
|
|
||||||
scrolledlist_items = self.pbNodePathNames)
|
|
||||||
self.pbNodePathMenu.selectitem('marker')
|
|
||||||
self.pbNodePathMenuEntry = (
|
|
||||||
self.pbNodePathMenu.component('entryfield_entry'))
|
|
||||||
self.pbNodePathMenuBG = (
|
|
||||||
self.pbNodePathMenuEntry.configure('background')[3])
|
|
||||||
self.pbNodePathMenu.pack(side = LEFT, fill = X, expand = 1)
|
|
||||||
self.bind(self.pbNodePathMenu,
|
|
||||||
'Select node path to fly along path during playback')
|
|
||||||
# Duration entry
|
|
||||||
self.createLabeledEntry(frame, 'Resample', 'Path Duration',
|
|
||||||
'Set total curve duration',
|
|
||||||
command = self.setPathDuration)
|
|
||||||
frame.pack(fill = X, expand = 1)
|
|
||||||
|
|
||||||
widget = self.createEntryScale(
|
widget = self.createEntryScale(
|
||||||
playbackFrame, 'Playback', 'Time', 'Set current playback time',
|
playbackFrame, 'Playback', 'Time', 'Set current playback time',
|
||||||
resolution = 0.01, command = self.playbackGoTo, side = TOP)
|
resolution = 0.01, command = self.playbackGoTo, side = TOP)
|
||||||
@ -285,19 +292,11 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Kill playback task if drag slider
|
# Kill playback task if drag slider
|
||||||
widget.component('scale').bind(
|
widget.component('scale').bind(
|
||||||
'<ButtonPress-1>', lambda e = None, s = self: s.stopPlayback())
|
'<ButtonPress-1>', lambda e = None, s = self: s.stopPlayback())
|
||||||
|
# Jam duration entry into entry scale
|
||||||
# Speed control
|
self.createLabeledEntry(widget.labelFrame, 'Resample', 'Path Duration',
|
||||||
frame = Frame(playbackFrame)
|
'Set total curve duration',
|
||||||
Label(frame, text = 'PB Speed Vernier').pack(side = LEFT, expand = 0)
|
command = self.setPathDuration,
|
||||||
self.speedScale = Scale(frame, from_ = -1, to = 1,
|
side = LEFT, expand = 0)
|
||||||
resolution = 0.01, showvalue = 0,
|
|
||||||
width = 10, orient = 'horizontal',
|
|
||||||
command = self.setPlaybackSF)
|
|
||||||
self.speedScale.pack(fill = X, expand = 0)
|
|
||||||
self.speedScale.bind('<ButtonRelease-1>',
|
|
||||||
lambda e = None, s = self: s.speedScale.set(0.0))
|
|
||||||
frame.pack(fill = X, expand = 1)
|
|
||||||
|
|
||||||
# Start stop buttons
|
# Start stop buttons
|
||||||
frame = Frame(playbackFrame)
|
frame = Frame(playbackFrame)
|
||||||
widget = self.createButton(frame, 'Playback', '<<',
|
widget = self.createButton(frame, 'Playback', '<<',
|
||||||
@ -322,80 +321,38 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
side = LEFT, fill = BOTH, expand = 0)
|
side = LEFT, fill = BOTH, expand = 0)
|
||||||
frame.pack(fill = X, expand = 1)
|
frame.pack(fill = X, expand = 1)
|
||||||
|
|
||||||
|
# Speed control
|
||||||
|
frame = Frame(playbackFrame)
|
||||||
|
widget = Button(frame, text = 'PB Speed Vernier', relief = FLAT,
|
||||||
|
command = lambda s = self: s.setSpeedScale(1.0))
|
||||||
|
widget.pack(side = LEFT, expand = 0)
|
||||||
|
self.speedScale = Scale(frame, from_ = -1, to = 1,
|
||||||
|
resolution = 0.01, showvalue = 0,
|
||||||
|
width = 10, orient = 'horizontal',
|
||||||
|
command = self.setPlaybackSF)
|
||||||
|
self.speedScale.pack(side = LEFT, fill = X, expand = 1)
|
||||||
|
self.speedVar = StringVar()
|
||||||
|
self.speedVar.set("0.00")
|
||||||
|
self.speedEntry = Entry(frame, textvariable = self.speedVar,
|
||||||
|
width = 8)
|
||||||
|
self.speedEntry.bind(
|
||||||
|
'<Return>',
|
||||||
|
lambda e = None, s = self: s.setSpeedScale(
|
||||||
|
string.atof(s.speedVar.get())))
|
||||||
|
self.speedEntry.pack(side = LEFT, expand = 0)
|
||||||
|
frame.pack(fill = X, expand = 1)
|
||||||
|
|
||||||
playbackFrame.pack(fill = X, pady = 2)
|
playbackFrame.pack(fill = X, pady = 2)
|
||||||
|
|
||||||
# Create notebook pages
|
# Create notebook pages
|
||||||
self.mainNotebook = Pmw.NoteBook(interior)
|
self.mainNotebook = Pmw.NoteBook(interior)
|
||||||
self.mainNotebook.pack(fill = BOTH, expand = 1)
|
self.mainNotebook.pack(fill = BOTH, expand = 1)
|
||||||
self.recordPage = self.mainNotebook.add('Record')
|
|
||||||
self.resamplePage = self.mainNotebook.add('Resample')
|
self.resamplePage = self.mainNotebook.add('Resample')
|
||||||
self.refinePage = self.mainNotebook.add('Refine')
|
self.refinePage = self.mainNotebook.add('Refine')
|
||||||
self.extendPage = self.mainNotebook.add('Extend')
|
self.extendPage = self.mainNotebook.add('Extend')
|
||||||
self.cropPage = self.mainNotebook.add('Crop')
|
self.cropPage = self.mainNotebook.add('Crop')
|
||||||
self.stylePage = self.mainNotebook.add('Style')
|
self.drawPage = self.mainNotebook.add('Draw')
|
||||||
|
self.optionsPage = self.mainNotebook.add('Options')
|
||||||
## RECORD PAGE ##
|
|
||||||
recordFrame = Frame(self.recordPage, relief = SUNKEN,
|
|
||||||
borderwidth = 2)
|
|
||||||
label = Label(recordFrame, text = 'RECORDING OPTIONS',
|
|
||||||
font=('MSSansSerif', 12, 'bold'))
|
|
||||||
label.pack(fill = X)
|
|
||||||
# Recording Buttons
|
|
||||||
# Record node path
|
|
||||||
frame = Frame(recordFrame)
|
|
||||||
self.recNodePathMenu = Pmw.ComboBox(
|
|
||||||
frame, labelpos = W, label_text = 'Record Node Path:',
|
|
||||||
label_width = 16, label_anchor = W, entry_width = 20,
|
|
||||||
selectioncommand = self.selectRecordNodePathNamed,
|
|
||||||
scrolledlist_items = self.recNodePathNames)
|
|
||||||
self.recNodePathMenu.selectitem('marker')
|
|
||||||
self.recNodePathMenuEntry = (
|
|
||||||
self.recNodePathMenu.component('entryfield_entry'))
|
|
||||||
self.recNodePathMenuBG = (
|
|
||||||
self.recNodePathMenuEntry.configure('background')[3])
|
|
||||||
self.bind(self.recNodePathMenu,
|
|
||||||
'Select node path to track when recording a new curve')
|
|
||||||
self.recNodePathMenu.pack(side = LEFT, expand = 0)
|
|
||||||
self.createButton(frame, 'Recording', 'Select',
|
|
||||||
'Select Current Record Node Path',
|
|
||||||
lambda s = self: direct.select(s['nodePath']))
|
|
||||||
frame.pack(expand = 1, fill = X)
|
|
||||||
|
|
||||||
# Hooks
|
|
||||||
frame = Frame(recordFrame)
|
|
||||||
widget = self.createLabeledEntry(
|
|
||||||
frame, 'Recording', 'Record Hook',
|
|
||||||
'Hook used to start/stop recording',
|
|
||||||
initialValue = self.startStopHook,
|
|
||||||
command = self.setStartStopHook)[0]
|
|
||||||
label = self.getWidget('Recording', 'Record Hook-Label')
|
|
||||||
label.configure(width = 16, anchor = W)
|
|
||||||
self.setStartStopHook()
|
|
||||||
widget = self.createLabeledEntry(
|
|
||||||
frame, 'Recording', 'Keyframe Hook',
|
|
||||||
'Hook used to add a new keyframe',
|
|
||||||
initialValue = self.keyframeHook,
|
|
||||||
command = self.setKeyframeHook)[0]
|
|
||||||
label = self.getWidget('Recording', 'Keyframe Hook-Label')
|
|
||||||
label.configure(width = 16, anchor = W)
|
|
||||||
self.setKeyframeHook()
|
|
||||||
frame.pack(expand = 1, fill = X)
|
|
||||||
# PreRecordFunc
|
|
||||||
frame = Frame(recordFrame)
|
|
||||||
widget = self.createComboBox(
|
|
||||||
frame, 'Recording', 'Pre-Record Func',
|
|
||||||
'Function called before sampling each point',
|
|
||||||
PRF_UTILITIES, self.setPreRecordFunc,
|
|
||||||
history = 1, expand = 1)
|
|
||||||
widget.configure(label_width = 16, label_anchor = W)
|
|
||||||
widget.configure(entryfield_entry_state = 'normal')
|
|
||||||
self.createCheckbutton(frame, 'Recording', 'PRF Active',
|
|
||||||
'On: Pre Record Func enabled',
|
|
||||||
None, 0,
|
|
||||||
side = LEFT, fill = BOTH, expand = 0)
|
|
||||||
frame.pack(expand = 1, fill = X)
|
|
||||||
# Pack record frame
|
|
||||||
recordFrame.pack(fill = X, pady = 2)
|
|
||||||
|
|
||||||
## RESAMPLE PAGE
|
## RESAMPLE PAGE
|
||||||
label = Label(self.resamplePage, text = 'RESAMPLE CURVE',
|
label = Label(self.resamplePage, text = 'RESAMPLE CURVE',
|
||||||
@ -410,22 +367,22 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
widget = self.createEntryScale(
|
widget = self.createEntryScale(
|
||||||
resampleFrame, 'Resample', 'Num. Samples',
|
resampleFrame, 'Resample', 'Num. Samples',
|
||||||
'Number of samples in resampled curve',
|
'Number of samples in resampled curve',
|
||||||
resolution = 1, min = 2, max = 1000, command = self.setNumSamples,
|
resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
|
||||||
side = LEFT)
|
|
||||||
widget.component('hull')['relief'] = RIDGE
|
widget.component('hull')['relief'] = RIDGE
|
||||||
widget.onRelease = widget.onReturnRelease = self.sampleCurve
|
widget.onRelease = widget.onReturnRelease = self.sampleCurve
|
||||||
|
|
||||||
frame = Frame(resampleFrame)
|
frame = Frame(resampleFrame)
|
||||||
self.createCheckbutton(frame, 'Resample', 'Even',
|
self.createButton(
|
||||||
'On: Resulting path has constant velocity',
|
frame, 'Resample', 'Make Even',
|
||||||
self.setEven, self.fEven,
|
'Apply timewarp so resulting path has constant velocity',
|
||||||
side = TOP, fill = BOTH, expand = 0)
|
self.makeEven, side = LEFT, fill = X, expand = 1)
|
||||||
self.createCheckbutton(
|
self.createButton(
|
||||||
frame, 'Resample', 'Forward',
|
frame, 'Resample', 'Face Forward',
|
||||||
'On: Resulting hpr curve faces along xyz tangent',
|
'Compute HPR so resulting hpr curve faces along xyz tangent',
|
||||||
self.setForward, self.fForward,
|
self.faceForward, side = LEFT, fill = X, expand = 1)
|
||||||
side = TOP, fill = BOTH, expand = 0)
|
|
||||||
frame.pack(fill = X, expand = 0)
|
frame.pack(fill = X, expand = 0)
|
||||||
resampleFrame.pack(fill = X, expand = 0, pady = 2)
|
resampleFrame.pack(fill = X, expand = 0, pady = 2)
|
||||||
|
|
||||||
# Desample
|
# Desample
|
||||||
desampleFrame = Frame(
|
desampleFrame = Frame(
|
||||||
self.resamplePage, relief = SUNKEN, borderwidth = 2)
|
self.resamplePage, relief = SUNKEN, borderwidth = 2)
|
||||||
@ -527,39 +484,42 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.cropCurve, fill = NONE)
|
self.cropCurve, fill = NONE)
|
||||||
cropFrame.pack(fill = X)
|
cropFrame.pack(fill = X)
|
||||||
|
|
||||||
## STYLE PAGE ##
|
## DRAW PAGE ##
|
||||||
styleFrame = Frame(self.stylePage, relief = SUNKEN,
|
drawFrame = Frame(self.drawPage, relief = SUNKEN,
|
||||||
borderwidth = 2)
|
borderwidth = 2)
|
||||||
label = Label(styleFrame, text = 'CURVE RENDERINNG STYLE',
|
|
||||||
|
self.sf = Pmw.ScrolledFrame(self.drawPage, horizflex = 'elastic')
|
||||||
|
self.sf.pack(fill = 'both', expand = 1)
|
||||||
|
sfFrame = self.sf.interior()
|
||||||
|
|
||||||
|
label = Label(sfFrame, text = 'CURVE RENDERING STYLE',
|
||||||
font=('MSSansSerif', 12, 'bold'))
|
font=('MSSansSerif', 12, 'bold'))
|
||||||
label.pack(fill = X)
|
label.pack(fill = X)
|
||||||
|
|
||||||
self.sf = Pmw.ScrolledFrame(styleFrame, horizflex = 'elastic')
|
|
||||||
self.sf.pack(fill = 'both', expand = 1)
|
|
||||||
sfFrame = self.sf.interior()
|
|
||||||
frame = Frame(sfFrame)
|
frame = Frame(sfFrame)
|
||||||
|
Label(frame, text = 'SHOW:').pack(side = LEFT, expand = 0)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show Path',
|
frame, 'Style', 'Path',
|
||||||
'On: path is visible', self.setPathVis, 1,
|
'On: path is visible', self.setPathVis, 1,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show Knots',
|
frame, 'Style', 'Knots',
|
||||||
'On: path knots are visible', self.setKnotVis, 1,
|
'On: path knots are visible', self.setKnotVis, 1,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show CVs',
|
frame, 'Style', 'CVs',
|
||||||
'On: path CVs are visible', self.setCvVis, 0,
|
'On: path CVs are visible', self.setCvVis, 0,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show Hull',
|
frame, 'Style', 'Hull',
|
||||||
'On: path hull is visible', self.setHullVis, 0,
|
'On: path hull is visible', self.setHullVis, 0,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show Trace',
|
frame, 'Style', 'Trace',
|
||||||
'On: record is visible', self.setTraceVis, 0,
|
'On: record is visible', self.setTraceVis, 0,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
widget = self.createCheckbutton(
|
widget = self.createCheckbutton(
|
||||||
frame, 'Style', 'Show Marker',
|
frame, 'Style', 'Marker',
|
||||||
'On: playback marker is visible', self.setMarkerVis, 0,
|
'On: playback marker is visible', self.setMarkerVis, 0,
|
||||||
side = LEFT, fill = X, expand = 1)
|
side = LEFT, fill = X, expand = 1)
|
||||||
frame.pack(fill = X, expand = 1)
|
frame.pack(fill = X, expand = 1)
|
||||||
@ -582,7 +542,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
sfFrame, 'Style', 'Tick Scale',
|
sfFrame, 'Style', 'Tick Scale',
|
||||||
'Set visible size of time tick marks',
|
'Set visible size of time tick marks',
|
||||||
min = 0.01, max = 100.0, resolution = 0.01,
|
min = 0.01, max = 100.0, resolution = 0.01,
|
||||||
initialValue = 1.0,
|
initialValue = 5.0,
|
||||||
command = self.setTickScale, side = TOP)
|
command = self.setTickScale, side = TOP)
|
||||||
widget.component('hull')['relief'] = RIDGE
|
widget.component('hull')['relief'] = RIDGE
|
||||||
self.createColorEntry(
|
self.createColorEntry(
|
||||||
@ -611,12 +571,56 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
command = self.setHullColor,
|
command = self.setHullColor,
|
||||||
initialValue = [255.0,128.0,128.0,255.0])
|
initialValue = [255.0,128.0,128.0,255.0])
|
||||||
|
|
||||||
styleFrame.pack(fill = X)
|
#drawFrame.pack(fill = X)
|
||||||
|
|
||||||
|
## OPTIONS PAGE ##
|
||||||
|
optionsFrame = Frame(self.optionsPage, relief = SUNKEN,
|
||||||
|
borderwidth = 2)
|
||||||
|
label = Label(optionsFrame, text = 'RECORDING OPTIONS',
|
||||||
|
font=('MSSansSerif', 12, 'bold'))
|
||||||
|
label.pack(fill = X)
|
||||||
|
# Hooks
|
||||||
|
frame = Frame(optionsFrame)
|
||||||
|
widget = self.createLabeledEntry(
|
||||||
|
frame, 'Recording', 'Record Hook',
|
||||||
|
'Hook used to start/stop recording',
|
||||||
|
initialValue = self.startStopHook,
|
||||||
|
command = self.setStartStopHook)[0]
|
||||||
|
label = self.getWidget('Recording', 'Record Hook-Label')
|
||||||
|
label.configure(width = 16, anchor = W)
|
||||||
|
self.setStartStopHook()
|
||||||
|
widget = self.createLabeledEntry(
|
||||||
|
frame, 'Recording', 'Keyframe Hook',
|
||||||
|
'Hook used to add a new keyframe',
|
||||||
|
initialValue = self.keyframeHook,
|
||||||
|
command = self.setKeyframeHook)[0]
|
||||||
|
label = self.getWidget('Recording', 'Keyframe Hook-Label')
|
||||||
|
label.configure(width = 16, anchor = W)
|
||||||
|
self.setKeyframeHook()
|
||||||
|
frame.pack(expand = 1, fill = X)
|
||||||
|
# PreRecordFunc
|
||||||
|
frame = Frame(optionsFrame)
|
||||||
|
widget = self.createComboBox(
|
||||||
|
frame, 'Recording', 'Pre-Record Func',
|
||||||
|
'Function called before sampling each point',
|
||||||
|
PRF_UTILITIES, self.setPreRecordFunc,
|
||||||
|
history = 1, expand = 1)
|
||||||
|
widget.configure(label_width = 16, label_anchor = W)
|
||||||
|
widget.configure(entryfield_entry_state = 'normal')
|
||||||
|
# Initialize preRecordFunc
|
||||||
|
self.preRecordFunc = eval(PRF_UTILITIES[0])
|
||||||
|
self.createCheckbutton(frame, 'Recording', 'PRF Active',
|
||||||
|
'On: Pre Record Func enabled',
|
||||||
|
None, 0,
|
||||||
|
side = LEFT, fill = BOTH, expand = 0)
|
||||||
|
frame.pack(expand = 1, fill = X)
|
||||||
|
# Pack record frame
|
||||||
|
optionsFrame.pack(fill = X, pady = 2)
|
||||||
|
|
||||||
self.mainNotebook.setnaturalsize()
|
self.mainNotebook.setnaturalsize()
|
||||||
|
|
||||||
def pushUndo(self, fResetRedo = 1):
|
def pushUndo(self, fResetRedo = 1):
|
||||||
direct.pushUndo([self['nodePath']])
|
direct.pushUndo([self.nodePath])
|
||||||
|
|
||||||
def undoHook(self):
|
def undoHook(self):
|
||||||
# Reflect new changes
|
# Reflect new changes
|
||||||
@ -631,7 +635,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.undoButton.configure(state = 'disabled')
|
self.undoButton.configure(state = 'disabled')
|
||||||
|
|
||||||
def pushRedo(self):
|
def pushRedo(self):
|
||||||
direct.pushRedo([self['nodePath']])
|
direct.pushRedo([self.nodePath])
|
||||||
|
|
||||||
def redoHook(self):
|
def redoHook(self):
|
||||||
# Reflect new changes
|
# Reflect new changes
|
||||||
@ -685,12 +689,10 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
hpr = Point3(0)
|
hpr = Point3(0)
|
||||||
pos = self.playbackMarker.getPos(self.nodePathParent)
|
pos = self.playbackMarker.getPos(self.nodePathParent)
|
||||||
hpr = self.playbackMarker.getHpr(self.nodePathParent)
|
hpr = self.playbackMarker.getHpr(self.nodePathParent)
|
||||||
self.curveCollection.getXyzCurve().adjustPoint(
|
self.curveCollection.adjustXyz(
|
||||||
self.playbackTime,
|
self.playbackTime, VBase3(pos[0], pos[1], pos[2]))
|
||||||
pos[0], pos[1], pos[2])
|
self.curveCollection.adjustHpr(
|
||||||
self.curveCollection.getHprCurve().adjustPoint(
|
self.playbackTime, VBase3(hpr[0], hpr[1], hpr[2]))
|
||||||
self.playbackTime,
|
|
||||||
hpr[0], hpr[1], hpr[2])
|
|
||||||
# Note: this calls recompute on the curves
|
# Note: this calls recompute on the curves
|
||||||
self.nurbsCurveDrawer.draw()
|
self.nurbsCurveDrawer.draw()
|
||||||
# Update tangent
|
# Update tangent
|
||||||
@ -756,26 +758,12 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
taskMgr.removeTasksNamed(self.name + '-playbackTask')
|
taskMgr.removeTasksNamed(self.name + '-playbackTask')
|
||||||
taskMgr.removeTasksNamed(self.name + '-curveEditTask')
|
taskMgr.removeTasksNamed(self.name + '-curveEditTask')
|
||||||
|
|
||||||
def savePointSet(self):
|
|
||||||
# Use curve to compute default point set at 30 fps
|
|
||||||
# Keep a handle on the original curve
|
|
||||||
curveCollection = self.curveCollection
|
|
||||||
# Sample curves
|
|
||||||
self.maxT = self.curveCollection.getMaxT()
|
|
||||||
self.setNumSamples(self.maxT * 30.0)
|
|
||||||
self.sampleCurve()
|
|
||||||
# Restore curves to those loaded in
|
|
||||||
self.curveCollection = curveCollection
|
|
||||||
# Redraw
|
|
||||||
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`
|
||||||
# Update dictionary and record pointer to new point set
|
# Update dictionary and record pointer to new point set
|
||||||
self.pointSet = self.pointSetDict[self.pointSetName] = []
|
self.pointSet = self.pointSetDict[self.pointSetName] = []
|
||||||
# Update combo box
|
# Update combo box
|
||||||
comboBox = self.getWidget('Mopath', 'Point Set')
|
comboBox = self.getWidget('Mopath', 'History')
|
||||||
scrolledList = comboBox.component('scrolledlist')
|
scrolledList = comboBox.component('scrolledlist')
|
||||||
listbox = scrolledList.component('listbox')
|
listbox = scrolledList.component('listbox')
|
||||||
names = list(listbox.get(0,'end'))
|
names = list(listbox.get(0,'end'))
|
||||||
@ -785,6 +773,28 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Update count
|
# Update count
|
||||||
self.pointSetCount += 1
|
self.pointSetCount += 1
|
||||||
|
|
||||||
|
def extractPointSetFromCurveFitter(self):
|
||||||
|
# Get new point set based on newly created curve
|
||||||
|
self.createNewPointSet()
|
||||||
|
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])
|
||||||
|
|
||||||
|
def extractPointSetFromCurveCollection(self):
|
||||||
|
# Use curve to compute new point set
|
||||||
|
# Record maxT
|
||||||
|
self.maxT = self.curveCollection.getMaxT()
|
||||||
|
# Determine num samples
|
||||||
|
# Limit point set to 1000 points and samples per second to 30
|
||||||
|
samplesPerSegment = min(30.0, 1000.0/self.curveCollection.getMaxT())
|
||||||
|
self.setNumSamples(self.maxT * samplesPerSegment)
|
||||||
|
# Sample the curve but don't create a new curve collection
|
||||||
|
self.sampleCurve(fCompute = 0)
|
||||||
|
# Update widgets based on new data
|
||||||
|
self.updateWidgets()
|
||||||
|
|
||||||
def selectPointSetNamed(self, name):
|
def selectPointSetNamed(self, name):
|
||||||
self.pointSet = self.pointSetDict.get(name, None)
|
self.pointSet = self.pointSetDict.get(name, None)
|
||||||
# Reload points into curve fitter
|
# Reload points into curve fitter
|
||||||
@ -797,31 +807,31 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.computeCurves()
|
self.computeCurves()
|
||||||
|
|
||||||
def setPathVis(self):
|
def setPathVis(self):
|
||||||
if self.getVariable('Style', 'Show Path').get():
|
if self.getVariable('Style', 'Path').get():
|
||||||
self.curveNodePath.show()
|
self.curveNodePath.show()
|
||||||
else:
|
else:
|
||||||
self.curveNodePath.hide()
|
self.curveNodePath.hide()
|
||||||
|
|
||||||
def setKnotVis(self):
|
def setKnotVis(self):
|
||||||
self.nurbsCurveDrawer.setShowKnots(
|
self.nurbsCurveDrawer.setShowKnots(
|
||||||
self.getVariable('Style', 'Show Knots').get())
|
self.getVariable('Style', 'Knots').get())
|
||||||
|
|
||||||
def setCvVis(self):
|
def setCvVis(self):
|
||||||
self.nurbsCurveDrawer.setShowCvs(
|
self.nurbsCurveDrawer.setShowCvs(
|
||||||
self.getVariable('Style', 'Show CVs').get())
|
self.getVariable('Style', 'CVs').get())
|
||||||
|
|
||||||
def setHullVis(self):
|
def setHullVis(self):
|
||||||
self.nurbsCurveDrawer.setShowHull(
|
self.nurbsCurveDrawer.setShowHull(
|
||||||
self.getVariable('Style', 'Show Hull').get())
|
self.getVariable('Style', 'Hull').get())
|
||||||
|
|
||||||
def setTraceVis(self):
|
def setTraceVis(self):
|
||||||
if self.getVariable('Style', 'Show Trace').get():
|
if self.getVariable('Style', 'Trace').get():
|
||||||
self.trace.show()
|
self.trace.show()
|
||||||
else:
|
else:
|
||||||
self.trace.hide()
|
self.trace.hide()
|
||||||
|
|
||||||
def setMarkerVis(self):
|
def setMarkerVis(self):
|
||||||
if self.getVariable('Style', 'Show Marker').get():
|
if self.getVariable('Style', 'Marker').get():
|
||||||
self.playbackMarker.reparentTo(self.recorderNodePath)
|
self.playbackMarker.reparentTo(self.recorderNodePath)
|
||||||
else:
|
else:
|
||||||
self.playbackMarker.reparentTo(hidden)
|
self.playbackMarker.reparentTo(hidden)
|
||||||
@ -924,17 +934,13 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.disableKeyframeButton()
|
self.disableKeyframeButton()
|
||||||
# Create a new point set to hold raw data
|
# Create a new point set to hold raw data
|
||||||
self.createNewPointSet()
|
self.createNewPointSet()
|
||||||
# Record nopath's parent
|
|
||||||
self.nodePathParent = self['nodePath'].getParent()
|
|
||||||
# Put curve drawer under record node path's parent
|
|
||||||
self.curveNodePath.reparentTo(self.nodePathParent)
|
|
||||||
# Clear out old trace, get ready to draw new
|
# Clear out old trace, get ready to draw new
|
||||||
self.initTrace()
|
self.initTrace()
|
||||||
# Keyframe mode?
|
# Keyframe mode?
|
||||||
if (self.samplingMode == 'Keyframe'):
|
if (self.samplingMode == 'Keyframe'):
|
||||||
# Record first point
|
# Record first point
|
||||||
self.lastPos.assign(Point3(
|
self.lastPos.assign(Point3(
|
||||||
self['nodePath'].getPos(self.nodePathParent)))
|
self.nodePath.getPos(self.nodePathParent)))
|
||||||
# Init delta time
|
# Init delta time
|
||||||
self.deltaTime = 0.0
|
self.deltaTime = 0.0
|
||||||
# Record first point
|
# Record first point
|
||||||
@ -948,12 +954,12 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Update widget to reflect new value
|
# Update widget to reflect new value
|
||||||
self.getVariable('Playback', 'Loop').set(0)
|
self.getVariable('Playback', 'Loop').set(0)
|
||||||
# Select tempCS as playback nodepath
|
# Select tempCS as playback nodepath
|
||||||
self.lastPlaybackNodePath = self.playbackNodePath
|
self.oldPlaybackNodePath = self.playbackNodePath
|
||||||
self.selectPlaybackNodePathNamed('mopathRecorderTempCS')
|
self.setPlaybackNodePath(self.tempCS)
|
||||||
# Parent record node path to temp
|
# Parent record node path to temp
|
||||||
self['nodePath'].reparentTo(self.tempCS)
|
self.nodePath.reparentTo(self.playbackNodePath)
|
||||||
# Align with temp
|
# Align with temp
|
||||||
self['nodePath'].setPosHpr(0,0,0,0,0,0)
|
self.nodePath.setPosHpr(0,0,0,0,0,0)
|
||||||
# Set playback start to self.recordStart
|
# Set playback start to self.recordStart
|
||||||
self.playbackGoTo(self.recordStart)
|
self.playbackGoTo(self.recordStart)
|
||||||
# start flying nodePath along path
|
# start flying nodePath along path
|
||||||
@ -969,12 +975,9 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
if ((self.recordingType.get() == 'Refine') or
|
if ((self.recordingType.get() == 'Refine') or
|
||||||
(self.recordingType.get() == 'Extend')):
|
(self.recordingType.get() == 'Extend')):
|
||||||
# Reparent node path back to parent
|
# Reparent node path back to parent
|
||||||
self['nodePath'].wrtReparentTo(self.nodePathParent)
|
self.nodePath.wrtReparentTo(self.nodePathParent)
|
||||||
# Restore playback Node Path
|
# Restore playback Node Path
|
||||||
self.playbackNodePath = self.lastPlaybackNodePath
|
self.setPlaybackNodePath(self.oldPlaybackNodePath)
|
||||||
# See if it was the playback marker
|
|
||||||
if self.playbackNodePath.id() == self.playbackMarker.id():
|
|
||||||
self.playbackMarker.show()
|
|
||||||
else:
|
else:
|
||||||
# Add last point
|
# Add last point
|
||||||
self.addKeyframe(0)
|
self.addKeyframe(0)
|
||||||
@ -996,7 +999,8 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
|
|
||||||
def recordTask(self, state):
|
def recordTask(self, state):
|
||||||
# Record raw data point
|
# Record raw data point
|
||||||
time = self.recordStart + (globalClock.getFrameTime() - state.startTime)
|
time = self.recordStart + (
|
||||||
|
globalClock.getFrameTime() - state.startTime)
|
||||||
self.recordPoint(time)
|
self.recordPoint(time)
|
||||||
return Task.cont
|
return Task.cont
|
||||||
|
|
||||||
@ -1010,7 +1014,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.toggleRecordVar()
|
self.toggleRecordVar()
|
||||||
else:
|
else:
|
||||||
# Use distance as a time
|
# Use distance as a time
|
||||||
pos = self['nodePath'].getPos(self.nodePathParent)
|
pos = self.nodePath.getPos(self.nodePathParent)
|
||||||
deltaPos = Vec3(pos - self.lastPos).length()
|
deltaPos = Vec3(pos - self.lastPos).length()
|
||||||
if deltaPos != 0:
|
if deltaPos != 0:
|
||||||
# If we've moved at all, use delta Pos as time
|
# If we've moved at all, use delta Pos as time
|
||||||
@ -1040,30 +1044,38 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
(self.preRecordFunc != None)):
|
(self.preRecordFunc != None)):
|
||||||
self.preRecordFunc()
|
self.preRecordFunc()
|
||||||
# Get point
|
# Get point
|
||||||
pos = self['nodePath'].getPos(self.nodePathParent)
|
pos = self.nodePath.getPos(self.nodePathParent)
|
||||||
hpr = self['nodePath'].getHpr(self.nodePathParent)
|
hpr = self.nodePath.getHpr(self.nodePathParent)
|
||||||
# Blend between recordNodePath and self['nodePath']
|
qNP = Quat()
|
||||||
|
qNP.setHpr(hpr)
|
||||||
|
# Blend between recordNodePath and self.nodePath
|
||||||
if ((self.recordingType.get() == 'Refine') or
|
if ((self.recordingType.get() == 'Refine') or
|
||||||
(self.recordingType.get() == 'Extend')):
|
(self.recordingType.get() == 'Extend')):
|
||||||
if ((time < self.controlStart) and
|
if ((time < self.controlStart) and
|
||||||
((self.controlStart - self.recordStart) != 0.0)):
|
((self.controlStart - self.recordStart) != 0.0)):
|
||||||
rPos = self.playbackNodePath.getPos(self.nodePathParent)
|
rPos = self.playbackNodePath.getPos(self.nodePathParent)
|
||||||
rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
|
rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
|
||||||
|
qR = Quat()
|
||||||
|
qR.setHpr(rHpr)
|
||||||
t = self.easeInOut(((time - self.recordStart)/
|
t = self.easeInOut(((time - self.recordStart)/
|
||||||
(self.controlStart - self.recordStart)))
|
(self.controlStart - self.recordStart)))
|
||||||
# Transition between the recorded node path and the driven one
|
# Transition between the recorded node path and the driven one
|
||||||
pos = (rPos * (1 - t)) + (pos * t)
|
pos = (rPos * (1 - t)) + (pos * t)
|
||||||
hpr = (rHpr * (1 - t)) + (hpr * t)
|
q = qSlerp(qR, qNP, t)
|
||||||
|
hpr.assign(q.getHpr())
|
||||||
elif ((self.recordingType.get() == 'Refine') and
|
elif ((self.recordingType.get() == 'Refine') and
|
||||||
(time > self.controlStop) and
|
(time > self.controlStop) and
|
||||||
((self.recordStop - self.controlStop) != 0.0)):
|
((self.recordStop - self.controlStop) != 0.0)):
|
||||||
rPos = self.playbackNodePath.getPos(self.nodePathParent)
|
rPos = self.playbackNodePath.getPos(self.nodePathParent)
|
||||||
rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
|
rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
|
||||||
|
qR = Quat()
|
||||||
|
qR.setHpr(rHpr)
|
||||||
t = self.easeInOut(((time - self.controlStop)/
|
t = self.easeInOut(((time - self.controlStop)/
|
||||||
(self.recordStop - self.controlStop)))
|
(self.recordStop - self.controlStop)))
|
||||||
# Transition between the recorded node path and the driven one
|
# Transition between the recorded node path and the driven one
|
||||||
pos = (pos * (1 - t)) + (rPos * t)
|
pos = (pos * (1 - t)) + (rPos * t)
|
||||||
hpr = (hpr * (1 - t)) + (rHpr * t)
|
q = qSlerp(qNP, qR, t)
|
||||||
|
hpr.assign(q.getHpr())
|
||||||
# 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
|
||||||
@ -1145,24 +1157,24 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
widget.set(numSamples, 0)
|
widget.set(numSamples, 0)
|
||||||
self.fAdjustingValues = 0
|
self.fAdjustingValues = 0
|
||||||
|
|
||||||
def selectRecordNodePathNamed(self, name):
|
def selectNodePathNamed(self, name):
|
||||||
nodePath = None
|
nodePath = None
|
||||||
if name == 'init':
|
if name == 'init':
|
||||||
nodePath = self['nodePath']
|
nodePath = self.nodePath
|
||||||
# Add Combo box entry for the initial node path
|
# Add Combo box entry for the initial node path
|
||||||
self.addRecordNodePath(nodePath)
|
self.addNodePath(nodePath)
|
||||||
elif name == 'selected':
|
elif name == 'selected':
|
||||||
nodePath = direct.selected.last
|
nodePath = direct.selected.last
|
||||||
# Add Combo box entry for this selected object
|
# Add Combo box entry for this selected object
|
||||||
self.addRecordNodePath(nodePath)
|
self.addNodePath(nodePath)
|
||||||
else:
|
else:
|
||||||
nodePath = self.recNodePathDict.get(name, None)
|
nodePath = self.nodePathDict.get(name, None)
|
||||||
if (nodePath == None):
|
if (nodePath == None):
|
||||||
# See if this evaluates into a node path
|
# See if this evaluates into a node path
|
||||||
try:
|
try:
|
||||||
nodePath = eval(name)
|
nodePath = eval(name)
|
||||||
if isinstance(nodePath, NodePath):
|
if isinstance(nodePath, NodePath):
|
||||||
self.addRecordNodePath(nodePath)
|
self.addNodePath(nodePath)
|
||||||
else:
|
else:
|
||||||
# Good eval but not a node path, give up
|
# Good eval but not a node path, give up
|
||||||
nodePath = None
|
nodePath = None
|
||||||
@ -1170,55 +1182,8 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Bogus eval
|
# Bogus eval
|
||||||
nodePath = None
|
nodePath = None
|
||||||
# Clear bogus entry from listbox
|
# Clear bogus entry from listbox
|
||||||
listbox = self.recNodePathMenu.component('scrolledlist')
|
listbox = self.nodePathMenu.component('scrolledlist')
|
||||||
listbox.setlist(self.recNodePathNames)
|
listbox.setlist(self.nodePathNames)
|
||||||
else:
|
|
||||||
if name == 'widget':
|
|
||||||
# Record relationship between selected nodes and widget
|
|
||||||
direct.selected.getWrtAll()
|
|
||||||
if name == 'marker':
|
|
||||||
self.playbackMarker.show()
|
|
||||||
else:
|
|
||||||
self.playbackMarker.hide()
|
|
||||||
# Update active node path
|
|
||||||
self.setRecordNodePath(nodePath)
|
|
||||||
|
|
||||||
def setRecordNodePath(self, nodePath):
|
|
||||||
self['nodePath'] = nodePath
|
|
||||||
if self['nodePath']:
|
|
||||||
self.recNodePathMenuEntry.configure(
|
|
||||||
background = self.recNodePathMenuBG)
|
|
||||||
else:
|
|
||||||
# Flash entry
|
|
||||||
self.recNodePathMenuEntry.configure(background = 'Pink')
|
|
||||||
|
|
||||||
def selectPlaybackNodePathNamed(self, name):
|
|
||||||
nodePath = None
|
|
||||||
if name == 'init':
|
|
||||||
nodePath = self['nodePath']
|
|
||||||
# Add Combo box entry for the initial node path
|
|
||||||
self.addPlaybackNodePath(nodePath)
|
|
||||||
elif name == 'selected':
|
|
||||||
nodePath = direct.selected.last
|
|
||||||
# Add Combo box entry for this selected object
|
|
||||||
self.addPlaybackNodePath(nodePath)
|
|
||||||
else:
|
|
||||||
nodePath = self.pbNodePathDict.get(name, None)
|
|
||||||
if (nodePath == None):
|
|
||||||
# See if this evaluates into a node path
|
|
||||||
try:
|
|
||||||
nodePath = eval(name)
|
|
||||||
if isinstance(nodePath, NodePath):
|
|
||||||
self.addPlaybackNodePath(nodePath)
|
|
||||||
else:
|
|
||||||
# Good eval but not a node path, give up
|
|
||||||
nodePath = None
|
|
||||||
except:
|
|
||||||
# Bogus eval
|
|
||||||
nodePath = None
|
|
||||||
# Clear bogus entry from listbox
|
|
||||||
listbox = self.pbNodePathMenu.component('scrolledlist')
|
|
||||||
listbox.setlist(self.pbNodePathNames)
|
|
||||||
else:
|
else:
|
||||||
if name == 'widget':
|
if name == 'widget':
|
||||||
# Record relationship between selected nodes and widget
|
# Record relationship between selected nodes and widget
|
||||||
@ -1234,24 +1199,28 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
else:
|
else:
|
||||||
self.playbackMarker.hide()
|
self.playbackMarker.hide()
|
||||||
# Update active node path
|
# Update active node path
|
||||||
self.setPlaybackNodePath(nodePath)
|
self.setNodePath(nodePath)
|
||||||
|
|
||||||
|
def setNodePath(self, nodePath):
|
||||||
|
self.playbackNodePath = self.nodePath = nodePath
|
||||||
|
if self.nodePath:
|
||||||
|
# Record nopath's parent
|
||||||
|
self.nodePathParent = self.nodePath.getParent()
|
||||||
|
# Put curve drawer under record node path's parent
|
||||||
|
self.curveNodePath.reparentTo(self.nodePathParent)
|
||||||
|
# Set entry color
|
||||||
|
self.nodePathMenuEntry.configure(
|
||||||
|
background = self.nodePathMenuBG)
|
||||||
|
else:
|
||||||
|
# Flash entry
|
||||||
|
self.nodePathMenuEntry.configure(background = 'Pink')
|
||||||
|
|
||||||
def setPlaybackNodePath(self, nodePath):
|
def setPlaybackNodePath(self, nodePath):
|
||||||
self.playbackNodePath = nodePath
|
self.playbackNodePath = nodePath
|
||||||
if self.playbackNodePath:
|
|
||||||
self.pbNodePathMenuEntry.configure(
|
|
||||||
background = self.pbNodePathMenuBG)
|
|
||||||
else:
|
|
||||||
# Flash entry
|
|
||||||
self.pbNodePathMenuEntry.configure(background = 'Pink')
|
|
||||||
|
|
||||||
def addRecordNodePath(self, nodePath):
|
def addNodePath(self, nodePath):
|
||||||
self.addNodePathToDict(nodePath, self.recNodePathNames,
|
self.addNodePathToDict(nodePath, self.nodePathNames,
|
||||||
self.recNodePathMenu, self.recNodePathDict)
|
self.nodePathMenu, self.nodePathDict)
|
||||||
|
|
||||||
def addPlaybackNodePath(self, nodePath):
|
|
||||||
self.addNodePathToDict(nodePath, self.pbNodePathNames,
|
|
||||||
self.pbNodePathMenu, self.pbNodePathDict)
|
|
||||||
|
|
||||||
def addNodePathToDict(self, nodePath, names, menu, dict):
|
def addNodePathToDict(self, nodePath, names, menu, dict):
|
||||||
if not nodePath:
|
if not nodePath:
|
||||||
@ -1299,10 +1268,11 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
t.lastTime = globalClock.getFrameTime()
|
t.lastTime = globalClock.getFrameTime()
|
||||||
|
|
||||||
def setSpeedScale(self, value):
|
def setSpeedScale(self, value):
|
||||||
self.speedScale.set(value)
|
self.speedScale.set(math.log10(value))
|
||||||
|
|
||||||
def setPlaybackSF(self, value):
|
def setPlaybackSF(self, value):
|
||||||
self.playbackSF = pow(10.0, float(value))
|
self.playbackSF = pow(10.0, float(value))
|
||||||
|
self.speedVar.set('%0.2f' % self.playbackSF)
|
||||||
|
|
||||||
def playbackTask(self, state):
|
def playbackTask(self, state):
|
||||||
time = globalClock.getFrameTime()
|
time = globalClock.getFrameTime()
|
||||||
@ -1323,13 +1293,19 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Also kill record task
|
# Also kill record task
|
||||||
self.toggleRecordVar()
|
self.toggleRecordVar()
|
||||||
return Task.done
|
return Task.done
|
||||||
elif (((self.loopPlayback == 0) and (cTime > self.maxT)) or
|
elif ((self.loopPlayback == 0) and (cTime > self.maxT)):
|
||||||
((self.recordingType.get() == 'Extend') and (cTime > self.maxT))):
|
|
||||||
# Go to maxT
|
# Go to maxT
|
||||||
self.getWidget('Playback', 'Time').set(self.maxT)
|
self.getWidget('Playback', 'Time').set(self.maxT)
|
||||||
# Then stop playback
|
# Then stop playback
|
||||||
self.stopPlayback()
|
self.stopPlayback()
|
||||||
return Task.done
|
return Task.done
|
||||||
|
elif ((self.recordingType.get() == 'Extend') and
|
||||||
|
(cTime > self.controlStart)):
|
||||||
|
# Go to final point
|
||||||
|
self.getWidget('Playback', 'Time').set(self.controlStart)
|
||||||
|
# Stop playback
|
||||||
|
self.stopPlayback()
|
||||||
|
return Task.done
|
||||||
# Otherwise go to specified time and continue
|
# Otherwise go to specified time and continue
|
||||||
self.getWidget('Playback', 'Time').set(cTime)
|
self.getWidget('Playback', 'Time').set(cTime)
|
||||||
state.currentTime = cTime
|
state.currentTime = cTime
|
||||||
@ -1363,51 +1339,39 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
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.curveFitter.desample(self.desampleFrequency)
|
self.curveFitter.desample(self.desampleFrequency)
|
||||||
|
# Compute new curve based on desampled data
|
||||||
self.computeCurves()
|
self.computeCurves()
|
||||||
# Get new point set based on newly created curve
|
# Get point set from the curve fitter
|
||||||
self.createNewPointSet()
|
self.extractPointSetFromCurveFitter()
|
||||||
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])
|
|
||||||
|
|
||||||
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, fCompute = 1):
|
||||||
if self.curveCollection == 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.curveFitter.reset()
|
self.curveFitter.reset()
|
||||||
# Get new data points based on given curve
|
# Sample curve using specified number of samples
|
||||||
if even == 'None Given':
|
|
||||||
even = self.fEven
|
|
||||||
# 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:
|
|
||||||
# MRM: To be added, face forward
|
|
||||||
pass
|
|
||||||
self.curveFitter.sample(self.curveCollection, self.numSamples)
|
self.curveFitter.sample(self.curveCollection, self.numSamples)
|
||||||
|
if fCompute:
|
||||||
# Now recompute curves
|
# Now recompute curves
|
||||||
self.computeCurves()
|
self.computeCurves()
|
||||||
# Get new point set based on newly created curve
|
# Get point set from the curve fitter
|
||||||
self.createNewPointSet()
|
self.extractPointSetFromCurveFitter()
|
||||||
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])
|
|
||||||
|
|
||||||
def setEven(self):
|
def makeEven(self):
|
||||||
self.fEven = self.getVariable('Resample', 'Even').get()
|
# Note: segments_per_unit = 2 seems to give a good fit
|
||||||
|
self.curveCollection.makeEven(self.maxT, 2)
|
||||||
|
# Get point set from curve
|
||||||
|
self.extractPointSetFromCurveCollection()
|
||||||
|
|
||||||
def setForward(self):
|
def faceForward(self):
|
||||||
self.fForward = self.getVariable('Resample', 'Forward').get()
|
# Note: segments_per_unit = 2 seems to give a good fit
|
||||||
|
self.curveCollection.faceForward(2)
|
||||||
|
# Get point set from curve
|
||||||
|
self.extractPointSetFromCurveCollection()
|
||||||
|
|
||||||
def setPathDuration(self, event):
|
def setPathDuration(self, event):
|
||||||
newMaxT = float(self.getWidget('Resample', 'Path Duration').get())
|
newMaxT = float(self.getWidget('Resample', 'Path Duration').get())
|
||||||
@ -1662,8 +1626,11 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.curveCollection.addCurves(nodePath.node())
|
self.curveCollection.addCurves(nodePath.node())
|
||||||
nodePath.removeNode()
|
nodePath.removeNode()
|
||||||
if self.curveCollection:
|
if self.curveCollection:
|
||||||
|
# Draw the curve
|
||||||
|
self.nurbsCurveDrawer.setCurves(self.curveCollection)
|
||||||
|
self.nurbsCurveDrawer.draw()
|
||||||
# Save a pointset for this curve
|
# Save a pointset for this curve
|
||||||
self.savePointSet()
|
self.extractPointSetFromCurveCollection()
|
||||||
else:
|
else:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
@ -1693,13 +1660,12 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
self.curveCollection.writeEgg(Filename(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)
|
||||||
node, hitPt, hitPtDist = self.iRay.pickGeom3D()
|
node, hitPt, hitPtDist = self.iRay.pickGeom3D()
|
||||||
if node:
|
if node:
|
||||||
self['nodePath'].setZ(self['nodePath'], height - hitPtDist)
|
self.nodePath.setZ(self.nodePath, height - hitPtDist)
|
||||||
self.iRay.rayCollisionNodePath.reparentTo(self.recorderNodePath)
|
self.iRay.rayCollisionNodePath.reparentTo(self.recorderNodePath)
|
||||||
|
|
||||||
|
|
||||||
## WIDGET UTILITY FUNCTIONS ##
|
## WIDGET UTILITY FUNCTIONS ##
|
||||||
def addWidget(self, widget, category, text):
|
def addWidget(self, widget, category, text):
|
||||||
self.widgetDict[category + '-' + text] = widget
|
self.widgetDict[category + '-' + text] = widget
|
||||||
@ -1888,4 +1854,3 @@ class MopathRecorder(AppShell, PandaObject):
|
|||||||
# Record widget
|
# Record widget
|
||||||
self.widgetDict[category + '-' + text] = widget
|
self.widgetDict[category + '-' + text] = widget
|
||||||
return widget
|
return widget
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user