| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074 |
- #################################################################
- # seMopathRecorder.py
- # Originally from MopathRecorder.py
- # Altered by Yi-Hong Lin, [email protected], 2004
- #
- # We have to change something about data flow and UI
- # so the curves data can be saved into our dataHolder.
- # Other things we have changed here is that we have added a copy model
- # of target nodePath under the render when the recording begins.
- # And, of course, we have removed it right after the recording ends.
- # You can find it in toggleRecord function.
- #
- #################################################################
- # Import Tkinter, Pmw, and the dial code from this directory tree.
- from direct.showbase.DirectObject import *
- from direct.showbase.TkGlobal import *
- from direct.tkwidgets.AppShell import *
- from direct.directtools.DirectGlobals import *
- from direct.directtools.DirectUtil import *
- from seGeometry import *
- from seSelection import *
- from tkFileDialog import *
- import os
- import string
- from direct.tkwidgets import Dial
- from direct.tkwidgets import Floater
- from direct.tkwidgets import Slider
- from direct.tkwidgets import EntryScale
- from direct.tkwidgets import VectorWidgets
- import __builtin__
- PRF_UTILITIES = [
- 'lambda: camera.lookAt(render)',
- 'lambda: camera.setZ(render, 0.0)',
- 'lambda s = self: s.playbackMarker.lookAt(render)',
- 'lambda s = self: s.playbackMarker.setZ(render, 0.0)',
- 'lambda s = self: s.followTerrain(10.0)']
- class MopathRecorder(AppShell, DirectObject):
- # Override class variables here
- appname = 'Mopath Recorder Panel'
- frameWidth = 450
- frameHeight = 550
- usecommandarea = 0
- usestatusarea = 0
- count = 0
- def __init__(self, parent = None, **kw):
- INITOPT = Pmw.INITOPT
- name = 'recorder-%d' % MopathRecorder.count
- MopathRecorder.count += 1
- optiondefs = (
- ('title', self.appname, None),
- ('nodePath', None, None),
- ('name', name, None)
- )
- self.defineoptions(kw, optiondefs)
- # Call superclass initialization function
- AppShell.__init__(self)
-
- self.initialiseoptions(MopathRecorder)
- self.selectNodePathNamed('camera')
- self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
- def appInit(self):
- self.mopathRecorderNode = render.attachNewNode("MopathRecorder")
- self.name = self['name']
- # Dictionary of widgets
- self.widgetDict = {}
- self.variableDict = {}
- # 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 = self.mopathRecorderNode.attachNewNode(self.name)
- # Temp CS for use in refinement/path extension
- self.tempCS = self.recorderNodePath.attachNewNode(
- 'mopathRecorderTempCS')
- # Marker for use in playback
- self.playbackMarker = loader.loadModel('models/misc/sphere') ###
- self.playbackMarker.setName('Playback Marker')
- self.playbackMarker.reparentTo(self.recorderNodePath)
- self.playbackMarkerIds = self.getChildIds(
- self.playbackMarker.getChild(0))
- self.playbackMarker.hide()
- # Tangent marker
- self.tangentGroup = self.playbackMarker.attachNewNode('Tangent Group')
- self.tangentGroup.hide()
- self.tangentMarker = loader.loadModel('models/misc/sphere')
- self.tangentMarker.reparentTo(self.tangentGroup)
- self.tangentMarker.setScale(0.5)
- self.tangentMarker.setColor(1,0,1,1)
- self.tangentMarker.setName('Tangent Marker')
- self.tangentMarkerIds = self.getChildIds(
- self.tangentMarker.getChild(0))
- self.tangentLines = LineNodePath(self.tangentGroup)
- self.tangentLines.setColor(VBase4(1,0,1,1))
- self.tangentLines.setThickness(1)
- self.tangentLines.moveTo(0,0,0)
- self.tangentLines.drawTo(0,0,0)
- self.tangentLines.create()
- # Active node path dictionary
- self.nodePathDict = {}
- self.nodePathDict['marker'] = self.playbackMarker
- self.nodePathDict['camera'] = camera
- self.nodePathDict['widget'] = SEditor.widget
- self.nodePathDict['mopathRecorderTempCS'] = self.tempCS
- self.nodePathNames = ['marker', 'camera', 'selected']
- # ID of selected object
- self.manipulandumId = None
- self.trace = LineNodePath(self.recorderNodePath)
- self.oldPlaybackNodePath = None
- # Count of point sets recorded
- self.pointSet = []
- self.prePoints = []
- self.postPoints = []
- self.pointSetDict = {}
- self.pointSetCount = 0
- self.pointSetName = self.name + '-ps-' + `self.pointSetCount`
- # User callback to call before recording point
- self.samplingMode = 'Continuous'
- self.preRecordFunc = None
- # Hook to start/stop recording
- self.startStopHook = 'f6'
- self.keyframeHook = 'f10'
- # Curve fitter object
- self.lastPos = Point3(0)
- self.curveFitter = CurveFitter()
- # Curve variables
- # Number of ticks per parametric unit
- self.numTicks = 1
- # Number of segments to represent each parametric unit
- # This just affects the visual appearance of the curve
- self.numSegs = 40
- # The nurbs curves
- self.curveCollection = None
- # Curve drawers
- 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.nurbsCurveDrawer.setTickScale(5.0)
- self.curveNodePath = self.recorderNodePath.attachNewNode(
- self.nurbsCurveDrawer.getGeomNode())
- useDirectRenderStyle(self.curveNodePath)
- # Playback variables
- self.maxT = 0.0
- self.playbackTime = 0.0
- self.loopPlayback = 1
- self.playbackSF = 1.0
- # Sample variables
- self.desampleFrequency = 1
- self.numSamples = 100
- self.recordStart = 0.0
- self.deltaTime = 0.0
- self.controlStart = 0.0
- self.controlStop = 0.0
- self.recordStop = 0.0
- self.cropFrom = 0.0
- self.cropTo = 0.0
- self.fAdjustingValues = 0
- # For terrain following
- self.iRayCS = self.recorderNodePath.attachNewNode(
- 'mopathRecorderIRayCS')
- self.iRay = SelectionRay(self.iRayCS)
- # Set up event hooks
- self.actionEvents = [
- ('DIRECT_undo', self.undoHook),
- ('DIRECT_pushUndo', self.pushUndoHook),
- ('DIRECT_undoListEmpty', self.undoListEmptyHook),
- ('DIRECT_redo', self.redoHook),
- ('DIRECT_pushRedo', self.pushRedoHook),
- ('DIRECT_redoListEmpty', self.redoListEmptyHook),
- ('DIRECT_selectedNodePath', self.selectedNodePathHook),
- ('DIRECT_deselectedNodePath', self.deselectedNodePathHook),
- ('DIRECT_manipulateObjectStart', self.manipulateObjectStartHook),
- ('DIRECT_manipulateObjectCleanup',
- self.manipulateObjectCleanupHook),
- ]
- for event, method in self.actionEvents:
- self.accept(event, method)
- def createInterface(self):
- interior = self.interior()
- # FILE MENU
- # Get a handle on the file menu so commands can be inserted
- # before quit item
- fileMenu = self.menuBar.component('File-menu')
- fileMenu.insert_command(
- fileMenu.index('Quit'),
- label = 'Load Curve',
- command = self.loadCurveFromFile)
- fileMenu.insert_command(
- fileMenu.index('Quit'),
- label = 'Save Curve',
- command = self.saveCurveToFile)
- # Add mopath recorder commands to menubar
- self.menuBar.addmenu('Recorder', 'Mopath Recorder Panel Operations')
- self.menuBar.addmenuitem(
- 'Recorder', 'command',
- 'Save current curve as a new point set',
- label = 'Save Point Set',
- command = self.extractPointSetFromCurveCollection)
- self.menuBar.addmenuitem(
- 'Recorder', 'command',
- 'Toggle widget visability',
- label = 'Toggle Widget Vis',
- command = self.toggleWidgetVis)
- self.menuBar.addmenuitem(
- 'Recorder', 'command',
- 'Toggle widget manipulation mode',
- label = 'Toggle Widget Mode',
- command = SEditor.manipulationControl.toggleObjectHandlesMode)
- self.historyWidget = self.createComboBox(self.menuFrame, 'Mopath', 'Path:',
- 'Select input points to fit curve to', '',
- self.selectPointSetNamed, expand = 1)
- self.undoButton = Button(self.menuFrame, text = 'Undo',
- command = SEditor.undo)
- if SEditor.undoList:
- self.undoButton['state'] = 'normal'
- else:
- self.undoButton['state'] = 'disabled'
- self.undoButton.pack(side = LEFT, expand = 0)
- self.bind(self.undoButton, 'Undo last operation')
- self.redoButton = Button(self.menuFrame, text = 'Redo',
- command = SEditor.redo)
- if SEditor.redoList:
- self.redoButton['state'] = 'normal'
- else:
- self.redoButton['state'] = 'disabled'
- self.redoButton.pack(side = LEFT, expand = 0)
- self.bind(self.redoButton, 'Redo last operation')
- # Record button
- mainFrame = Frame(interior, relief = SUNKEN, borderwidth = 2)
- frame = Frame(mainFrame)
- # Active node path
- # Button to select active node path
- widget = self.createButton(frame, 'Recording', 'Node Path:',
- 'Select Active Mopath Node Path',
- lambda s = self: SEditor.select(s.nodePath),
- side = LEFT, expand = 0)
- widget['relief'] = FLAT
- self.nodePathMenu = Pmw.ComboBox(
- 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.set('New Curve')
- widget = self.createRadiobutton(
- frame, 'left',
- 'Recording', 'New Curve',
- ('Next record session records a new path'),
- self.recordingType, 'New Curve',expand = 0)
- widget = self.createRadiobutton(
- frame, 'left',
- 'Recording', 'Refine',
- ('Next record session refines existing path'),
- self.recordingType, 'Refine', expand = 0)
- widget = self.createRadiobutton(
- frame, 'left',
- 'Recording', 'Extend',
- ('Next record session extends existing path'),
- self.recordingType, 'Extend', expand = 0)
- 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)
- widget = self.createButton(frame, 'Recording', 'Bind Path to Node',
- 'Bind Motion Path to selected Object',
- self.bindMotionPathToNode,
- side = LEFT, expand = 1)
- frame.pack(fill = X, expand = 1)
-
- mainFrame.pack(expand = 1, fill = X, pady = 3)
-
- # Playback controls
- playbackFrame = Frame(interior, relief = SUNKEN,
- borderwidth = 2)
- Label(playbackFrame, text = 'PLAYBACK CONTROLS',
- font=('MSSansSerif', 12, 'bold')).pack(fill = X)
- # Main playback control slider
- widget = self.createEntryScale(
- playbackFrame, 'Playback', 'Time', 'Set current playback time',
- resolution = 0.01, command = self.playbackGoTo, side = TOP)
- widget.component('hull')['relief'] = RIDGE
- # Kill playback task if drag slider
- widget['preCallback'] = self.stopPlayback
- # Jam duration entry into entry scale
- self.createLabeledEntry(widget.labelFrame, 'Resample', 'Path Duration',
- 'Set total curve duration',
- command = self.setPathDuration,
- side = LEFT, expand = 0)
- # Start stop buttons
- frame = Frame(playbackFrame)
- widget = self.createButton(frame, 'Playback', '<<',
- 'Jump to start of playback',
- self.jumpToStartOfPlayback,
- side = LEFT, expand = 1)
- widget['font'] = (('MSSansSerif', 12, 'bold'))
- widget = self.createCheckbutton(frame, 'Playback', 'Play',
- 'Start/Stop playback',
- self.startStopPlayback, 0,
- side = LEFT, fill = BOTH, expand = 1)
- widget.configure(anchor = 'center', justify = 'center',
- relief = RAISED, font = ('MSSansSerif', 12, 'bold'))
- widget = self.createButton(frame, 'Playback', '>>',
- 'Jump to end of playback',
- self.jumpToEndOfPlayback,
- side = LEFT, expand = 1)
- widget['font'] = (('MSSansSerif', 12, 'bold'))
- self.createCheckbutton(frame, 'Playback', 'Loop',
- 'On: loop playback',
- self.setLoopPlayback, self.loopPlayback,
- side = LEFT, fill = BOTH, expand = 0)
- 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)
- # Create notebook pages
- self.mainNotebook = Pmw.NoteBook(interior)
- self.mainNotebook.pack(fill = BOTH, expand = 1)
- self.resamplePage = self.mainNotebook.add('Resample')
- self.refinePage = self.mainNotebook.add('Refine')
- self.extendPage = self.mainNotebook.add('Extend')
- self.cropPage = self.mainNotebook.add('Crop')
- self.drawPage = self.mainNotebook.add('Draw')
- self.optionsPage = self.mainNotebook.add('Options')
- ## RESAMPLE PAGE
- label = Label(self.resamplePage, text = 'RESAMPLE CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = X)
-
- # Resample
- resampleFrame = Frame(
- self.resamplePage, relief = SUNKEN, borderwidth = 2)
- label = Label(resampleFrame, text = 'RESAMPLE CURVE',
- font=('MSSansSerif', 12, 'bold')).pack()
- widget = self.createSlider(
- resampleFrame, 'Resample', 'Num. Samples',
- 'Number of samples in resampled curve',
- resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
- widget.component('hull')['relief'] = RIDGE
- widget['postCallback'] = self.sampleCurve
- frame = Frame(resampleFrame)
- self.createButton(
- frame, 'Resample', 'Make Even',
- 'Apply timewarp so resulting path has constant velocity',
- self.makeEven, side = LEFT, fill = X, expand = 1)
- self.createButton(
- frame, 'Resample', 'Face Forward',
- 'Compute HPR so resulting hpr curve faces along xyz tangent',
- self.faceForward, side = LEFT, fill = X, expand = 1)
- frame.pack(fill = X, 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.createSlider(
- desampleFrame, 'Resample', 'Points Between Samples',
- 'Specify number of points to skip between samples',
- min = 1, max = 100, resolution = 1,
- command = self.setDesampleFrequency)
- widget.component('hull')['relief'] = RIDGE
- widget['postCallback'] = self.desampleCurve
- desampleFrame.pack(fill = X, expand = 0, pady = 2)
- ## REFINE PAGE ##
- refineFrame = Frame(self.refinePage, relief = SUNKEN,
- borderwidth = 2)
- label = Label(refineFrame, text = 'REFINE CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = X)
- widget = self.createSlider(refineFrame,
- 'Refine Page', 'Refine From',
- 'Begin time of refine pass',
- resolution = 0.01,
- command = self.setRecordStart)
- widget['preCallback'] = self.setRefineMode
- widget['postCallback'] = lambda s = self: s.getPrePoints('Refine')
- widget = self.createSlider(
- refineFrame, 'Refine Page',
- 'Control Start',
- 'Time when full control of node path is given during refine pass',
- resolution = 0.01,
- command = self.setControlStart)
- widget['preCallback'] = self.setRefineMode
- widget = self.createSlider(
- refineFrame, 'Refine Page',
- 'Control Stop',
- 'Time when node path begins transition back to original curve',
- resolution = 0.01,
- command = self.setControlStop)
- widget['preCallback'] = self.setRefineMode
- widget = self.createSlider(refineFrame, 'Refine Page', 'Refine To',
- 'Stop time of refine pass',
- resolution = 0.01,
- command = self.setRefineStop)
- widget['preCallback'] = self.setRefineMode
- widget['postCallback'] = self.getPostPoints
- refineFrame.pack(fill = X)
- ## EXTEND PAGE ##
- extendFrame = Frame(self.extendPage, relief = SUNKEN,
- borderwidth = 2)
- label = Label(extendFrame, text = 'EXTEND CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = X)
- widget = self.createSlider(extendFrame,
- 'Extend Page', 'Extend From',
- 'Begin time of extend pass',
- resolution = 0.01,
- command = self.setRecordStart)
- widget['preCallback'] = self.setExtendMode
- widget['postCallback'] = lambda s = self: s.getPrePoints('Extend')
- widget = self.createSlider(
- extendFrame, 'Extend Page',
- 'Control Start',
- 'Time when full control of node path is given during extend pass',
- resolution = 0.01,
- command = self.setControlStart)
- widget['preCallback'] = self.setExtendMode
- extendFrame.pack(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.createSlider(
- cropFrame,
- 'Crop Page', 'Crop From',
- 'Delete all curve points before this time',
- resolution = 0.01,
- command = self.setCropFrom)
- widget = self.createSlider(
- 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)
- ## DRAW PAGE ##
- drawFrame = Frame(self.drawPage, relief = SUNKEN,
- borderwidth = 2)
- 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'))
- label.pack(fill = X)
- frame = Frame(sfFrame)
- Label(frame, text = 'SHOW:').pack(side = LEFT, expand = 0)
- widget = self.createCheckbutton(
- frame, 'Style', 'Path',
- 'On: path is visible', self.setPathVis, 1,
- side = LEFT, fill = X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Knots',
- 'On: path knots are visible', self.setKnotVis, 1,
- side = LEFT, fill = X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'CVs',
- 'On: path CVs are visible', self.setCvVis, 0,
- side = LEFT, fill = X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Hull',
- 'On: path hull is visible', self.setHullVis, 0,
- side = LEFT, fill = X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Trace',
- 'On: record is visible', self.setTraceVis, 0,
- side = LEFT, fill = X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Marker',
- 'On: playback marker is visible', self.setMarkerVis, 0,
- side = LEFT, fill = X, expand = 1)
- frame.pack(fill = X, expand = 1)
- # Sliders
- widget = self.createSlider(
- sfFrame, 'Style', 'Num Segs',
- 'Set number of segments used to approximate each parametric unit',
- min = 1.0, max = 400, resolution = 1.0,
- value = 40,
- command = self.setNumSegs, side = TOP)
- widget.component('hull')['relief'] = RIDGE
- widget = self.createSlider(
- sfFrame, 'Style', 'Num Ticks',
- 'Set number of tick marks drawn for each unit of time',
- min = 0.0, max = 10.0, resolution = 1.0,
- value = 0.0,
- command = self.setNumTicks, side = TOP)
- widget.component('hull')['relief'] = RIDGE
- widget = self.createSlider(
- sfFrame, 'Style', 'Tick Scale',
- 'Set visible size of time tick marks',
- min = 0.01, max = 100.0, resolution = 0.01,
- value = 5.0,
- command = self.setTickScale, side = TOP)
- widget.component('hull')['relief'] = RIDGE
- self.createColorEntry(
- sfFrame, 'Style', 'Path Color',
- 'Color of curve',
- command = self.setPathColor,
- value = [255.0,255.0,255.0,255.0])
- self.createColorEntry(
- sfFrame, 'Style', 'Knot Color',
- 'Color of knots',
- command = self.setKnotColor,
- value = [0,0,255.0,255.0])
- self.createColorEntry(
- sfFrame, 'Style', 'CV Color',
- 'Color of CVs',
- command = self.setCvColor,
- value = [255.0,0,0,255.0])
- self.createColorEntry(
- sfFrame, 'Style', 'Tick Color',
- 'Color of Ticks',
- command = self.setTickColor,
- value = [255.0,0,0,255.0])
- self.createColorEntry(
- sfFrame, 'Style', 'Hull Color',
- 'Color of Hull',
- command = self.setHullColor,
- value = [255.0,128.0,128.0,255.0])
- #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',
- value = 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',
- value = 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()
-
- def pushUndo(self, fResetRedo = 1):
- SEditor.pushUndo([self.nodePath])
- def undoHook(self):
- # Reflect new changes
- pass
- def pushUndoHook(self):
- # Make sure button is reactivated
- self.undoButton.configure(state = 'normal')
- def undoListEmptyHook(self):
- # Make sure button is deactivated
- self.undoButton.configure(state = 'disabled')
- def pushRedo(self):
- SEditor.pushRedo([self.nodePath])
-
- def redoHook(self):
- # Reflect new changes
- pass
- def pushRedoHook(self):
- # Make sure button is reactivated
- self.redoButton.configure(state = 'normal')
- def redoListEmptyHook(self):
- # Make sure button is deactivated
- self.redoButton.configure(state = 'disabled')
-
- def selectedNodePathHook(self, nodePath):
- """
- Hook called upon selection of a node path used to select playback
- marker if subnode selected
- """
- taskMgr.remove(self.name + '-curveEditTask')
- print nodePath.id()
- if nodePath.id() in self.playbackMarkerIds:
- SEditor.select(self.playbackMarker)
- elif nodePath.id() in self.tangentMarkerIds:
- SEditor.select(self.tangentMarker)
- elif nodePath.id() == self.playbackMarker.id():
- self.tangentGroup.show()
- taskMgr.add(self.curveEditTask,
- self.name + '-curveEditTask')
- elif nodePath.id() == self.tangentMarker.id():
- self.tangentGroup.show()
- taskMgr.add(self.curveEditTask,
- self.name + '-curveEditTask')
- else:
- self.tangentGroup.hide()
- def getChildIds(self, nodePath):
- ids = [nodePath.id()]
- kids = nodePath.getChildrenAsList()
- for kid in kids:
- ids += self.getChildIds(kid)
- return ids
- def deselectedNodePathHook(self, nodePath):
- """
- Hook called upon deselection of a node path used to select playback
- marker if subnode selected
- """
- if ((nodePath.id() == self.playbackMarker.id()) or
- (nodePath.id() == self.tangentMarker.id())):
- self.tangentGroup.hide()
- def curveEditTask(self,state):
- if self.curveCollection != None:
- # Update curve position
- if self.manipulandumId == self.playbackMarker.id():
- # Show playback marker
- self.playbackMarker.getChild(0).show()
- pos = Point3(0)
- hpr = Point3(0)
- pos = self.playbackMarker.getPos(self.nodePathParent)
- hpr = self.playbackMarker.getHpr(self.nodePathParent)
- self.curveCollection.adjustXyz(
- self.playbackTime, VBase3(pos[0], pos[1], pos[2]))
- self.curveCollection.adjustHpr(
- self.playbackTime, VBase3(hpr[0], hpr[1], hpr[2]))
- # Note: this calls recompute on the curves
- self.nurbsCurveDrawer.draw()
- # Update tangent
- if self.manipulandumId == self.tangentMarker.id():
- # If manipulating marker, update tangent
- # Hide playback marker
- self.playbackMarker.getChild(0).hide()
- # Where is tangent marker relative to playback marker
- tan = self.tangentMarker.getPos()
- # Transform this vector to curve space
- tan2Curve = Vec3(
- self.playbackMarker.getMat(
- self.nodePathParent).xformVec(tan))
- # Update nurbs curve
- self.curveCollection.getXyzCurve().adjustTangent(
- self.playbackTime,
- tan2Curve[0], tan2Curve[1], tan2Curve[2])
- # Note: this calls recompute on the curves
- self.nurbsCurveDrawer.draw()
- else:
- # Show playback marker
- self.playbackMarker.getChild(0).show()
- # Update tangent marker line
- tan = Point3(0)
- self.curveCollection.getXyzCurve().getTangent(
- self.playbackTime, tan)
- # Transform this point to playback marker space
- tan.assign(
- self.nodePathParent.getMat(
- self.playbackMarker).xformVec(tan))
- self.tangentMarker.setPos(tan)
- # In either case update tangent line
- self.tangentLines.setVertex(1, tan[0], tan[1], tan[2])
- return Task.cont
- def manipulateObjectStartHook(self):
- self.manipulandumId = None
- if SEditor.selected.last:
- if SEditor.selected.last.id() == self.playbackMarker.id():
- self.manipulandumId = self.playbackMarker.id()
- elif SEditor.selected.last.id() == self.tangentMarker.id():
- self.manipulandumId = self.tangentMarker.id()
-
- def manipulateObjectCleanupHook(self):
- # Clear flag
- self.manipulandumId = None
-
- def onDestroy(self, event):
- # Remove hooks
- for event, method in self.actionEvents:
- self.ignore(event)
- # remove start stop hook
- self.ignore(self.startStopHook)
- self.ignore(self.keyframeHook)
- self.curveNodePath.reparentTo(self.recorderNodePath)
- self.trace.reparentTo(self.recorderNodePath)
- self.recorderNodePath.removeNode()
- # Make sure markers are deselected
- SEditor.deselect(self.playbackMarker)
- SEditor.deselect(self.tangentMarker)
- # Remove tasks
- taskMgr.remove(self.name + '-recordTask')
- taskMgr.remove(self.name + '-playbackTask')
- taskMgr.remove(self.name + '-curveEditTask')
- self.mopathRecorderNode.removeChildren()
- self.mopathRecorderNode.removeNode()
- messenger.send('mPath_close')
- messenger.send('SGE_Update Explorer',[render])
- def createNewPointSet(self, curveName = None):
- if curveName == None:
- self.pointSetName = self.name + '-ps-' + `self.pointSetCount`
- else:
- self.pointSetName = curveName
- # Update dictionary and record pointer to new point set
- self.pointSet = self.pointSetDict[self.pointSetName] = []
- # Update combo box
- comboBox = self.getWidget('Mopath', 'Path:')
- scrolledList = comboBox.component('scrolledlist')
- listbox = scrolledList.component('listbox')
- names = list(listbox.get(0,'end'))
- names.append(self.pointSetName)
- scrolledList.setlist(names)
- comboBox.selectitem(self.pointSetName)
- # Update count
- self.pointSetCount += 1
- def extractPointSetFromCurveFitter(self, curveName = None):
- # Get new point set based on newly created curve
- self.createNewPointSet(curveName)
- 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, curveName=None):
- # 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, curveName = curveName)
- # Update widgets based on new data
- self.updateWidgets()
- def selectPointSetNamed(self, name):
- self.pointSet = self.pointSetDict.get(name, None)
- # Reload points into curve fitter
- # Reset curve fitters
- self.curveFitter.reset()
- for time, pos, hpr in self.pointSet:
- # Add it to the curve fitters
- self.curveFitter.addXyzHpr(time, pos, hpr)
- # Compute curve
- self.computeCurves()
- def setPathVis(self):
- if self.getVariable('Style', 'Path').get():
- self.curveNodePath.show()
- else:
- self.curveNodePath.hide()
-
- def setKnotVis(self):
- self.nurbsCurveDrawer.setShowKnots(
- self.getVariable('Style', 'Knots').get())
- def setCvVis(self):
- self.nurbsCurveDrawer.setShowCvs(
- self.getVariable('Style', 'CVs').get())
-
- def setHullVis(self):
- self.nurbsCurveDrawer.setShowHull(
- self.getVariable('Style', 'Hull').get())
-
- def setTraceVis(self):
- if self.getVariable('Style', 'Trace').get():
- self.trace.show()
- else:
- self.trace.hide()
- def setMarkerVis(self):
- if self.getVariable('Style', 'Marker').get():
- self.playbackMarker.reparentTo(self.recorderNodePath)
- else:
- self.playbackMarker.reparentTo(hidden)
- def setNumSegs(self, value):
- self.numSegs = int(value)
- self.nurbsCurveDrawer.setNumSegs(self.numSegs)
-
- def setNumTicks(self, value):
- self.nurbsCurveDrawer.setNumTicks(float(value))
-
- def setTickScale(self, value):
- self.nurbsCurveDrawer.setTickScale(float(value))
- def setPathColor(self, color):
- self.nurbsCurveDrawer.setColor(
- color[0]/255.0,color[1]/255.0,color[2]/255.0)
- self.nurbsCurveDrawer.draw()
- def setKnotColor(self, color):
- self.nurbsCurveDrawer.setKnotColor(
- color[0]/255.0,color[1]/255.0,color[2]/255.0)
- def setCvColor(self, color):
- self.nurbsCurveDrawer.setCvColor(
- color[0]/255.0,color[1]/255.0,color[2]/255.0)
- def setTickColor(self, color):
- self.nurbsCurveDrawer.setTickColor(
- color[0]/255.0,color[1]/255.0,color[2]/255.0)
- def setHullColor(self, color):
- self.nurbsCurveDrawer.setHullColor(
- color[0]/255.0,color[1]/255.0,color[2]/255.0)
- def setStartStopHook(self, event = None):
- # Clear out old hook
- self.ignore(self.startStopHook)
- # Record new one
- hook = self.getVariable('Recording', 'Record Hook').get()
- self.startStopHook = hook
- # Add new one
- self.accept(self.startStopHook, self.toggleRecordVar)
- def setKeyframeHook(self, event = None):
- # Clear out old hook
- self.ignore(self.keyframeHook)
- # Record new one
- hook = self.getVariable('Recording', 'Keyframe Hook').get()
- self.keyframeHook = hook
- # Add new one
- self.accept(self.keyframeHook, self.addKeyframe)
- def reset(self):
- self.pointSet = []
- self.hasPoints = 0
- self.curveCollection = None
- self.curveFitter.reset()
- self.nurbsCurveDrawer.hide()
-
- def setSamplingMode(self, mode):
- self.samplingMode = mode
- def disableKeyframeButton(self):
- self.getWidget('Recording', 'Add Keyframe')['state'] = 'disabled'
- def enableKeyframeButton(self):
- self.getWidget('Recording', 'Add Keyframe')['state'] = 'normal'
- def setRecordingType(self, type):
- self.recordingType.set(type)
- def setNewCurveMode(self):
- self.setRecordingType('New Curve')
- def setRefineMode(self):
- self.setRecordingType('Refine')
-
- def setExtendMode(self):
- self.setRecordingType('Extend')
- def toggleRecordVar(self):
- # Get recording variable
- v = self.getVariable('Recording', 'Record')
- # Toggle it
- v.set(1 - v.get())
- # Call the command
- self.toggleRecord()
- def toggleRecord(self):
- if self.getVariable('Recording', 'Record').get():
- # Reparent a Marker to target nodePath to show where the recording start
- self.markingNode = self.nodePath.getParent().attachNewNode('MopthMarkerNode')
- self.nodePath.copyTo(self.markingNode)
- self.markingNode.wrtReparentTo(render)
- # Kill old tasks
- taskMgr.remove(self.name + '-recordTask')
- taskMgr.remove(self.name + '-curveEditTask')
- # Remove old curve
- self.nurbsCurveDrawer.hide()
- # Reset curve fitters
- self.curveFitter.reset()
- # Update sampling mode button if necessary
- if self.samplingMode == 'Continuous':
- self.disableKeyframeButton()
- # Create a new point set to hold raw data
- self.createNewPointSet()
- # Clear out old trace, get ready to draw new
- self.initTrace()
- # Keyframe mode?
- if (self.samplingMode == 'Keyframe'):
- # Record first point
- self.lastPos.assign(Point3(
- self.nodePath.getPos(self.nodePathParent)))
- # Init delta time
- self.deltaTime = 0.0
- # Record first point
- self.recordPoint(self.recordStart)
- # Everything else
- else:
- if ((self.recordingType.get() == 'Refine') or
- (self.recordingType.get() == 'Extend')):
- # Turn off looping playback
- self.loopPlayback = 0
- # Update widget to reflect new value
- self.getVariable('Playback', 'Loop').set(0)
- # Select tempCS as playback nodepath
- self.oldPlaybackNodePath = self.playbackNodePath
- self.setPlaybackNodePath(self.tempCS)
- # Parent record node path to temp
- self.nodePath.reparentTo(self.playbackNodePath)
- # Align with temp
- self.nodePath.setPosHpr(0,0,0,0,0,0)
- # Set playback start to self.recordStart
- self.playbackGoTo(self.recordStart)
- # start flying nodePath along path
- self.startPlayback()
- # Start new task
- t = taskMgr.add(
- self.recordTask, self.name + '-recordTask')
- t.startTime = globalClock.getFrameTime()
- else:
- self.markingNode.removeNode() # Hide the marker in the end of recording
- if self.samplingMode == 'Continuous':
- # Kill old task
- taskMgr.remove(self.name + '-recordTask')
- if ((self.recordingType.get() == 'Refine') or
- (self.recordingType.get() == 'Extend')):
- # Reparent node path back to parent
- self.nodePath.wrtReparentTo(self.nodePathParent)
- # Restore playback Node Path
- self.setPlaybackNodePath(self.oldPlaybackNodePath)
- else:
- # Add last point
- self.addKeyframe(0)
- # Reset sampling mode
- self.setSamplingMode('Continuous')
- self.enableKeyframeButton()
- # Clean up after refine or extend
- if ((self.recordingType.get() == 'Refine') or
- (self.recordingType.get() == 'Extend')):
- # Merge prePoints, pointSet, postPoints
- self.mergePoints()
- # Clear out pre and post list
- self.prePoints = []
- self.postPoints = []
- # Reset recording mode
- self.setNewCurveMode()
- # Compute curve
- self.computeCurves()
-
- def recordTask(self, state):
- # Record raw data point
- time = self.recordStart + (
- globalClock.getFrameTime() - state.startTime)
- self.recordPoint(time)
- return Task.cont
- def addKeyframe(self, fToggleRecord = 1):
- # Make sure we're in a recording mode!
- if (fToggleRecord and
- (not self.getVariable('Recording', 'Record').get())):
- # Set sampling mode
- self.setSamplingMode('Keyframe')
- # This will automatically add the first point
- self.toggleRecordVar()
- else:
- # Use distance as a time
- pos = self.nodePath.getPos(self.nodePathParent)
- deltaPos = Vec3(pos - self.lastPos).length()
- if deltaPos != 0:
- # If we've moved at all, use delta Pos as time
- self.deltaTime = self.deltaTime + deltaPos
- else:
- # Otherwise add one second
- self.deltaTime = self.deltaTime + 1.0
- # Record point at new time
- self.recordPoint(self.recordStart + self.deltaTime)
- # Update last pos
- self.lastPos.assign(pos)
- def easeInOut(self, t):
- x = t * t
- return (3 * x) - (2 * t * x)
- def setPreRecordFunc(self, func):
- # Note: If func is one defined at command prompt, need to set
- # __builtins__.func = func at command line
- self.preRecordFunc = eval(func)
- # Update widget to reflect new value
- self.getVariable('Recording', 'PRF Active').set(1)
- def recordPoint(self, time):
- # Call user define callback before recording point
- if (self.getVariable('Recording', 'PRF Active').get() and
- (self.preRecordFunc != None)):
- self.preRecordFunc()
- # Get point
- pos = self.nodePath.getPos(self.nodePathParent)
- hpr = self.nodePath.getHpr(self.nodePathParent)
- qNP = Quat()
- qNP.setHpr(hpr)
- # Blend between recordNodePath and self.nodePath
- if ((self.recordingType.get() == 'Refine') or
- (self.recordingType.get() == 'Extend')):
- if ((time < self.controlStart) and
- ((self.controlStart - self.recordStart) != 0.0)):
- rPos = self.playbackNodePath.getPos(self.nodePathParent)
- rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
- qR = Quat()
- qR.setHpr(rHpr)
- t = self.easeInOut(((time - self.recordStart)/
- (self.controlStart - self.recordStart)))
- # Transition between the recorded node path and the driven one
- pos = (rPos * (1 - t)) + (pos * t)
- q = qSlerp(qR, qNP, t)
- hpr.assign(q.getHpr())
- elif ((self.recordingType.get() == 'Refine') and
- (time > self.controlStop) and
- ((self.recordStop - self.controlStop) != 0.0)):
- rPos = self.playbackNodePath.getPos(self.nodePathParent)
- rHpr = self.playbackNodePath.getHpr(self.nodePathParent)
- qR = Quat()
- qR.setHpr(rHpr)
- t = self.easeInOut(((time - self.controlStop)/
- (self.recordStop - self.controlStop)))
- # Transition between the recorded node path and the driven one
- pos = (pos * (1 - t)) + (rPos * t)
- q = qSlerp(qNP, qR, t)
- hpr.assign(q.getHpr())
- # Add it to the point set
- self.pointSet.append([time, pos, hpr])
- # Add it to the curve fitters
- self.curveFitter.addXyzHpr(time, pos, hpr)
- # Update trace now if recording keyframes
- if (self.samplingMode == 'Keyframe'):
- self.trace.reset()
- for t, p, h in self.pointSet:
- self.trace.drawTo(p[0], p[1], p[2])
- self.trace.create()
- def computeCurves(self):
- # Check to make sure curve fitters have points
- if (self.curveFitter.getNumSamples() == 0):
- print 'MopathRecorder.computeCurves: Must define curve first'
- return
- # Create curves
- # XYZ
- 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
- self.updateWidgets()
- def initTrace(self):
- self.trace.reset()
- # Put trace line segs under node path's parent
- self.trace.reparentTo(self.nodePathParent)
- # Show it
- self.trace.show()
- def updateWidgets(self):
- if not self.curveCollection:
- return
- self.fAdjustingValues = 1
- # Widgets depending on max T
- maxT = self.curveCollection.getMaxT()
- maxT_text = '%0.2f' % maxT
- # Playback controls
- self.getWidget('Playback', 'Time').configure(max = maxT_text)
- self.getVariable('Resample', 'Path Duration').set(maxT_text)
- # Refine widgets
- widget = self.getWidget('Refine Page', 'Refine From')
- widget.configure(max = maxT)
- widget.set(0.0)
- widget = self.getWidget('Refine Page', 'Control Start')
- widget.configure(max = maxT)
- widget.set(0.0)
- widget = self.getWidget('Refine Page', 'Control Stop')
- widget.configure(max = maxT)
- widget.set(float(maxT))
- widget = self.getWidget('Refine Page', 'Refine To')
- widget.configure(max = maxT)
- widget.set(float(maxT))
- # Extend widgets
- widget = self.getWidget('Extend Page', 'Extend From')
- widget.configure(max = maxT)
- widget.set(float(0.0))
- widget = self.getWidget('Extend Page', 'Control Start')
- widget.configure(max = maxT)
- widget.set(float(0.0))
- # Crop widgets
- 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.curveFitter.getNumSamples()
- widget = self.getWidget('Resample', 'Points Between Samples')
- widget.configure(max=numSamples)
- widget = self.getWidget('Resample', 'Num. Samples')
- widget.configure(max = 4 * numSamples)
- widget.set(numSamples, 0)
- self.fAdjustingValues = 0
- def selectNodePathNamed(self, name):
- nodePath = None
- if name == 'init':
- nodePath = self.nodePath
- # Add Combo box entry for the initial node path
- self.addNodePath(nodePath)
- elif name == 'selected':
- nodePath = SEditor.selected.last
- # Add Combo box entry for this selected object
- self.addNodePath(nodePath)
- else:
- nodePath = self.nodePathDict.get(name, None)
- if (nodePath == None):
- # See if this evaluates into a node path
- try:
- nodePath = eval(name)
- if isinstance(nodePath, NodePath):
- self.addNodePath(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.nodePathMenu.component('scrolledlist')
- listbox.setlist(self.nodePathNames)
- else:
- if name == 'widget':
- # Record relationship between selected nodes and widget
- SEditor.selected.getWrtAll()
- if name == 'marker':
- self.playbackMarker.show()
- # Initialize tangent marker position
- tan = Point3(0)
- if self.curveCollection != None:
- self.curveCollection.getXyzCurve().getTangent(
- self.playbackTime, tan)
- self.tangentMarker.setPos(tan)
- else:
- self.playbackMarker.hide()
- # Update active node path
- self.setNodePath(nodePath)
- messenger.send('mPath_requestCurveList',[nodePath,self.name])
- self.accept('curveListFor'+self.name, self.addCurvesFromNodepath)
- 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):
- self.playbackNodePath = nodePath
- def addNodePath(self, nodePath):
- self.addNodePathToDict(nodePath, self.nodePathNames,
- self.nodePathMenu, self.nodePathDict)
- def addNodePathToDict(self, nodePath, names, menu, dict):
- if not nodePath:
- return
- # Get node path's name
- name = nodePath.getName()
- if name in ['mopathRecorderTempCS', 'widget', 'camera', 'marker']:
- dictName = name
- else:
- # Generate a unique name for the dict
- dictName = name # + '-' + `nodePath.id()`
- if not dict.has_key(dictName):
- # Update combo box to include new item
- names.append(dictName)
- listbox = menu.component('scrolledlist')
- listbox.setlist(names)
- # Add new item to dictionary
- dict[dictName] = nodePath
- menu.selectitem(dictName)
- def setLoopPlayback(self):
- self.loopPlayback = self.getVariable('Playback', 'Loop').get()
- def playbackGoTo(self, time):
- if self.curveCollection == None:
- return
- self.playbackTime = CLAMP(time, 0.0, self.maxT)
- if self.curveCollection != None:
- pos = Point3(0)
- hpr = Point3(0)
- self.curveCollection.evaluate(self.playbackTime, pos, hpr)
- self.playbackNodePath.setPosHpr(self.nodePathParent, pos, hpr)
- def startPlayback(self):
- if self.curveCollection == None:
- return
- # Kill any existing tasks
- self.stopPlayback()
- # Make sure checkbutton is set
- self.getVariable('Playback', 'Play').set(1)
- # Start new playback task
- t = taskMgr.add(
- self.playbackTask, self.name + '-playbackTask')
- t.currentTime = self.playbackTime
- t.lastTime = globalClock.getFrameTime()
- def setSpeedScale(self, value):
- self.speedScale.set(math.log10(value))
- def setPlaybackSF(self, value):
- self.playbackSF = pow(10.0, float(value))
- self.speedVar.set('%0.2f' % self.playbackSF)
-
- def playbackTask(self, state):
- time = globalClock.getFrameTime()
- dTime = self.playbackSF * (time - state.lastTime)
- state.lastTime = time
- if self.loopPlayback:
- cTime = (state.currentTime + dTime) % self.maxT
- else:
- cTime = state.currentTime + dTime
- # Stop task if not looping and at end of curve
- # Or if refining curve and past recordStop
- if ((self.recordingType.get() == 'Refine') and
- (cTime > self.recordStop)):
- # Go to recordStop
- self.getWidget('Playback', 'Time').set(self.recordStop)
- # Then stop playback
- self.stopPlayback()
- # Also kill record task
- self.toggleRecordVar()
- return Task.done
- elif ((self.loopPlayback == 0) and (cTime > self.maxT)):
- # Go to maxT
- self.getWidget('Playback', 'Time').set(self.maxT)
- # Then stop playback
- self.stopPlayback()
- 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
- self.getWidget('Playback', 'Time').set(cTime)
- state.currentTime = cTime
- return Task.cont
- def stopPlayback(self):
- self.getVariable('Playback', 'Play').set(0)
- taskMgr.remove(self.name + '-playbackTask')
- def jumpToStartOfPlayback(self):
- self.stopPlayback()
- self.getWidget('Playback', 'Time').set(0.0)
- def jumpToEndOfPlayback(self):
- self.stopPlayback()
- if self.curveCollection != None:
- self.getWidget('Playback', 'Time').set(self.maxT)
- def startStopPlayback(self):
- if self.getVariable('Playback', 'Play').get():
- self.startPlayback()
- else:
- self.stopPlayback()
- def setDesampleFrequency(self, frequency):
- self.desampleFrequency = frequency
-
- def desampleCurve(self):
- if (self.curveFitter.getNumSamples() == 0):
- print 'MopathRecorder.desampleCurve: Must define curve first'
- return
- # NOTE: This is destructive, points will be deleted from curve fitter
- self.curveFitter.desample(self.desampleFrequency)
- # Compute new curve based on desampled data
- self.computeCurves()
- # Get point set from the curve fitter
- self.extractPointSetFromCurveFitter()
- def setNumSamples(self, numSamples):
- self.numSamples = int(numSamples)
-
- def sampleCurve(self, fCompute = 1, curveName = None):
- if self.curveCollection == None:
- print 'MopathRecorder.sampleCurve: Must define curve first'
- return
- # Reset curve fitters
- self.curveFitter.reset()
- # Sample curve using specified number of samples
- self.curveFitter.sample(self.curveCollection, self.numSamples)
- if fCompute:
- # Now recompute curves
- self.computeCurves()
- # Get point set from the curve fitter
- self.extractPointSetFromCurveFitter(curveName)
- def makeEven(self):
- # 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 faceForward(self):
- # 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):
- newMaxT = float(self.getWidget('Resample', 'Path Duration').get())
- self.setPathDurationTo(newMaxT)
-
- def setPathDurationTo(self, newMaxT):
- # Compute scale factor
- sf = newMaxT/self.maxT
- # Scale curve collection
- self.curveCollection.resetMaxT(newMaxT)
- # Scale point set
- # Save handle to old point set
- oldPointSet = self.pointSet
- # Create new point set
- self.createNewPointSet()
- # Reset curve fitters
- self.curveFitter.reset()
- # Now scale values
- for time, pos, hpr in oldPointSet:
- newTime = time * sf
- # Update point set
- self.pointSet.append([newTime, Point3(pos), Point3(hpr)])
- # Add it to the curve fitters
- self.curveFitter.addXyzHpr(newTime, pos, hpr)
- # Update widgets
- self.updateWidgets()
- # Compute curve
- #self.computeCurves()
- def setRecordStart(self,value):
- self.recordStart = value
- # Someone else is adjusting values, let them take care of it
- if self.fAdjustingValues:
- return
- self.fAdjustingValues = 1
- # Adjust refine widgets
- # Make sure we're in sync
- self.getWidget('Refine Page', 'Refine From').set(
- self.recordStart)
- self.getWidget('Extend Page', 'Extend From').set(
- self.recordStart)
- # Check bounds
- if self.recordStart > self.controlStart:
- self.getWidget('Refine Page', 'Control Start').set(
- self.recordStart)
- self.getWidget('Extend Page', 'Control Start').set(
- self.recordStart)
- if self.recordStart > self.controlStop:
- self.getWidget('Refine Page', 'Control Stop').set(
- self.recordStart)
- if self.recordStart > self.recordStop:
- self.getWidget('Refine Page', 'Refine To').set(self.recordStart)
- # Move playback node path to specified time
- self.getWidget('Playback', 'Time').set(value)
- self.fAdjustingValues = 0
- def getPrePoints(self, type = 'Refine'):
- # Switch to appropriate recording type
- self.setRecordingType(type)
- # Reset prePoints
- self.prePoints = []
- # See if we need to save any points before recordStart
- for i in range(len(self.pointSet)):
- # Have we passed recordStart?
- if self.recordStart < self.pointSet[i][0]:
- # Get a copy of the points prior to recordStart
- self.prePoints = self.pointSet[:i-1]
- break
- def setControlStart(self, value):
- self.controlStart = value
- # Someone else is adjusting values, let them take care of it
- if self.fAdjustingValues:
- return
- self.fAdjustingValues = 1
- # Adjust refine widgets
- # Make sure both pages are in sync
- self.getWidget('Refine Page', 'Control Start').set(
- self.controlStart)
- self.getWidget('Extend Page', 'Control Start').set(
- self.controlStart)
- # Check bounds on other widgets
- if self.controlStart < self.recordStart:
- self.getWidget('Refine Page', 'Refine From').set(
- self.controlStart)
- self.getWidget('Extend Page', 'Extend From').set(
- self.controlStart)
- if self.controlStart > self.controlStop:
- self.getWidget('Refine Page', 'Control Stop').set(
- self.controlStart)
- if self.controlStart > self.recordStop:
- 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):
- self.controlStop = value
- # Someone else is adjusting values, let them take care of it
- if self.fAdjustingValues:
- return
- self.fAdjustingValues = 1
- if self.controlStop < self.recordStart:
- self.getWidget('Refine Page', 'Refine From').set(
- self.controlStop)
- if self.controlStop < self.controlStart:
- self.getWidget('Refine Page', 'Control Start').set(
- self.controlStop)
- if self.controlStop > self.recordStop:
- 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):
- self.recordStop = value
- # Someone else is adjusting values, let them take care of it
- if self.fAdjustingValues:
- return
- self.fAdjustingValues = 1
- if self.recordStop < self.recordStart:
- self.getWidget('Refine Page', 'Refine From').set(
- self.recordStop)
- if self.recordStop < self.controlStart:
- self.getWidget('Refine Page', 'Control Start').set(
- self.recordStop)
- if self.recordStop < self.controlStop:
- self.getWidget('Refine Page', 'Control Stop').set(
- self.recordStop)
- # Move playback node path to specified time
- self.getWidget('Playback', 'Time').set(value)
- self.fAdjustingValues = 0
- def getPostPoints(self):
- # Set flag so we know to do a refine pass
- self.setRefineMode()
- # Reset postPoints
- self.postPoints = []
- # See if we need to save any points after recordStop
- for i in range(len(self.pointSet)):
- # Have we reached recordStop?
- if self.recordStop < self.pointSet[i][0]:
- # Get a copy of the points after recordStop
- self.postPoints = self.pointSet[i:]
- break
- def mergePoints(self):
- # prepend pre points
- self.pointSet[0:0] = self.prePoints
- for time, pos, hpr in self.prePoints:
- # Add it to the curve fitters
- self.curveFitter.addXyzHpr(time, pos, hpr)
- # And post points
- # What is end time of pointSet?
- endTime = self.pointSet[-1][0]
- for time, pos, hpr in self.postPoints:
- adjustedTime = endTime + (time - self.recordStop)
- # Add it to point set
- self.pointSet.append([adjustedTime, pos, hpr])
- # Add it to the curve fitters
- self.curveFitter.addXyzHpr(adjustedTime, pos, 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):
- if self.pointSet == None:
- print 'Empty Point Set'
- return
- # Keep handle on old points
- oldPoints = self.pointSet
- # Create new point set
- self.createNewPointSet()
- # Copy over points between from/to
- # Reset curve fitters
- self.curveFitter.reset()
- # Add start point
- pos = Point3(0)
- hpr = Point3(0)
- self.curveCollection.evaluate(self.cropFrom, pos, hpr)
- self.curveFitter.addXyzHpr(0.0, pos, hpr)
- # Get points within bounds
- for time, pos, hpr in oldPoints:
- # Is it within the time?
- if ((time > self.cropFrom) and
- (time < self.cropTo)):
- # Add it to the curve fitters
- t = time - self.cropFrom
- self.curveFitter.addXyzHpr(t, pos, hpr)
- # And the point set
- self.pointSet.append([t, pos, hpr])
- # Add last point
- pos = Vec3(0)
- hpr = Vec3(0)
- self.curveCollection.evaluate(self.cropTo, pos, hpr)
- self.curveFitter.addXyzHpr(self.cropTo - self.cropFrom, pos, hpr)
- # Compute curve
- self.computeCurves()
- def loadCurveFromFile(self):
- # Use first directory in model path
- mPath = getModelPath()
- if mPath.getNumDirectories() > 0:
- if `mPath.getDirectory(0)` == '.':
- path = '.'
- else:
- path = mPath.getDirectory(0).toOsSpecific()
- else:
- path = '.'
- if not os.path.isdir(path):
- print 'MopathRecorder Info: Empty Model Path!'
- print 'Using current directory'
- path = '.'
- mopathFilename = askopenfilename(
- defaultextension = '.egg',
- filetypes = (('Egg Files', '*.egg'),
- ('Bam Files', '*.bam'),
- ('All files', '*')),
- initialdir = path,
- title = 'Load Nurbs Curve',
- parent = self.parent)
- if mopathFilename:
- self.reset()
- nodePath = loader.loadModel(
- Filename.fromOsSpecific(mopathFilename))
- self.curveCollection = ParametricCurveCollection()
- # MRM: Add error check
- self.curveCollection.addCurves(nodePath.node())
- nodePath.removeNode()
- if self.curveCollection:
- # Draw the curve
- self.nurbsCurveDrawer.setCurves(self.curveCollection)
- self.nurbsCurveDrawer.draw()
- # Save a pointset for this curve
- self.extractPointSetFromCurveCollection()
- else:
- self.reset()
- def saveCurveToFile(self):
- # Use first directory in model path
- mPath = getModelPath()
- if mPath.getNumDirectories() > 0:
- if `mPath.getDirectory(0)` == '.':
- path = '.'
- else:
- path = mPath.getDirectory(0).toOsSpecific()
- else:
- path = '.'
- if not os.path.isdir(path):
- print 'MopathRecorder Info: Empty Model Path!'
- print 'Using current directory'
- path = '.'
- mopathFilename = asksaveasfilename(
- defaultextension = '.egg',
- filetypes = (('Egg Files', '*.egg'),
- ('Bam Files', '*.bam'),
- ('All files', '*')),
- initialdir = path,
- title = 'Save Nurbs Curve as',
- parent = self.parent)
- if mopathFilename:
- self.curveCollection.writeEgg(Filename(mopathFilename))
- def followTerrain(self, height = 1.0):
- self.iRay.rayCollisionNodePath.reparentTo(self.nodePath)
- entry = self.iRay.pickGeom3D()
- if entry:
- fromNodePath = entry.getFromNodePath()
- hitPtDist = Vec3(entry.getSurfacePoint(fromNodePath))
- self.nodePath.setZ(self.nodePath, height - hitPtDist)
- self.iRay.rayCollisionNodePath.reparentTo(self.recorderNodePath)
- ## WIDGET UTILITY FUNCTIONS ##
- def addWidget(self, widget, category, text):
- self.widgetDict[category + '-' + text] = widget
-
- def getWidget(self, category, text):
- return self.widgetDict[category + '-' + text]
- def getVariable(self, category, text):
- return self.variableDict[category + '-' + text]
- def createLabeledEntry(self, parent, category, text, balloonHelp,
- value = '', command = None,
- relief = 'sunken', side = LEFT,
- expand = 1, width = 12):
- frame = Frame(parent)
- variable = StringVar()
- variable.set(value)
- label = Label(frame, text = text)
- label.pack(side = LEFT, fill = X)
- self.bind(label, balloonHelp)
- self.widgetDict[category + '-' + text + '-Label'] = label
- entry = Entry(frame, width = width, relief = relief,
- textvariable = variable)
- entry.pack(side = LEFT, fill = X, expand = expand)
- self.bind(entry, balloonHelp)
- self.widgetDict[category + '-' + text] = entry
- self.variableDict[category + '-' + text] = variable
- if command:
- entry.bind('<Return>', command)
- frame.pack(side = side, fill = X, expand = expand)
- return (frame, label, entry)
- def createButton(self, parent, category, text, balloonHelp, command,
- 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 = fill, expand = expand)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
-
- def createCheckbutton(self, parent, category, text,
- balloonHelp, command, initialState,
- side = 'top', fill = X, expand = 0):
- bool = BooleanVar()
- bool.set(initialState)
- widget = Checkbutton(parent, text = text, anchor = W,
- variable = bool)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(side = side, fill = fill, expand = expand)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- self.variableDict[category + '-' + text] = bool
- return widget
-
- def createRadiobutton(self, parent, side, category, text,
- balloonHelp, variable, value,
- command = None, fill = X, expand = 0):
- widget = Radiobutton(parent, text = text, anchor = W,
- variable = variable, value = value)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(side = side, fill = fill, expand = expand)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
-
- def createFloater(self, parent, category, text, balloonHelp,
- command = None, min = 0.0, resolution = None,
- maxVelocity = 10.0, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['maxVelocity'] = maxVelocity
- kw['resolution'] = resolution
- widget = apply(Floater.Floater, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createAngleDial(self, parent, category, text, balloonHelp,
- command = None, **kw):
- kw['text'] = text
- widget = apply(Dial.AngleDial,(parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createSlider(self, parent, category, text, balloonHelp,
- command = None, min = 0.0, max = 1.0,
- resolution = None,
- side = TOP, fill = X, expand = 1, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['max'] = max
- kw['resolution'] = resolution
- #widget = apply(EntryScale.EntryScale, (parent,), kw)
- from direct.tkwidgets import Slider
- widget = apply(Slider.Slider, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(side = side, fill = fill, expand = expand)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createEntryScale(self, parent, category, text, balloonHelp,
- command = None, min = 0.0, max = 1.0,
- resolution = None,
- side = TOP, fill = X, expand = 1, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['max'] = max
- kw['resolution'] = resolution
- widget = apply(EntryScale.EntryScale, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(side = side, fill = fill, expand = expand)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createVector2Entry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = apply(VectorWidgets.Vector2Entry, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createVector3Entry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = apply(VectorWidgets.Vector3Entry, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createColorEntry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = apply(VectorWidgets.ColorEntry, (parent,) ,kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createOptionMenu(self, parent, category, text, balloonHelp,
- items, command):
- optionVar = StringVar()
- if len(items) > 0:
- optionVar.set(items[0])
- widget = Pmw.OptionMenu(parent, labelpos = W, label_text = text,
- label_width = 12, menu_tearoff = 1,
- menubutton_textvariable = optionVar,
- items = items)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = X)
- self.bind(widget.component('menubutton'), balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- self.variableDict[category + '-' + text] = optionVar
- return optionVar
- def createComboBox(self, parent, category, text, balloonHelp,
- items, command, history = 0,
- side = LEFT, expand = 0, fill = X):
- widget = Pmw.ComboBox(parent,
- labelpos = W,
- label_text = text,
- label_anchor = 'e',
- label_width = 12,
- entry_width = 16,
- history = history,
- scrolledlist_items = items)
- # Don't allow user to edit entryfield
- widget.configure(entryfield_entry_state = 'disabled')
- # Select first item if it exists
- if len(items) > 0:
- widget.selectitem(items[0])
- # Bind selection command
- widget['selectioncommand'] = command
- widget.pack(side = side, fill = fill, expand = expand)
- # Bind help
- self.bind(widget, balloonHelp)
- # Record widget
- self.widgetDict[category + '-' + text] = widget
- return widget
- def makeCameraWindow(self):
- # First, we need to make a new layer on the window.
- chan = base.win.getChannel(0)
- self.cLayer = chan.makeLayer(1)
- self.layerIndex = 1
- self.cDr = self.cLayer.makeDisplayRegion(0.6, 1.0, 0, 0.4)
- self.cDr.setClearDepthActive(1)
- self.cDr.setClearColorActive(1)
- self.cDr.setClearColor(Vec4(0))
- # It gets its own camera
- self.cCamera = render.attachNewNode('cCamera')
- self.cCamNode = Camera('cCam')
- self.cLens = PerspectiveLens()
- self.cLens.setFov(40,40)
- self.cLens.setNear(0.1)
- self.cLens.setFar(100.0)
- self.cCamNode.setLens(self.cLens)
- self.cCamNode.setScene(render)
- self.cCam = self.cCamera.attachNewNode(self.cCamNode)
-
- self.cDr.setCamera(self.cCam)
- def toggleWidgetVis(self):
- ## In order to make sure everything is going on right way...
- messenger.send('SEditor-ToggleWidgetVis')
- SEditor.toggleWidgetVis()
- def bindMotionPathToNode(self):
- if self.curveCollection == None:
- print '----Error: you need to select or create a curve first!'
- return
- self.accept('MP_checkName', self.bindMotionPath)
- self.askName = namePathPanel(MopathRecorder.count)
- return
- def bindMotionPath(self,name=None,test=None):
- print test
- self.ignore('MP_checkName')
- del self.askName
- self.curveCollection.getCurve(0).setName(name)
- comboBox = self.getWidget('Mopath', 'Path:')
- oldName = comboBox.get()
- self.pointSetDict[name] = self.pointSetDict[oldName]
- del self.pointSetDict[oldName]
- scrolledList = comboBox.component('scrolledlist')
- listbox = scrolledList.component('listbox')
- names = list(listbox.get(0,'end'))
- num = names.index(oldName)
- names.pop(num)
- names.append(name)
- scrolledList.setlist(names)
- comboBox.selectitem(name)
- messenger.send('mPath_bindPathToNode',[self.playbackNodePath, self.curveCollection])
- return
-
-
- def addCurvesFromNodepath(self,curveList):
- '''addCurvesFromNodepath(self,curveList)
- This function will take a curveCollection list as a input.
- If the list is not None, it will put the vurve back into the curve list.
- else, do nothing.
- '''
- print curveList
- self.ignore('curveListFor'+self.name)
- if curveList != None:
- for collection in curveList:
- self.curveCollection = collection
- self.extractPointSetFromCurveCollection(curveName=self.curveCollection.getCurve(0).getName())
- else:
- pass
- return
- class namePathPanel(AppShell):
- # Override class variables
- appname = 'Name the Path'
- frameWidth = 575
- frameHeight = 200
- usecommandarea = 0
- usestatusarea = 0
- index = 0
- def __init__(self, count, parent = None, **kw):
- INITOPT = Pmw.INITOPT
- self.id = 'Name the Path'
- self.appname = self.id
- optiondefs = (
- ('title', self.appname, None),
- )
- self.defineoptions(kw, optiondefs)
- # Initialize the superclass
- AppShell.__init__(self)
- self.parent.resizable(False,False)
- # Execute option callbacks
- self.initialiseoptions(namePathPanel)
- def createInterface(self):
- self.menuBar.destroy()
- interior = self.interior()
- mainFrame = Frame(interior)
- dataFrame = Frame(mainFrame)
- label = Label(dataFrame, text='This name will be used as a reference for this Path.',font=('MSSansSerif', 10))
- label.pack(side = TOP, expand = 0, fill = X)
- dataFrame.pack(side = TOP, expand = 0, fill = X, padx=5, pady=10)
-
- dataFrame = Frame(mainFrame)
- self.inputZone = Pmw.EntryField(dataFrame, labelpos='w', label_text = 'Name Selected Path: ',
- entry_font=('MSSansSerif', 10),
- label_font=('MSSansSerif', 10),
- validate = None,
- entry_width = 20)
- self.inputZone.pack(side = LEFT, fill=X,expand=0)
- self.button_ok = Button(dataFrame, text="OK", command=self.ok_press,width=10)
- self.button_ok.pack(fill=X,expand=0,side=LEFT, padx = 3)
- dataFrame.pack(side = TOP, expand = 0, fill = X, padx=10, pady=10)
- mainFrame.pack(expand = 1, fill = BOTH)
-
-
- def onDestroy(self, event):
- '''
- If you have open any thing, please rewrite here!
- '''
- pass
-
- def ok_press(self):
- name = self.inputZone.getvalue()
- messenger.send('MP_checkName',[name])
- self.quit()
- return
|