Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
38c15b1bdd

+ 10 - 1
direct/src/directscripts/python-mode.el

@@ -554,7 +554,7 @@ Currently-active file is at the head of the list.")
   (define-key py-shell-map "\C-c-" 'py-up-exception)
   (define-key py-shell-map "\C-c-" 'py-up-exception)
   (define-key py-shell-map "\C-c=" 'py-down-exception)
   (define-key py-shell-map "\C-c=" 'py-down-exception)
   ;; VR STUDIO ENHANCEMENTS
   ;; VR STUDIO ENHANCEMENTS
-  (define-key py-shell-map "\C-d"  'delete-char)
+  (define-key py-shell-map "\C-d"  'comint-delchar-or-maybe-python-resume)
   (define-key py-shell-map "\C-c\C-r" 'python-resume)
   (define-key py-shell-map "\C-c\C-r" 'python-resume)
   (define-key py-shell-map "\C-c\C-s" 'pyd-shell)
   (define-key py-shell-map "\C-c\C-s" 'pyd-shell)
   )
   )
@@ -3146,6 +3146,15 @@ These are Python temporary files awaiting execution."
 (add-hook 'kill-emacs-hook 'py-kill-emacs-hook)
 (add-hook 'kill-emacs-hook 'py-kill-emacs-hook)
 
 
 ;; VR STUDIO ENHANCEMENT
 ;; VR STUDIO ENHANCEMENT
+(defun comint-delchar-or-maybe-python-resume (arg)
+  "Delete ARG characters forward or send a python-resume to subprocess.
+  Sends a python-resume only if point is at the end of the buffer and there is no input."
+  (interactive "p")
+  (let ((proc (get-buffer-process (current-buffer))))
+    (if (and (eobp) proc (= (point) (marker-position (process-mark proc))))
+	(python-resume)
+      (delete-char arg))))
+
 ;; Function to try to resume panda mainloop
 ;; Function to try to resume panda mainloop
 (defun python-resume ()
 (defun python-resume ()
   (interactive)
   (interactive)

+ 307 - 0
direct/src/directutil/DirectCameraManipulation.py

@@ -0,0 +1,307 @@
+from PandaObject import *
+from DirectGrid import DirectGrid
+
+class DirectCameraManipulation(PandaObject):
+    def __init__():
+        # Create the grid
+	self.grid = DirectGrid(render)
+	self.grid.hide()
+	self.hitPt = Point3(0)
+	self.iPoint = Point3(0)
+	self.centerOfRotation = render.attachNewNode( NamedNode() )
+	self.centerOfRotation.node().setName( 'centerOfRotation' )
+	self.centerOfRotation.setPosHpr(Vec3(0), Vec3(0))
+	self.orthoViewRoll = 0.0
+	self.lastView = 0
+	self.targetNodePath = render.attachNewNode(NamedNode('targetNode'))
+        self.zeroBaseVec = VBase3(0)
+        self.zeroVector = Vec3(0)
+        self.centerVec = Vec3(0., 1., 0.)
+        self.zeroPoint = Point3(0)
+
+    def centerCam(chan):
+        # Chan is a display region context
+	self.centerCamIn(chan, 1.0)
+        
+    def centerCamNow(chan):
+        self.centerCamIn(chan, 0.)
+
+    def centerCamIn(chan,t):
+        # Chan is a display region context
+	taskMgr.removeTasksNamed('manipulateCamera')
+	widgetToCam = direct.widget.getPos( chan.camera )
+	dist = Vec3(widgetToCam - zeroPoint).length()
+	scaledCenterVec = centerVec * dist.
+	delta = widgetToCam - scaledCenterVec.
+	relNodePath = render.attachNewNode(Node())
+	relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0))
+        ###
+	[ chan camera setPos: relNodePath pos: delta t: t. 
+		] spawnTaskNamed: 'manipulateCamera'
+	uponDeath: [ relNodePath removeNode. ]
+        ###
+
+    def homeCam(chan):
+        chan.camera.setMat(Mat4.identMat())
+
+
+    def mouseFlyStart(chan):
+	# Record starting mouse positions
+	initMouseX = chan.mouseX
+	initMouseY = chan.mouseY
+
+	# Where are we in the channel?
+        if ((initMouseX abs < 0.9) & (initMouseY abs < 0.9)):
+            # Mouse is in central region
+            # spawn task to determine mouse fly mode"
+            self.determineMouseFlyMode()
+        else:
+            #Mouse is in outer frame, spawn mouseRotateTask
+            self.spawnMouseRotateTask()
+
+    def mouseFlyStop():
+	taskMgr.removeTasksNamed('determineMouseFlyMode')
+	taskMgr.removeTasksNamed('manipulateCamera')
+
+    def removeManipulateCameraTask():
+        taskMgr.removeTasksNamed('manipulateCamera')
+
+    def enableMouseFly():
+	self.enableMouseInteraction()
+	self.enableHotKeys()
+
+    def enableMouseInteraction():
+	# disable C++ fly interface
+	base.disableMouse()
+	# Accept middle mouse events
+	self.accept('mouse2', self.mouseFlyStart, [chanCenter])
+	self.accept('mouse2-up' self.mouseFlyStop)
+
+    def disableMouseFly():
+	# Accept middle mouse events
+	self.ignore('mouse2')
+	self.ignore:'mouse2-up')
+	self.ignore('u')
+	self.ignore('c')
+	self.ignore('h')
+        for i in range(0,10):
+            self.ignore(`i`)
+	self.ignore('=')
+	self.ignore('+')
+	self.ignore('-')
+	self.ignore('=')
+
+    def enableHotKeys():
+	self.accept('u', self.uprightCam, [chanCenter])
+	self.accept('c', self.centerCamIn, [chanCenter, 0.5])
+	self.accept('h', self.homeCam, [chanCenter])
+        for i in range(1,8):
+            self.accept(`i`, self.moveToView, [chanCenter, i])
+	self.accept('9', self.swingCamAboutWidget, [chanCenter, -90.0, 1.0])
+	self.accept('0', self.swingCamAboutWidget, [chanCenter,  90.0, 1.0])
+	self.accept('8', self.removeManipulateCameraTask)
+	self.accept('=', self.zoomCam, [chanCenter, 0.5, 1.0])
+	self.accept('+', self.zoomCam, [chanCenter, 0.5, 1.0])
+	self.accept('-', self.zoomCam, [chanCenter, -2.0, 1.0])
+	self.accept('=', self.zoomCam, [chanCenter, -2.0, 1.0])
+
+    def SpawnMoveToView(chan, view):
+        # Kill any existing tasks
+	taskMgr.removeTasksNamed('manipulateCamera')
+        # Calc hprOffset
+	hprOffset = VBase3()
+        if view = 1:
+            hprOffset.set(180., 0., 0.)
+        elif view = 2:
+            hprOffset set(0., 0., 0.)
+        elif view = 3:
+            hprOffset set(90., 0., 0.)
+        elif view = 4:
+            hprOffset set(-90., 0., 0.)
+        elif view = 5:
+            hprOffset set(0., -90., 0.)
+        elif view = 6:
+            hprOffset set(0., 90., 0.)
+        elif view = 7:
+            hprOffset set(135., -35.264, 0.)
+        # Position target
+	targetNodePath.setPosHpr(direct.widget,
+                                 self.zeroBaseVec,
+                                 hprOffset)
+	# Scale center vec by current distance to target
+	offsetDistance = Vec3(chan.camera.getPos(targetNodePath) - \
+                              zeroPoint).length()
+	scaledCenterVec = centerVec * (-1.0 * offsetDistance).
+
+   	# Now put the targetNodePath at that point
+	targetNodePath.setPosHpr(targetNodePath,
+                                 scaledCenterVec,
+                                 zeroBaseVec)
+
+	# Start off with best view if change is to new view
+        if (view != lastView):
+            orthoViewRoll = 0.0
+        lastView = view.
+
+	[ chan camera setPosHpr: targetNodePath pos: zeroBaseVec 
+    			       hpr: (VBase3 new: 0.0 y: 0.0 z: orthoViewRoll)
+			       t: 1.0.
+	  "Try another roll next time"
+	  orthoViewRoll = (orthoViewRoll + 90.0) rem: 360.0.]
+		spawnTaskNamed: #manipulateCamera.
+        
+
+    def determineMouseFlyMode():
+        # Get mouse intersection point
+        # TBS
+
+        # Find this point to camera space
+	gridToCamera = grid getMat: chanCenter camera.
+	hitPt operatorAssign: (gridToCamera xformPoint: iPoint).
+	"Make sure hitPt is in front of the camera"
+	hitPt setY: (hitPt at: 1) abs.
+
+	"Handle case of bad hit point (too close or too far)"
+	hitDistance = (hitPt - zeroPoint) length.
+	((hitDistance < (1.1 * chanCenter near)) | (hitDistance > chanCenter far)) ifTrue: [ 
+		"Just use grid origin"
+		"hitPt operatorAssign: centerVec * (0.5 * (chanCenter far + chanCenter near))"
+		hitPt operatorAssign: (grid getPos: chanCenter camera).
+		].
+
+	(direct fShift) ifTrue: [ self.spawnHPPan. ]
+	ifFalse: [
+		[[deltaX = chanCenter mouseX - initMouseX.
+			deltaY = chanCenter mouseY - initMouseY.
+			((deltaX abs < 0.1) & (deltaY abs < 0.1))] taskWhileTrue: [ nil ]
+			] spawnTaskNamed: #determineMouseFlyMode
+			uponDeath: [
+				(deltaY abs > 0.1) ifTrue: [
+					self.spawnHPanYZoom]
+	 			ifFalse: [
+					self.spawnXZTranslate ].
+		].
+			].
+! !
+
+
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+spawnHPPan
+	[[true] taskWhileTrue:
+		[ chanCenter camera setHpr: chanCenter camera 
+			h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
+			p: (-0.5 * chanCenter mouseDeltaY * chanCenter fovV)
+			r: 0.0 ]]
+	spawnTaskNamed: #manipulateCamera.
+! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+spawnHPanYZoom
+	| targetVector distToMove |
+	targetVector = Vec3 new: (hitPt at: 0) y: (hitPt at: 1) z: (hitPt at: 2).
+	[[true] taskWhileTrue:
+		[ distToMove = targetVector * (-1.0 * chanCenter mouseDeltaY).
+		  chanCenter camera setPosHpr: chanCenter camera 
+			x: (distToMove at: 0)
+			y: (distToMove at: 1)
+			z: (distToMove at: 2)
+			h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
+			p: 0.0 r: 0.0. ]]
+	spawnTaskNamed: #manipulateCamera.
+! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+spawnMouseRotateTask
+	| wrtMat |
+	centerOfRotation setPos: grid pos: iPoint.
+	centerOfRotation setHpr: chanCenter camera h: 0.0 p: 0.0 r: 0.0.
+	
+	wrtMat = chanCenter camera getMat: centerOfRotation.
+
+	[[true] taskWhileTrue:
+		[ centerOfRotation setHpr: centerOfRotation
+			h: (-0.5 * chanCenter mouseDeltaX * 180.0)
+			p: (0.5 * chanCenter mouseDeltaY * 180.0)
+			r: 0.0.
+		   chanCenter camera setMat: centerOfRotation mat: wrtMat. ]]
+	spawnTaskNamed: #manipulateCamera.
+! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+spawnXZTranslate
+	| scaleFactor | 
+	scaleFactor = ((hitPt at: 1) / chanCenter near).
+	[[true] taskWhileTrue:
+		[ chanCenter camera setPos: chanCenter camera 
+			x: (-0.5 * chanCenter mouseDeltaX * chanCenter nearWidth * scaleFactor)
+			y: 0.0
+			z: (-0.5 * chanCenter mouseDeltaY * chanCenter nearHeight * scaleFactor) ] ]
+	spawnTaskNamed: #manipulateCamera. 
+! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+spawnXZTranslateOrHPPan
+	| scaleFactor | 
+	scaleFactor = ((hitPt at: 1) / chanCenter near).
+	[[true] taskWhileTrue:
+		[ direct fShift 
+			ifTrue: [ chanCenter camera setHpr: chanCenter camera 
+						h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
+						p: (-0.5 * chanCenter mouseDeltaY * chanCenter fovV)
+						r: 0.0 ]
+			ifFalse: [ chanCenter camera setPos: chanCenter camera 
+						x: (-0.5 * chanCenter mouseDeltaX * chanCenter nearWidth * scaleFactor)
+						y: 0.0
+						z: (-0.5 * chanCenter mouseDeltaY * chanCenter nearHeight * scaleFactor)]
+		]]
+	spawnTaskNamed: #manipulateCamera. 
+! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+swingCamAboutWidget: chan deg: degrees in: t
+	| relNodePath parent |
+
+	Task removeTasksNamed: #manipulateCamera.
+	
+	relNodePath = showBase render attachNewNode: (Node new).
+	"Coincident with widget"
+	relNodePath setPos: direct widget pos: (Point3 zero).
+	"But aligned with render space"
+	relNodePath setHpr: (Point3 zero).
+
+	parent = chanCenter camera getParent.
+	chanCenter camera wrtReparentTo: relNodePath.
+
+	[ relNodePath setHpr: (VBase3 new: degrees y: 0.0 z: 0.0) t: t. ] 
+		spawnTaskNamed: #manipulateCamera
+		uponDeath: [ 
+			chanCenter camera wrtReparentTo: parent.
+			relNodePath reparentTo: showBase hidden.
+			relNodePath removeNode.
+			].! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+uprightCam: chan
+	| currH |
+	Task removeTasksNamed: #manipulateCamera.
+	currH = chan camera getH.
+	[ chan camera setHpr: showBase render h: currH p: 0.0 r: 0.0 t: 1.0.
+		] spawnTaskNamed: #manipulateCamera.! !
+
+!DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
+zoomCam: chan zoom: zoom in: t
+	| relNodePath zoomPtToCam |
+	Task removeTasksNamed: #manipulateCamera.
+	"Find a point zoom factor times the current separation of the widget and cam"
+	zoomPtToCam = (direct widget getPos: chan camera) * zoom.
+
+	"Put a target nodePath there"
+	relNodePath = showBase render attachNewNode: (Node new).
+	relNodePath setPos: chanCenter camera pos: zoomPtToCam.
+	
+	"Move to that point"
+	[ chan camera setPos: relNodePath pos: (Point3 zero) t: t. ] 
+		spawnTaskNamed: #manipulateCamera
+		uponDeath: [ relNodePath removeNode. ].! !
+

+ 56 - 0
direct/src/directutil/DirectGeometry.py

@@ -0,0 +1,56 @@
+from PandaObject import *
+import math
+
+class LineNodePath(NodePath):
+    def __init__(self, parent = hidden, **kw):
+
+        # Initialize the superclass
+        NodePath.__init__(self)
+
+        # Attach a geomNode to the parent and set self to be
+        # the resulting node path
+        self.lineNode = GeomNode()
+        self.assign(parent.attachNewNode( self.lineNode ))
+
+        # Create a lineSegs object to hold the line
+        ls = self.lineSegs = LineSegs()
+        # Initialize the lineSegs parameters
+        ls.setThickness( kw.get('thickness', 1.0) )
+        ls.setColor( kw.get('colorVec', VBase4(1.0)) )
+
+    def moveTo( self, *_args ):
+        apply( self.lineSegs.moveTo, _args )
+
+    def drawTo( self, *_args ):
+        apply( self.lineSegs.drawTo, _args )
+
+    def create( self, frameAccurate = 0 ):
+        self.lineSegs.create( self.lineNode, frameAccurate )
+
+    def reset( self ):
+        self.lineSegs.reset()
+        self.lineNode.clear()
+
+    def isEmpty( self ):
+        return self.lineSegs.isEmpty()
+
+    def setThickness( self, thickness ):
+        self.lineSegs.setThickness( thickness )
+
+    def setColor( self, *_args ):
+        apply( self.lineSegs.setColor, _args )
+
+    def setVertexColor( self, vertex, *_args ):
+        apply( self.lineSegs.setVertexColor, (vertex,) + _args )
+
+    def getCurrentPosition( self ):
+        return self.lineSegs.getCurrentPosition()
+
+    def getNumVertices( self ):
+        return self.lineSegs.getNumVertices()
+
+    def getVertex( self ):
+        return self.lineSegs.getVertex()
+
+    def getVertexColor( self ):
+        return self.lineSegs.getVertexColor()

+ 7 - 0
direct/src/directutil/DirectGrid.py

@@ -0,0 +1,7 @@
+from PandaObject import *
+
+class DirectGrid(NodePath):
+    def __init__(self, parent = hidden):
+        NodePath.__init__(self)
+        self.assign(parent.attachNewNode( NamedNode('grid') ))
+

+ 31 - 0
direct/src/directutil/DirectSelection.py

@@ -0,0 +1,31 @@
+dd = loader.loadModel(r"I:\beta\toons\install\neighborhoods\donalds_dock")
+dd.reparentTo(render)
+
+cam = base.cam.node()
+rNode = camera.attachNewNode( CollisionNode() )
+rNode.node().setCollideGeom(1)
+ray = CollisionRay()
+rNode.node().addSolid( ray )
+cq = CollisionHandlerQueue()
+ct = CollisionTraverser( )
+# Optionally
+# ct = CollisionTraverser( RenderRelation.getClassType() )
+ct.addCollider(rNode.node(), cq )
+# These are the mouse coordinates
+ray.setProjection( cam, 0, 0 )
+ct.traverse( render.node() )
+
+# Operations on cq
+cq.getNumEntries()
+cq.getEntry(0).getIntoNode()
+cq.getEntry(0).getIntoNode().getName()
+print cq.getEntry(i).getIntoIntersectionPoint()
+
+for i in range(0,cq.getNumEntries()):
+    name = cq.getEntry(i).getIntoNode().getName()
+    if not name:
+        name = "<noname>"
+    print name
+    print cq.getEntry(i).getIntoIntersectionPoint()[0],
+    print cq.getEntry(i).getIntoIntersectionPoint()[1],
+    print cq.getEntry(i).getIntoIntersectionPoint()[2]

+ 69 - 37
direct/src/directutil/DirectSession.py

@@ -1,4 +1,6 @@
 from PandaObject import *
 from PandaObject import *
+from DirectGeometry import *
+import OnscreenText
 import math
 import math
 
 
 class DisplayRegionContext(PandaObject):
 class DisplayRegionContext(PandaObject):
@@ -51,7 +53,7 @@ class DisplayRegionContext(PandaObject):
         self.mouseDeltaY = self.mouseY - self.mouseLastY
         self.mouseDeltaY = self.mouseY - self.mouseLastY
         # Continue the task
         # Continue the task
         return Task.cont
         return Task.cont
-        
+
 class DirectSession(PandaObject):
 class DirectSession(PandaObject):
     def __init__(self):
     def __init__(self):
         self.contextList = []
         self.contextList = []
@@ -62,50 +64,80 @@ class DirectSession(PandaObject):
         self.selectedNodePaths = {}
         self.selectedNodePaths = {}
         self.lastSelected = None
         self.lastSelected = None
 
 
+        self.readout = OnscreenText.OnscreenText( '', 0.1, -0.95 )
+        # self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5)
+        self.readout.reparentTo( hidden )
+
+        self.createBBox()
+
+        # self.createObjectHandles()
+        # self.useObjectHandles()
+        
         self.bboxList = []
         self.bboxList = []
 
 
         self.fControl = 0
         self.fControl = 0
         self.fAlt = 0
         self.fAlt = 0
         self.fShift = 0
         self.fShift = 0
         
         
-        """"
-    def createBBox(self):
-	bbox = hidden.attachNewNode(NamedNode())
-	bbox.setName('bbox')
-	bboxLines = GridLine new: bbox.
-	bboxLines color: (VBase4 new: 1.0 y: 0.0 z: 0.0 w: 1.0).
-	bboxLines thickness: 0.5.
-
-	"Bottom face"
-	bboxLines moveTo: 0.0 y: 0.0 z: 0.0.
-	bboxLines drawTo: 1.0 y: 0.0 z: 0.0.
-	bboxLines drawTo: 1.0 y: 1.0 z: 0.0.
-	bboxLines drawTo: 0.0 y: 1.0 z: 0.0.
-	bboxLines drawTo: 0.0 y: 0.0 z: 0.0.
-
-	"Front Edge/Top face"
-	bboxLines drawTo: 0.0 y: 0.0 z: 1.0.
-	bboxLines drawTo: 1.0 y: 0.0 z: 1.0.
-	bboxLines drawTo: 1.0 y: 1.0 z: 1.0.
-	bboxLines drawTo: 0.0 y: 1.0 z: 1.0.
-	bboxLines drawTo: 0.0 y: 0.0 z: 1.0.
-
-	"Three remaining edges"
-	bboxLines moveTo: 1.0 y: 0.0 z: 0.0.
-	bboxLines drawTo: 1.0 y: 0.0 z: 1.0.
-	bboxLines moveTo: 1.0 y: 1.0 z: 0.0.
-	bboxLines drawTo: 1.0 y: 1.0 z: 1.0.
-	bboxLines moveTo: 0.0 y: 1.0 z: 0.0.
-	bboxLines drawTo: 0.0 y: 1.0 z: 1.0.
-
-	bboxLines create: bboxLines lineNode.! !
-        """
-
-class Line(NodePath, LineSegs):
-    def __init__(self):
-        LineSegs.__init__(self)
+    def createBBox(self, parent = hidden):
+        # Create a line segments object for the bbox
+	bbox = self.bbox = LineNodePath(parent)
+	#bbox.setName('bbox')
+        bbox.setColor( VBase4( 1., 0., 0., 1. ) )
+	bbox.setThickness( 0.5 )
+
+        # Bottom face
+	bbox.drawTo( 0.0, 0.0, 0.0 )
+	bbox.drawTo( 1.0, 0.0, 0.0 )
+	bbox.drawTo( 1.0, 1.0, 0.0 )
+	bbox.drawTo( 0.0, 1.0, 0.0 )
+	bbox.drawTo( 0.0, 0.0, 0.0 )
+
+	# Front Edge/Top face
+	bbox.drawTo( 0.0, 0.0, 1.0 )
+	bbox.drawTo( 1.0, 0.0, 1.0 )
+	bbox.drawTo( 1.0, 1.0, 1.0 )
+	bbox.drawTo( 0.0, 1.0, 1.0 )
+	bbox.drawTo( 0.0, 0.0, 1.0 )
+
+	# Three remaining edges
+	bbox.moveTo( Point3( 1.0, 0.0, 0.0 ) )
+	bbox.drawTo( 1.0, 0.0, 1.0 )
+	bbox.moveTo( Point3( 1.0, 1.0, 0.0 ) )
+	bbox.drawTo( 1.0, 1.0, 1.0 )
+	bbox.moveTo( Point3( 0.0, 1.0, 0.0 ) )
+	bbox.drawTo( 0.0, 1.0, 1.0 )
+
+	bbox.create()
+
+    def createObjectHandles(self):
+	oh = self.objectHandles = hidden.attachNewNode( NamedNode('objectHandles') )
+	ohLines = LineNodePath( oh )
+	ohLines.setColor( VBase4( 1.0, 0.0, 1.0, 1.0) )
+	ohLines.setThickness( 3.0 )
+
+	"InnerRing"
+	ohLines.moveTo( 0.8, 0.0, 0.0 )
+        for ang in range(10, 360, 10):
+            ohLines.drawTo( (0.8 * math.cos(deg2Rad(ang))),
+                            (0.8 * math.sin(deg2Rad(ang))),
+                            0.0 )
+
+	"Outer Ring" 
+	ohLines.moveTo( 1.2, 0.0, 0.0 )
+        for ang in range(0, 360, 10):
+            ohLines.drawTo( (1.2 * math.cos(deg2Rad(ang))),
+                            (1.2 * math.sin(deg2Rad(ang))),
+                            0.0 )
+
+	ohLines.moveTo( 0.0, 0.0, 0.0 )
+	ohLines.drawTo( 0.0, 0.0, 1.5 )
+
+	ohLines.create()
 
 
 
 
+        
+
 
 
 
 
 
 

+ 9 - 1
direct/src/showbase/PythonUtil.py

@@ -25,7 +25,10 @@ def apropos(obj, str = None, fOverloaded = 0, width = None,
             fTruncate = 1, lineWidth = 75):
             fTruncate = 1, lineWidth = 75):
     if type(obj) == types.InstanceType:
     if type(obj) == types.InstanceType:
         print "***************************INSTANCE INFO*****************************"
         print "***************************INSTANCE INFO*****************************"
-    dict = obj.__dict__
+    if type(obj) == types.DictionaryType:
+        dict = obj
+    else:
+        dict = obj.__dict__
     if width:
     if width:
         maxWidth = width
         maxWidth = width
     else:
     else:
@@ -81,3 +84,8 @@ def aproposAll(obj):
     apropos(obj, fOverloaded = 1, fTruncate = 0)
     apropos(obj, fOverloaded = 1, fTruncate = 0)
     
     
 
 
+def doc(obj):
+    if (isinstance(obj, types.MethodType)) or \
+       (isinstance(obj, types.FunctionType)):
+        print obj.__doc__
+