| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073 |
- #################################################################
- # 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.
- #
- #################################################################
- from direct.showbase.DirectObject import DirectObject
- from direct.tkwidgets.AppShell import AppShell
- #from direct.directtools.DirectGlobals import *
- #from direct.directtools.DirectUtil import *
- from seGeometry import *
- from seSelection import *
- from direct.task.Task import Task
- from direct.tkwidgets.Dial import AngleDial
- from direct.tkwidgets.Floater import Floater
- from direct.tkwidgets.Slider import Slider
- from direct.tkwidgets.EntryScale import EntryScale
- from direct.tkwidgets.VectorWidgets import Vector2Entry, Vector3Entry
- from direct.tkwidgets.VectorWidgets import ColorEntry
- from Tkinter import Button, Frame, Radiobutton, Checkbutton, Label
- from Tkinter import StringVar, BooleanVar, Entry, Scale
- import os, string, Tkinter, Pmw
- 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 = Tkinter.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 = Tkinter.LEFT, expand = 0)
- self.bind(self.redoButton, 'Redo last operation')
- # Record button
- mainFrame = Frame(interior, relief = Tkinter.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 = Tkinter.LEFT, expand = 0)
- widget['relief'] = Tkinter.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 = Tkinter.LEFT, fill = Tkinter.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 = Tkinter.X, expand = 1)
- frame = Frame(mainFrame)
- widget = self.createCheckbutton(
- frame, 'Recording', 'Record',
- 'On: path is being recorded', self.toggleRecord, 0,
- side = Tkinter.LEFT, fill = Tkinter.BOTH, expand = 1)
- widget.configure(foreground = 'Red', relief = Tkinter.RAISED, borderwidth = 2,
- anchor = Tkinter.CENTER, width = 16)
- widget = self.createButton(frame, 'Recording', 'Add Keyframe',
- 'Add Keyframe To Current Path',
- self.addKeyframe,
- side = Tkinter.LEFT, expand = 1)
- widget = self.createButton(frame, 'Recording', 'Bind Path to Node',
- 'Bind Motion Path to selected Object',
- self.bindMotionPathToNode,
- side = Tkinter.LEFT, expand = 1)
- frame.pack(fill = Tkinter.X, expand = 1)
-
- mainFrame.pack(expand = 1, fill = Tkinter.X, pady = 3)
-
- # Playback controls
- playbackFrame = Frame(interior, relief = Tkinter.SUNKEN,
- borderwidth = 2)
- Label(playbackFrame, text = 'PLAYBACK CONTROLS',
- font=('MSSansSerif', 12, 'bold')).pack(fill = Tkinter.X)
- # Main playback control slider
- widget = self.createEntryScale(
- playbackFrame, 'Playback', 'Time', 'Set current playback time',
- resolution = 0.01, command = self.playbackGoTo, side = Tkinter.TOP)
- widget.component('hull')['relief'] = Tkinter.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 = Tkinter.LEFT, expand = 0)
- # Start stop buttons
- frame = Frame(playbackFrame)
- widget = self.createButton(frame, 'Playback', '<<',
- 'Jump to start of playback',
- self.jumpToStartOfPlayback,
- side = Tkinter.LEFT, expand = 1)
- widget['font'] = (('MSSansSerif', 12, 'bold'))
- widget = self.createCheckbutton(frame, 'Playback', 'Play',
- 'Start/Stop playback',
- self.startStopPlayback, 0,
- side = Tkinter.LEFT, fill = Tkinter.BOTH, expand = 1)
- widget.configure(anchor = 'center', justify = 'center',
- relief = Tkinter.RAISED, font = ('MSSansSerif', 12, 'bold'))
- widget = self.createButton(frame, 'Playback', '>>',
- 'Jump to end of playback',
- self.jumpToEndOfPlayback,
- side = Tkinter.LEFT, expand = 1)
- widget['font'] = (('MSSansSerif', 12, 'bold'))
- self.createCheckbutton(frame, 'Playback', 'Loop',
- 'On: loop playback',
- self.setLoopPlayback, self.loopPlayback,
- side = Tkinter.LEFT, fill = Tkinter.BOTH, expand = 0)
- frame.pack(fill = Tkinter.X, expand = 1)
- # Speed control
- frame = Frame(playbackFrame)
- widget = Button(frame, text = 'PB Speed Vernier', relief = Tkinter.FLAT,
- command = lambda s = self: s.setSpeedScale(1.0))
- widget.pack(side = Tkinter.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 = Tkinter.LEFT, fill = Tkinter.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 = Tkinter.LEFT, expand = 0)
- frame.pack(fill = Tkinter.X, expand = 1)
-
- playbackFrame.pack(fill = Tkinter.X, pady = 2)
- # Create notebook pages
- self.mainNotebook = Pmw.NoteBook(interior)
- self.mainNotebook.pack(fill = Tkinter.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 = Tkinter.X)
-
- # Resample
- resampleFrame = Frame(
- self.resamplePage, relief = Tkinter.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'] = Tkinter.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 = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- self.createButton(
- frame, 'Resample', 'Face Forward',
- 'Compute HPR so resulting hpr curve faces along xyz tangent',
- self.faceForward, side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- frame.pack(fill = Tkinter.X, expand = 0)
- resampleFrame.pack(fill = Tkinter.X, expand = 0, pady = 2)
-
- # Desample
- desampleFrame = Frame(
- self.resamplePage, relief = Tkinter.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'] = Tkinter.RIDGE
- widget['postCallback'] = self.desampleCurve
- desampleFrame.pack(fill = Tkinter.X, expand = 0, pady = 2)
- ## REFINE PAGE ##
- refineFrame = Frame(self.refinePage, relief = Tkinter.SUNKEN,
- borderwidth = 2)
- label = Label(refineFrame, text = 'REFINE CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = Tkinter.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 = Tkinter.X)
- ## EXTEND PAGE ##
- extendFrame = Frame(self.extendPage, relief = Tkinter.SUNKEN,
- borderwidth = 2)
- label = Label(extendFrame, text = 'EXTEND CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = Tkinter.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 = Tkinter.X)
- ## CROP PAGE ##
- cropFrame = Frame(self.cropPage, relief = Tkinter.SUNKEN,
- borderwidth = 2)
- label = Label(cropFrame, text = 'CROP CURVE',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = Tkinter.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 = Tkinter.NONE)
- cropFrame.pack(fill = Tkinter.X)
- ## DRAW PAGE ##
- drawFrame = Frame(self.drawPage, relief = Tkinter.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 = Tkinter.X)
- frame = Frame(sfFrame)
- Label(frame, text = 'SHOW:').pack(side = Tkinter.LEFT, expand = 0)
- widget = self.createCheckbutton(
- frame, 'Style', 'Path',
- 'On: path is visible', self.setPathVis, 1,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Knots',
- 'On: path knots are visible', self.setKnotVis, 1,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'CVs',
- 'On: path CVs are visible', self.setCvVis, 0,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Hull',
- 'On: path hull is visible', self.setHullVis, 0,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Trace',
- 'On: record is visible', self.setTraceVis, 0,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- widget = self.createCheckbutton(
- frame, 'Style', 'Marker',
- 'On: playback marker is visible', self.setMarkerVis, 0,
- side = Tkinter.LEFT, fill = Tkinter.X, expand = 1)
- frame.pack(fill = Tkinter.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 = Tkinter.TOP)
- widget.component('hull')['relief'] = Tkinter.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 = Tkinter.TOP)
- widget.component('hull')['relief'] = Tkinter.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 = Tkinter.TOP)
- widget.component('hull')['relief'] = Tkinter.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 = Tkinter.X)
- ## OPTIONS PAGE ##
- optionsFrame = Frame(self.optionsPage, relief = Tkinter.SUNKEN,
- borderwidth = 2)
- label = Label(optionsFrame, text = 'RECORDING OPTIONS',
- font=('MSSansSerif', 12, 'bold'))
- label.pack(fill = Tkinter.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 = Tkinter.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 = Tkinter.W)
- self.setKeyframeHook()
- frame.pack(expand = 1, fill = Tkinter.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 = Tkinter.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 = Tkinter.LEFT, fill = Tkinter.BOTH, expand = 0)
- frame.pack(expand = 1, fill = Tkinter.X)
- # Pack record frame
- optionsFrame.pack(fill = Tkinter.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.getChildren()
- 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 = Tkinter.LEFT,
- expand = 1, width = 12):
- frame = Frame(parent)
- variable = StringVar()
- variable.set(value)
- label = Label(frame, text = text)
- label.pack(side = Tkinter.LEFT, fill = Tkinter.X)
- self.bind(label, balloonHelp)
- self.widgetDict[category + '-' + text + '-Label'] = label
- entry = Entry(frame, width = width, relief = relief,
- textvariable = variable)
- entry.pack(side = Tkinter.LEFT, fill = Tkinter.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 = Tkinter.X, expand = expand)
- return (frame, label, entry)
- def createButton(self, parent, category, text, balloonHelp, command,
- side = 'top', expand = 0, fill = Tkinter.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 = Tkinter.X, expand = 0):
- bool = BooleanVar()
- bool.set(initialState)
- widget = Checkbutton(parent, text = text, anchor = Tkinter.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 = Tkinter.X, expand = 0):
- widget = Radiobutton(parent, text = text, anchor = Tkinter.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, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = Tkinter.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(AngleDial,(parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = Tkinter.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 = Tkinter.TOP, fill = Tkinter.X, expand = 1, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['max'] = max
- kw['resolution'] = resolution
- #widget = apply(EntryScale, (parent,), kw)
- widget = apply(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 = Tkinter.TOP, fill = Tkinter.X, expand = 1, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['max'] = max
- kw['resolution'] = resolution
- widget = apply(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(Vector2Entry, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = Tkinter.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(Vector3Entry, (parent,), kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = Tkinter.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(ColorEntry, (parent,) ,kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = Tkinter.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 = Tkinter.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 = Tkinter.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 = Tkinter.LEFT, expand = 0, fill = Tkinter.X):
- widget = Pmw.ComboBox(parent,
- labelpos = Tkinter.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 = Tkinter.TOP, expand = 0, fill = Tkinter.X)
- dataFrame.pack(side = Tkinter.TOP, expand = 0, fill = Tkinter.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 = Tkinter.LEFT, fill=Tkinter.X,expand=0)
- self.button_ok = Button(dataFrame, text="OK", command=self.ok_press,width=10)
- self.button_ok.pack(fill=Tkinter.X,expand=0,side=Tkinter.LEFT, padx = 3)
- dataFrame.pack(side = Tkinter.TOP, expand = 0, fill = Tkinter.X, padx=10, pady=10)
- mainFrame.pack(expand = 1, fill = Tkinter.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
|