| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991 |
- #################################################################
- # seSession.py
- # Originally from DirectSession.py
- # Altered by Yi-Hong Lin, [email protected], 2004
- #
- # We took out a lot of stuff we don't need in the sceneeditor.
- # This is also the main reason we didn't just inherite the original directSession.
- # Also, the way of selecting, renaming and some hot-key controls are changed.
- #
- #################################################################
- from direct.showbase.DirectObject import *
- from direct.directtools.DirectGlobals import *
- from direct.directtools.DirectUtil import*
- from direct.interval.IntervalGlobal import *
- from seCameraControl import *
- from seManipulation import *
- from seSelection import *
- from seGrid import *
- from seGeometry import *
- from direct.tkpanels import Placer
- from direct.tkwidgets import Slider
- from direct.gui import OnscreenText
- import types
- import string
- from direct.showbase import Loader
- class SeSession(DirectObject): ### Customized DirectSession
- def __init__(self):
- # Establish a global pointer to the direct object early on
- # so dependant classes can access it in their code
- __builtins__["SEditor"] = self
- # These come early since they are used later on
- self.group = render.attachNewNode('SEditor')
- self.font = TextNode.getDefaultFont()
- self.fEnabled = 0
- self.drList = DisplayRegionList()
- self.iRayList = map(lambda x: x.iRay, self.drList)
- self.dr = self.drList[0]
- self.camera = base.camera
- self.trueCamera = self.camera
- self.iRay = self.dr.iRay
- self.coaMode = COA_ORIGIN
- self.enableAutoCamera = True
- self.cameraControl = DirectCameraControl()
- self.manipulationControl = DirectManipulationControl()
- self.useObjectHandles()
- self.grid = DirectGrid()
- self.grid.disable()
-
- # Initialize the collection of selected nodePaths
- self.selected = SelectedNodePaths()
- # Ancestry of currently selected object
- self.ancestry = []
- self.ancestryIndex = 0
- self.activeParent = None
- self.selectedNPReadout = OnscreenText.OnscreenText(
- pos = (-1.0, -0.9), bg=Vec4(1,1,1,1),
- scale = 0.05, align = TextNode.ALeft,
- mayChange = 1, font = self.font)
- # Make sure readout is never lit or drawn in wireframe
- useDirectRenderStyle(self.selectedNPReadout)
- self.selectedNPReadout.reparentTo(hidden)
- self.activeParentReadout = OnscreenText.OnscreenText(
- pos = (-1.0, -0.975), bg=Vec4(1,1,1,1),
- scale = 0.05, align = TextNode.ALeft,
- mayChange = 1, font = self.font)
- # Make sure readout is never lit or drawn in wireframe
- useDirectRenderStyle(self.activeParentReadout)
- self.activeParentReadout.reparentTo(hidden)
- self.directMessageReadout = OnscreenText.OnscreenText(
- pos = (-1.0, 0.9), bg=Vec4(1,1,1,1),
- scale = 0.05, align = TextNode.ALeft,
- mayChange = 1, font = self.font)
- # Make sure readout is never lit or drawn in wireframe
- useDirectRenderStyle(self.directMessageReadout)
- self.directMessageReadout.reparentTo(hidden)
- self.fControl = 0
- self.fAlt = 0
- self.fShift = 0
- self.pos = VBase3()
- self.hpr = VBase3()
- self.scale = VBase3()
- self.hitPt = Point3(0.0)
- # Lists for managing undo/redo operations
- self.undoList = []
- self.redoList = []
-
- # One run through the context task to init everything
- self.drList.updateContext()
- for dr in self.drList:
- dr.camUpdate()
-
- self.modifierEvents = ['control', 'control-up',
- 'shift', 'shift-up',
- 'alt', 'alt-up',
- ]
- self.keyEvents = ['escape', 'delete', 'page_up', 'page_down',
- '[', '{', ']', '}',
- 'shift-a', 'b', 'control-f',
- 'l', 'shift-l', 'o', 'p', 'r',
- 'shift-r', 's', 't', 'v', 'w']
- self.mouseEvents = ['mouse1', 'mouse1-up',
- 'shift-mouse1', 'shift-mouse1-up',
- 'control-mouse1', 'control-mouse1-up',
- 'alt-mouse1', 'alt-mouse1-up',
- 'mouse2', 'mouse2-up',
- 'shift-mouse2', 'shift-mouse2-up',
- 'control-mouse2', 'control-mouse2-up',
- 'alt-mouse2', 'alt-mouse2-up',
- 'mouse3', 'mouse3-up',
- 'shift-mouse3', 'shift-mouse3-up',
- 'control-mouse3', 'control-mouse3-up',
- 'alt-mouse3', 'alt-mouse3-up',
- ]
-
- def enable(self):
- if self.fEnabled:
- return
- # Make sure old tasks are shut down
- self.disable()
- # Start all display region context tasks
- self.drList.spawnContextTask()
- # Turn on mouse Flying
- self.cameraControl.enableMouseFly()
- # Turn on object manipulation
- self.manipulationControl.enableManipulation()
- # Make sure list of selected items is reset
- self.selected.reset()
- # Accept appropriate hooks
- self.enableKeyEvents()
- self.enableModifierEvents()
- self.enableMouseEvents()
- # Set flag
- self.fEnabled = 1
- if self.enableAutoCamera:
- self.accept('DH_LoadingComplete', self.autoCameraMove)
- def disable(self):
- # Shut down all display region context tasks
- self.drList.removeContextTask()
- # Turn off camera fly
- self.cameraControl.disableMouseFly()
- # Turn off object manipulation
- self.manipulationControl.disableManipulation()
- self.disableKeyEvents()
- self.disableModifierEvents()
- self.disableMouseEvents()
- self.ignore('DH_LoadingComplete')
- # Kill tasks
- taskMgr.remove('flashNodePath')
- taskMgr.remove('hideDirectMessage')
- taskMgr.remove('hideDirectMessageLater')
- # Set flag
- self.fEnabled = 0
- def minimumConfiguration(self):
- # Remove context task
- self.drList.removeContextTask()
- # Turn off camera fly
- self.cameraControl.disableMouseFly()
- # Ignore keyboard and action events
- self.disableKeyEvents()
- self.disableActionEvents()
- # But let mouse events pass through
- self.enableMouseEvents()
- self.enableModifierEvents()
- def oobe(self):
- # If oobeMode was never set, set it to false and create the
- # structures we need to implement OOBE.
- try:
- self.oobeMode
- except:
- self.oobeMode = 0
- self.oobeCamera = hidden.attachNewNode('oobeCamera')
- self.oobeVis = loader.loadModelOnce('models/misc/camera')
- if self.oobeVis:
- self.oobeVis.node().setFinal(1)
- if self.oobeMode:
- # Position a target point to lerp the oobe camera to
- self.cameraControl.camManipRef.iPosHpr(self.trueCamera)
- t = self.oobeCamera.lerpPosHpr(
- Point3(0), Vec3(0), 2.0,
- other = self.cameraControl.camManipRef,
- task = 'manipulateCamera',
- blendType = 'easeInOut')
- # When move is done, switch to oobe mode
- t.uponDeath = self.endOOBE
- else:
- # Place camera marker at true camera location
- self.oobeVis.reparentTo(self.trueCamera)
- # Remove any transformation on the models arc
- self.oobeVis.clearMat()
- # Make oobeCamera be a sibling of wherever camera is now.
- cameraParent = self.camera.getParent()
- # Prepare oobe camera
- self.oobeCamera.reparentTo(cameraParent)
- self.oobeCamera.iPosHpr(self.trueCamera)
- # Put camera under new oobe camera
- base.cam.reparentTo(self.oobeCamera)
- # Position a target point to lerp the oobe camera to
- self.cameraControl.camManipRef.setPos(
- self.trueCamera, Vec3(-2,-20, 5))
- self.cameraControl.camManipRef.lookAt(self.trueCamera)
- t = self.oobeCamera.lerpPosHpr(
- Point3(0), Vec3(0), 2.0,
- other = self.cameraControl.camManipRef,
- task = 'manipulateCamera',
- blendType = 'easeInOut')
- # When move is done, switch to oobe mode
- t.uponDeath = self.beginOOBE
- def beginOOBE(self, state):
- # Make sure we've reached our final destination
- self.oobeCamera.iPosHpr(self.cameraControl.camManipRef)
- self.camera = self.oobeCamera
- self.oobeMode = 1
- def endOOBE(self, state):
- # Make sure we've reached our final destination
- self.oobeCamera.iPosHpr(self.trueCamera)
- # Disable OOBE mode.
- base.cam.reparentTo(self.trueCamera)
- self.camera = self.trueCamera
- # Get rid of ancillary node paths
- self.oobeVis.reparentTo(hidden)
- self.oobeCamera.reparentTo(hidden)
- self.oobeMode = 0
- def destroy(self):
- self.disable()
- def reset(self):
- self.enable()
- # EVENT FUNCTIONS
- def enableModifierEvents(self):
- for event in self.modifierEvents:
- self.accept(event, self.inputHandler, [event])
- def enableKeyEvents(self):
- for event in self.keyEvents:
- self.accept(event, self.inputHandler, [event])
- def enableMouseEvents(self):
- for event in self.mouseEvents:
- self.accept(event, self.inputHandler, [event])
- def disableModifierEvents(self):
- for event in self.modifierEvents:
- self.ignore(event)
- def disableKeyEvents(self):
- for event in self.keyEvents:
- self.ignore(event)
- def disableMouseEvents(self):
- for event in self.mouseEvents:
- self.ignore(event)
- def inputHandler(self, input):
- # Deal with keyboard and mouse input
- if input == 'mouse1-up':
- messenger.send('DIRECT-mouse1Up')
- if SEditor.widget.fActive:
- messenger.send('shift-f')
- elif input.find('mouse1') != -1:
- modifiers = self.getModifiers(input, 'mouse1')
- messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
- elif input == 'mouse2-up':
- messenger.send('DIRECT-mouse2Up')
- if SEditor.widget.fActive:
- messenger.send('shift-f')
- elif input.find('mouse2') != -1:
- modifiers = self.getModifiers(input, 'mouse2')
- messenger.send('DIRECT-mouse2', sentArgs = [modifiers])
- elif input == 'mouse3-up':
- messenger.send('DIRECT-mouse3Up')
- if SEditor.widget.fActive:
- messenger.send('shift-f')
- elif input.find('mouse3') != -1:
- modifiers = self.getModifiers(input, 'mouse3')
- messenger.send('DIRECT-mouse3', sentArgs = [modifiers])
- elif input == 'shift':
- self.fShift = 1
- elif input == 'shift-up':
- self.fShift = 0
- elif input == 'control':
- self.fControl = 1
- elif input == 'control-up':
- self.fControl = 0
- elif input == 'alt':
- self.fAlt = 1
- elif input == 'alt-up':
- self.fAlt = 0
- elif input == 'page_up':
- self.upAncestry()
- elif input == 'page_down':
- self.downAncestry()
- elif input == 'escape':
- self.deselectAll()
- elif input == 'delete':
- taskMgr.remove('followSelectedNodePath')
- #self.removeAllSelected()
- messenger.send('SGE_Remove',[None])
- self.deselectAll()
- elif input == 'v':
- messenger.send('SEditor-ToggleWidgetVis')
- self.toggleWidgetVis()
- if SEditor.widget.fActive:
- messenger.send('shift-f')
- elif input == 'b':
- messenger.send('SEditor-ToggleBackface')
- base.toggleBackface()
- #elif input == 'control-f':
- # self.flash(last)
- elif input == 'shift-l':
- self.cameraControl.toggleCOALock()
- elif input == 'o':
- self.oobe()
- elif input == 'p':
- if self.selected.last:
- self.setActiveParent(self.selected.last)
- elif input == 'r':
- # Do wrt reparent
- if self.selected.last:
- self.reparent(self.selected.last, fWrt = 1)
- elif input == 'shift-r':
- # Do regular reparent
- if self.selected.last:
- self.reparent(self.selected.last)
- elif input == 's':
- if self.selected.last:
- self.select(self.selected.last)
- elif input == 't':
- messenger.send('SEditor-ToggleTexture')
- base.toggleTexture()
- elif input == 'shift-a':
- self.selected.toggleVisAll()
- elif input == 'w':
- messenger.send('SEditor-ToggleWireframe')
- base.toggleWireframe()
- elif (input == '[') or (input == '{'):
- self.undo()
- elif (input == ']') or (input == '}'):
- self.redo()
-
- def getModifiers(self, input, base):
- modifiers = DIRECT_NO_MOD
- modifierString = input[: input.find(base)]
- if modifierString.find('shift') != -1:
- modifiers |= DIRECT_SHIFT_MOD
- if modifierString.find('control') != -1:
- modifiers |= DIRECT_CONTROL_MOD
- if modifierString.find('alt') != -1:
- modifiers |= DIRECT_ALT_MOD
- return modifiers
- def gotShift(self, modifiers):
- return modifiers & DIRECT_SHIFT_MOD
- def gotControl(self, modifiers):
- return modifiers & DIRECT_CONTROL_MOD
- def gotAlt(self, modifiers):
- return modifiers & DIRECT_ALT_MOD
- def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1, callback=False):
- dnp = self.selected.select(nodePath, fMultiSelect)
- if dnp:
- messenger.send('DIRECT_preSelectNodePath', [dnp])
- if fResetAncestry:
- # Update ancestry
- self.ancestry = dnp.getAncestors()
- self.ancestry.reverse()
- self.ancestryIndex = 0
- # Update the selectedNPReadout
- self.selectedNPReadout.reparentTo(aspect2d)
- self.selectedNPReadout.setText(
- 'Selected:' + dnp.getName())
- # Show the manipulation widget
- self.widget.showWidget()
- # Update camera controls coa to this point
- # Coa2Camera = Coa2Dnp * Dnp2Camera
- mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(self.camera)
- row = mCoa2Camera.getRow(3)
- coa = Vec3(row[0], row[1], row[2])
- self.cameraControl.updateCoa(coa)
- # Adjust widgets size
- # This uses the additional scaling factor used to grow and
- # shrink the widget
- self.widget.setScalingFactor(dnp.getRadius())
- # Spawn task to have object handles follow the selected object
- taskMgr.remove('followSelectedNodePath')
- t = Task.Task(self.followSelectedNodePathTask)
- t.dnp = dnp
- taskMgr.add(t, 'followSelectedNodePath')
- # Send an message marking the event
- messenger.send('DIRECT_selectedNodePath', [dnp])
- if callback:
- messenger.send('se_selectedNodePath', [dnp, False])
- else:
- messenger.send('se_selectedNodePath', [dnp])
- self.upAncestry()
- if SEditor.widget.fActive:
- messenger.send('shift-f')
- def followSelectedNodePathTask(self, state):
- mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render)
- decomposeMatrix(mCoa2Render,
- self.scale,self.hpr,self.pos,
- CSDefault)
- self.widget.setPosHpr(self.pos,self.hpr)
- return Task.cont
- def deselect(self, nodePath):
- dnp = self.selected.deselect(nodePath)
- if dnp:
- # Hide the manipulation widget
- self.widget.hideWidget()
- self.selectedNPReadout.reparentTo(hidden)
- self.selectedNPReadout.setText(' ')
- taskMgr.remove('followSelectedNodePath')
- self.ancestry = []
- # Send an message marking the event
- messenger.send('DIRECT_deselectedNodePath', [dnp])
- def deselectAll(self):
- self.selected.deselectAll()
- # Hide the manipulation widget
- self.widget.hideWidget()
- self.selectedNPReadout.reparentTo(hidden)
- self.selectedNPReadout.setText(' ')
- taskMgr.remove('followSelectedNodePath')
- messenger.send('se_deselectedAll')
- def setActiveParent(self, nodePath = None):
- # Record new parent
- self.activeParent = nodePath
- # Update the activeParentReadout
- self.activeParentReadout.reparentTo(aspect2d)
- self.activeParentReadout.setText(
- 'Active Reparent Target:' + nodePath.getName())
- # Alert everyone else
- self.activeParentReadout.show()
-
- def reparent(self, nodePath = None, fWrt = 0):
- if (nodePath and self.activeParent and
- self.isNotCycle(nodePath, self.activeParent)):
- oldParent = nodePath.getParent()
- if fWrt:
- nodePath.wrtReparentTo(self.activeParent)
- else:
- nodePath.reparentTo(self.activeParent)
- # Alert everyone else
- messenger.send('DIRECT_reparent',
- [nodePath, oldParent, self.activeParent])
- messenger.send('SGE_Update Explorer',[render])
- self.activeParentReadout.hide()
- def isNotCycle(self, nodePath, parent):
- if nodePath.id() == parent.id():
- print 'DIRECT.reparent: Invalid parent'
- return 0
- elif parent.hasParent():
- return self.isNotCycle(nodePath, parent.getParent())
- else:
- return 1
-
- def fitOnNodePath(self, nodePath = 'None Given'):
- if nodePath == 'None Given':
- # If nothing specified, try selected node path
- nodePath = self.selected.last
- SEditor.select(nodePath)
- def fitTask(state, self = self):
- self.cameraControl.fitOnWidget()
- return Task.done
- taskMgr.doMethodLater(0.1, fitTask, 'manipulateCamera')
- def isolate(self, nodePath = 'None Given'):
- """ Show a node path and hide its siblings """
- # First kill the flashing task to avoid complications
- taskMgr.remove('flashNodePath')
- # Use currently selected node path if node selected
- if nodePath == 'None Given':
- nodePath = self.selected.last
- # Do we have a node path?
- if nodePath:
- # Yes, show everything in level
- self.showAllDescendants(nodePath.getParent())
- # Now hide all of this node path's siblings
- nodePath.hideSiblings()
- def toggleVis(self, nodePath = 'None Given'):
- """ Toggle visibility of node path """
- # First kill the flashing task to avoid complications
- taskMgr.remove('flashNodePath')
- if nodePath == 'None Given':
- # If nothing specified, try selected node path
- nodePath = self.selected.last
- if nodePath:
- # Now toggle node path's visibility state
- nodePath.toggleVis()
- def removeNodePath(self, nodePath = 'None Given'):
- if nodePath == 'None Given':
- # If nothing specified, try selected node path
- nodePath = self.selected.last
- if nodePath:
- nodePath.remove()
- def removeAllSelected(self):
- self.selected.removeAll()
- def showAllDescendants(self, nodePath = render):
- """ Show the level and its descendants """
- nodePath.showAllDescendants()
- nodePath.hideCS()
- def upAncestry(self):
- if self.ancestry:
- l = len(self.ancestry)
- i = self.ancestryIndex + 1
- if i < l:
- np = self.ancestry[i]
- name = np.getName()
- if i>0:
- type = self.ancestry[i-1].node().getType().getName()
- else:
- type = self.ancestry[0].node().getType().getName()
- ntype = np.node().getType().getName()
- if (name != 'render') and (name != 'renderTop')and(self.checkTypeNameForAncestry(type, ntype)):
- self.ancestryIndex = i
- self.select(np, 0, 0, True)
-
- def checkTypeNameForAncestry(self, type, nextType ):
- if (type=='ModelRoot'):
- if (nextType=='AmbientLight')or(nextType=='PointLight')or(nextType=='DirectionalLight')or(nextType=='Spotlight'):
- return True
- return False
- elif (type=='ModelNode'):
- if (nextType=='ModelNode'):
- return True
- return False
- elif (type=='CollisionNode'):
- return False
- elif (type=='ActorNode'):
- return False
- elif (type=='AmbientLight')or(type=='PointLight')or(type=='DirectionalLight')or(type=='Spotlight'):
- return False
- else:
- return True
- def downAncestry(self):
- if self.ancestry:
- l = len(self.ancestry)
- i = self.ancestryIndex - 1
- if i >= 0:
- np = self.ancestry[i]
- name = np.getName()
- if (name != 'render') and (name != 'renderTop'):
- self.ancestryIndex = i
- self.select(np, 0, 0, True)
- def getAndSetName(self, nodePath):
- """ Prompt user for new node path name """
- from tkSimpleDialog import askstring
- newName = askstring('Node Path: ' + nodePath.getName(),
- 'Enter new name:')
- if newName:
- nodePath.setName(newName)
- messenger.send('DIRECT_nodePathSetName', [nodePath, newName])
- # UNDO REDO FUNCTIONS
- def pushUndo(self, nodePathList, fResetRedo = 1):
- # Assemble group of changes
- undoGroup = []
- for nodePath in nodePathList:
- t = nodePath.getTransform()
- undoGroup.append([nodePath, t])
- # Now record group
- self.undoList.append(undoGroup)
- # Truncate list
- self.undoList = self.undoList[-25:]
- # Alert anyone who cares
- messenger.send('DIRECT_pushUndo')
- if fResetRedo and (nodePathList != []):
- self.redoList = []
- messenger.send('DIRECT_redoListEmpty')
- def popUndoGroup(self):
- # Get last item
- undoGroup = self.undoList[-1]
- # Strip last item off of undo list
- self.undoList = self.undoList[:-1]
- # Update state of undo button
- if not self.undoList:
- messenger.send('DIRECT_undoListEmpty')
- # Return last item
- return undoGroup
-
- def pushRedo(self, nodePathList):
- # Assemble group of changes
- redoGroup = []
- for nodePath in nodePathList:
- t = nodePath.getTransform()
- redoGroup.append([nodePath, t])
- # Now record redo group
- self.redoList.append(redoGroup)
- # Truncate list
- self.redoList = self.redoList[-25:]
- # Alert anyone who cares
- messenger.send('DIRECT_pushRedo')
- def popRedoGroup(self):
- # Get last item
- redoGroup = self.redoList[-1]
- # Strip last item off of redo list
- self.redoList = self.redoList[:-1]
- # Update state of redo button
- if not self.redoList:
- messenger.send('DIRECT_redoListEmpty')
- # Return last item
- return redoGroup
-
- def undo(self):
- if self.undoList:
- # Get last item off of redo list
- undoGroup = self.popUndoGroup()
- # Record redo information
- nodePathList = map(lambda x: x[0], undoGroup)
- self.pushRedo(nodePathList)
- # Now undo xform for group
- for pose in undoGroup:
- # Undo xform
- pose[0].setTransform(pose[1])
- # Alert anyone who cares
- messenger.send('DIRECT_undo')
- def redo(self):
- if self.redoList:
- # Get last item off of redo list
- redoGroup = self.popRedoGroup()
- # Record undo information
- nodePathList = map(lambda x: x[0], redoGroup)
- self.pushUndo(nodePathList, fResetRedo = 0)
- # Redo xform
- for pose in redoGroup:
- pose[0].setTransform(pose[1])
- # Alert anyone who cares
- messenger.send('DIRECT_redo')
- # UTILITY FUNCTIONS
- def message(self, text):
- taskMgr.remove('hideDirectMessage')
- taskMgr.remove('hideDirectMessageLater')
- self.directMessageReadout.reparentTo(aspect2d)
- self.directMessageReadout.setText(text)
- self.hideDirectMessageLater()
- def hideDirectMessageLater(self):
- taskMgr.doMethodLater(3.0, self.hideDirectMessage, 'hideDirectMessage')
- def hideDirectMessage(self, state):
- self.directMessageReadout.reparentTo(hidden)
- return Task.done
- def useObjectHandles(self):
- self.widget = self.manipulationControl.objectHandles
- self.widget.reparentTo(SEditor.group)
- def hideSelectedNPReadout(self):
- self.selectedNPReadout.reparentTo(hidden)
- def hideActiveParentReadout(self):
- self.activeParentReadout.reparentTo(hidden)
- def toggleWidgetVis(self):
- self.widget.toggleWidget()
- def setCOAMode(self, mode):
- self.coaMode = mode
- def isEnabled(self):
- return self.fEnabled
- def addUnpickable(self, item):
- for iRay in self.iRayList:
- iRay.addUnpickable(item)
- def removeUnpickable(self, item):
- for iRay in self.iRayList:
- iRay.removeUnpickable(item)
- def toggleAutoCamera(self):
- self.enableAutoCamera = (self.enableAutoCamera+1)%2
- if self.enableAutoCamera==1:
- self.accept('DH_LoadingComplete', self.autoCameraMove)
- else:
- self.ignore('DH_LoadingComplete')
- return
- def autoCameraMove(self, nodePath):
- time = 1
- node = DirectNodePath(nodePath)
- radius = node.getRadius()
- center = node.getCenter()
- node.dehighlight()
- posB = base.camera.getPos()
- hprB = base.camera.getHpr()
- posE = Point3((radius*-1.41)+center.getX(), (radius*-1.41)+center.getY(), (radius*1.41)+center.getZ())
- hprE = Point3(-45, -38, 0)
- print posB, hprB
- print posE, hprE
- posInterval1 = base.camera.posInterval(time, posE, bakeInStart = 1)
- posInterval2 = base.camera.posInterval(time, posB, bakeInStart = 1)
-
- hprInterval1 = base.camera.hprInterval(time, hprE, bakeInStart = 1)
- hprInterval2 = base.camera.hprInterval(time, hprB, bakeInStart = 1)
- parallel1 = Parallel(posInterval1, hprInterval1)
- parallel2 = Parallel(posInterval2, hprInterval2)
- Sequence(Wait(7), parallel1, Wait(1), parallel2).start()
-
- return
-
- class DisplayRegionContext(DirectObject):
- regionCount = 0
- def __init__(self, cam):
- self.cam = cam
- self.camNode = self.cam.node()
- self.camLens = self.camNode.getLens()
- # set lens change callback
- changeEvent = 'dr%d-change-event' % DisplayRegionContext.regionCount
- DisplayRegionContext.regionCount += 1
- self.camLens.setChangeEvent(changeEvent)
- self.accept(changeEvent, self.camUpdate)
- self.iRay = SelectionRay(self.cam)
- self.nearVec = Vec3(0)
- self.mouseX = 0.0
- self.mouseY = 0.0
- # A Camera node can have more than one display region
- # associated with it. Here I assume that there is only
- # one display region per camera, since we are defining a
- # display region on a per-camera basis. See note in
- # DisplayRegionList.__init__()
- try:
- self.dr = self.camNode.getDr(0)
- except:
- self.dr = self.camNode.getDisplayRegion(0)
- left = self.dr.getLeft()
- right = self.dr.getRight()
- bottom = self.dr.getBottom()
- top = self.dr.getTop()
- self.originX = left+right-1
- self.originY = top+bottom-1
- self.scaleX = 1.0/(right-left)
- self.scaleY = 1.0/(top-bottom)
- self.setOrientation()
- self.camUpdate()
- def __getitem__(self,key):
- return self.__dict__[key]
- def setOrientation(self):
- # MRM This assumes orientation is set on transform above cam
- hpr = self.cam.getHpr()
- if hpr[2] < 135 and hpr[2]>45 or hpr[2]>225 and hpr[2]<315:
- self.isSideways = 1
- elif hpr[2] > -135 and hpr[2] < -45 or hpr[2] < -225 and hpr[2] > -315:
- self.isSideways = 1
- else:
- self.isSideways = 0
- # The following take into consideration sideways displays
- def getHfov(self):
- if self.isSideways:
- return self.camLens.getVfov()
- else:
- return self.camLens.getHfov()
- def getVfov(self):
- if self.isSideways:
- return self.camLens.getHfov()
- else:
- return self.camLens.getVfov()
- def setHfov(self,hfov):
- if self.isSideways:
- self.camLens.setFov(self.camLens.getHfov(), hfov)
- else:
- self.camLens.setFov(hfov, self.camLens.getVfov())
- def setVfov(self,vfov):
- if self.isSideways:
- self.camLens.setFov(vfov, self.camLens.getVfov())
- else:
- self.camLens.setFov(self.camLens.getHfov(), vfov)
- def setFov(self,hfov,vfov):
- if self.isSideways:
- self.camLens.setFov(vfov, hfov)
- else:
- self.camLens.setFov(hfov, vfov)
- def getWidth(self):
- prop = base.win.getProperties()
- if prop.hasSize():
- return prop.getXSize()
- else:
- return 640
-
- def getHeight(self):
- prop = base.win.getProperties()
- if prop.hasSize():
- return prop.getYSize()
- else:
- return 480
-
- def camUpdate(self, lens = None):
- # Window Data
- self.near = self.camLens.getNear()
- self.far = self.camLens.getFar()
- self.fovH = self.camLens.getHfov()
- self.fovV = self.camLens.getVfov()
- self.nearWidth = math.tan(deg2Rad(self.fovH * 0.5)) * self.near * 2.0
- self.nearHeight = math.tan(deg2Rad(self.fovV * 0.5)) * self.near * 2.0
- self.left = -self.nearWidth * 0.5
- self.right = self.nearWidth * 0.5
- self.top = self.nearHeight * 0.5
- self.bottom = -self.nearHeight * 0.5
- def mouseUpdate(self):
- # Mouse Data
- # Last frame
- self.mouseLastX = self.mouseX
- self.mouseLastY = self.mouseY
- # Values for this frame
- # This ranges from -1 to 1
- if (base.mouseWatcherNode.hasMouse()):
- self.mouseX = base.mouseWatcherNode.getMouseX()
- self.mouseY = base.mouseWatcherNode.getMouseY()
- self.mouseX = (self.mouseX-self.originX)*self.scaleX
- self.mouseY = (self.mouseY-self.originY)*self.scaleY
- # Delta percent of window the mouse moved
- self.mouseDeltaX = self.mouseX - self.mouseLastX
- self.mouseDeltaY = self.mouseY - self.mouseLastY
- self.nearVec.set((self.nearWidth*0.5) * self.mouseX,
- self.near,
- (self.nearHeight*0.5) * self.mouseY)
- class DisplayRegionList(DirectObject):
- def __init__(self):
- self.displayRegionList = []
- i = 0
- # Things are funky if we are oobe
- if (hasattr(base, 'oobeMode') and base.oobeMode):
- # assume we only have one cam at this point
- drc = DisplayRegionContext(base.cam)
- self.displayRegionList.append(drc)
- else:
- # MRM: Doesn't properly handle multiple camera groups anymore
- # Assumes everything is under main camera
-
- # This is following the old way of setting up
- # display regions. A display region is set up for
- # each camera node in the scene graph. This was done
- # so that only display regions in the scene graph are
- # considered. The right way to do this is to set up
- # a display region for each real display region, and then
- # keep track of which are currently active (e.g. use a flag)
- # processing only them.
- for camIndex in range(len(base.camList)):
- cam = base.camList[camIndex]
- if cam.getName()=='<noname>':
- cam.setName('Camera%d' % camIndex)
- drc = DisplayRegionContext(cam)
- self.displayRegionList.append(drc)
- self.accept("DIRECT-mouse1",self.mouseUpdate)
- self.accept("DIRECT-mouse2",self.mouseUpdate)
- self.accept("DIRECT-mouse3",self.mouseUpdate)
- self.accept("DIRECT-mouse1Up",self.mouseUpdate)
- self.accept("DIRECT-mouse2Up",self.mouseUpdate)
- self.accept("DIRECT-mouse3Up",self.mouseUpdate)
- def __getitem__(self, index):
- return self.displayRegionList[index]
- def __len__(self):
- return len(self.displayRegionList)
- def updateContext(self):
- self.contextTask(None)
- def setNearFar(self, near, far):
- for dr in self.displayRegionList:
- dr.camLens.setNearFar(near, far)
-
- def setNear(self, near):
- for dr in self.displayRegionList:
- dr.camLens.setNear(near)
-
- def setFar(self, far):
- for dr in self.displayRegionList:
- dr.camLens.setFar(far)
- def setFov(self, hfov, vfov):
- for dr in self.displayRegionList:
- dr.setFov(hfov, vfov)
- def setHfov(self, fov):
- for dr in self.displayRegionList:
- dr.setHfov(fov)
- def setVfov(self, fov):
- for dr in self.displayRegionList:
- dr.setVfov(fov)
- def mouseUpdate(self, modifiers = DIRECT_NO_MOD):
- for dr in self.displayRegionList:
- dr.mouseUpdate()
- SEditor.dr = self.getCurrentDr()
- def getCurrentDr(self):
- for dr in self.displayRegionList:
- if (dr.mouseX >= -1.0 and dr.mouseX <= 1.0 and
- dr.mouseY >= -1.0 and dr.mouseY <= 1.0):
- return dr
- return self.displayRegionList[0]
- def start(self):
- # First shutdown any existing task
- self.stop()
- # Start a new context task
- self.spawnContextTask()
- def stop(self):
- # Kill the existing context task
- taskMgr.remove('DIRECTContextTask')
- def spawnContextTask(self):
- taskMgr.add(self.contextTask, 'DIRECTContextTask')
- def removeContextTask(self):
- taskMgr.remove('DIRECTContextTask')
- def contextTask(self, state):
- # Window Data
- self.mouseUpdate()
- # hack to test movement
- return Task.cont
- # Create one
- #__builtins__['direct'] = base.direct = DirectSession()
|