From 43b5345588d0660be68b40e6b11182ac32457d3c Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 25 Jul 2020 12:48:54 +0200 Subject: [PATCH] ShowBase: significant improvements to ShowBase API documentation Fixes #198 --- direct/src/showbase/ShowBase.py | 366 ++++++++++++++++++++++---------- 1 file changed, 255 insertions(+), 111 deletions(-) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 13ce27a6ca..59df8a1407 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -85,6 +85,7 @@ def exitfunc(): # *seem* to cause anyone any problems. class ShowBase(DirectObject.DirectObject): + #: The deprecated `.DConfig` interface for accessing config variables. config = DConfig notify = directNotify.newCategory("ShowBase") @@ -101,6 +102,8 @@ class ShowBase(DirectObject.DirectObject): including this instance itself (under the name ``base``). """ + #: Set if the want-dev Config.prc variable is enabled. By default, it + #: is set to True except when using Python with the -O flag. self.__dev__ = self.config.GetBool('want-dev', __debug__) builtins.__dev__ = self.__dev__ @@ -113,13 +116,13 @@ class ShowBase(DirectObject.DirectObject): if __debug__: self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False) - ## The directory containing the main Python file of this application. + #: The directory containing the main Python file of this application. self.mainDir = ExecutionEnvironment.getEnvironmentVariable("MAIN_DIR") self.main_dir = self.mainDir - ## This contains the global appRunner instance, as imported from - ## AppRunnerGlobal. This will be None if we are not running in the - ## runtime environment (ie. from a .p3d file). + #: This contains the global appRunner instance, as imported from + #: `.AppRunnerGlobal`. This will be None if we are not running in the + #: runtime environment (ie. from a .p3d file). Deprecated. self.appRunner = AppRunnerGlobal.appRunner self.app_runner = self.appRunner @@ -154,13 +157,13 @@ class ShowBase(DirectObject.DirectObject): self.wantTk = False self.wantWx = False - ## Fill this in with a function to invoke when the user "exits" - ## the program by closing the main window. + #: Fill this in with a function to invoke when the user "exits" + #: the program by closing the main window. self.exitFunc = None - ## Add final-exit callbacks to this list. These will be called - ## when sys.exit() is called, after Panda has unloaded, and - ## just before Python is about to shut down. + #: Add final-exit callbacks to this list. These will be called + #: when sys.exit() is called, after Panda has unloaded, and + #: just before Python is about to shut down. self.finalExitCallbacks = [] # Set up the TaskManager to reset the PStats clock back @@ -181,27 +184,34 @@ class ShowBase(DirectObject.DirectObject): # we get a window-event. self.__oldAspectRatio = None - ## This is set to the value of the window-type config variable, but may - ## optionally be overridden in the Showbase constructor. Should either be - ## 'onscreen' (the default), 'offscreen' or 'none'. + #: This is set to the value of the window-type config variable, but may + #: optionally be overridden in the Showbase constructor. Should either + #: be 'onscreen' (the default), 'offscreen' or 'none'. self.windowType = windowType if self.windowType is None: self.windowType = self.config.GetString('window-type', 'onscreen') self.requireWindow = self.config.GetBool('require-window', 1) - ## This is the main, or only window; see winList for a list of *all* windows. + #: This is the main, or only window; see `winList` for a list of *all* windows. self.win = None self.frameRateMeter = None self.sceneGraphAnalyzerMeter = None + #: A list of all windows opened via `openWindow()`. self.winList = [] self.winControls = [] self.mainWinMinimized = 0 self.mainWinForeground = 0 + #: Contains the :class:`~panda3d.core.GraphicsPipe` object created by + #: `makeDefaultPipe()`. self.pipe = None + #: The full list of :class:`~panda3d.core.GraphicsPipe` objects, + #: including any auxiliary pipes. Filled by `makeAllPipes()`. self.pipeList = [] self.mouse2cam = None self.buttonThrowers = None self.mouseWatcher = None + #: The :class:`~panda3d.core.MouseWatcher` object, created by + #: `setupMouse()`. self.mouseWatcherNode = None self.pointerWatcherNodes = None self.mouseInterface = None @@ -211,28 +221,37 @@ class ShowBase(DirectObject.DirectObject): self.showVertices = None self.deviceButtonThrowers = [] - ## This is a NodePath pointing to the Camera object set up for the 3D scene. - ## This is usually a child of self.camera. + #: This is a :class:`~panda3d.core.NodePath` pointing to the + #: :class:`~panda3d.core.Camera` object set up for the 3D scene. + #: Usually a child of `camera`. self.cam = None + #: Same as `cam`, but for the 2D scene graph. self.cam2d = None + #: Same as `cam2d`, but for the 2D overlay scene graph. self.cam2dp = None - ## This is the NodePath that should be used to manipulate the camera. This - ## is the node to which the default camera is attached. + #: This is the :class:`~panda3d.core.NodePath` that should be used to + #: manipulate the camera. It points at the node to which the default + #: camera (`cam`, `camNode`) is attached. self.camera = None + #: Same as `camera`, but for the 2D scene graph. Parent of `cam2d`. self.camera2d = None + #: Same as `camera2d`, but for the 2D overlay scene graph. Parent of + #: `cam2dp`. self.camera2dp = None - ## This is a list of all cameras created with makeCamera, including base.cam. + #: A list of all cameras created with `makeCamera()`, including `cam`. self.camList = [] - ## Convenience accessor for base.cam.node() + #: Convenience accessor for base.cam.node(), containing a + #: :class:`~panda3d.core.Camera` object. self.camNode = None - ## Convenience accessor for base.camNode.get_lens() + #: Convenience accessor for base.camNode.get_lens(), containing a + #: :class:`~panda3d.core.Lens` object. self.camLens = None self.camFrustumVis = None self.direct = None - ## This is used to store the wx.Application object used when want-wx is - ## set or base.startWx() is called. + #: This is used to store the wx.Application object used when want-wx is + #: set or `startWx()` is called. self.wxApp = None self.wxAppCreated = False self.tkRoot = None @@ -251,7 +270,8 @@ class ShowBase(DirectObject.DirectObject): from . import ShowBaseGlobal self.hidden = ShowBaseGlobal.hidden - ## The global graphics engine, ie. GraphicsEngine.getGlobalPtr() + #: The global :class:`~panda3d.core.GraphicsEngine`, as returned by + #: GraphicsEngine.getGlobalPtr() self.graphicsEngine = GraphicsEngine.getGlobalPtr() self.graphics_engine = self.graphicsEngine self.setupRender() @@ -261,10 +281,11 @@ class ShowBase(DirectObject.DirectObject): if self.wantRender2dp: self.setupRender2dp() - - ## This is a placeholder for a CollisionTraverser. If someone - ## stores a CollisionTraverser pointer here, we'll traverse it - ## in the collisionLoop task. + #: A placeholder for a :class:`~panda3d.core.CollisionTraverser`. If + #: someone stores a CollisionTraverser pointer here, ShowBase will + #: traverse it automatically in the collisionLoop task, so you won't + #: need to call :meth:`~panda3d.core.CollisionTraverser.traverse()` + #: yourself every frame. self.cTrav = 0 self.shadowTrav = 0 self.cTravStack = Stack() @@ -322,33 +343,35 @@ class ShowBase(DirectObject.DirectObject): self.mouseInterface = self.trackball self.useTrackball() + #: `.Loader.Loader` object. self.loader = Loader.Loader(self) self.graphicsEngine.setDefaultLoader(self.loader.loader) - ## The global event manager, as imported from EventManagerGlobal. + #: The global event manager, as imported from `.EventManagerGlobal`. self.eventMgr = eventMgr - ## The global messenger, as imported from MessengerGlobal. + #: The global messenger, as imported from `.MessengerGlobal`. self.messenger = messenger - ## The global bulletin board, as imported from BulletinBoardGlobal. + #: The global bulletin board, as imported from `.BulletinBoardGlobal`. self.bboard = bulletinBoard - ## The global task manager, as imported from TaskManagerGlobal. + #: The global task manager, as imported from `.TaskManagerGlobal`. self.taskMgr = taskMgr self.task_mgr = taskMgr - ## The global job manager, as imported from JobManagerGlobal. + #: The global job manager, as imported from `.JobManagerGlobal`. self.jobMgr = jobMgr - - ## Particle manager + #: If `enableParticles()` has been called, this is the particle manager + #: as imported from :mod:`direct.particles.ParticleManagerGlobal`. self.particleMgr = None self.particleMgrEnabled = 0 - ## Physics manager + #: If `enableParticles()` has been called, this is the physics manager + #: as imported from :mod:`direct.showbase.PhysicsManagerGlobal`. self.physicsMgr = None self.physicsMgrEnabled = 0 self.physicsMgrAngular = 0 - ## This is the global input device manager, which keeps track of - ## connected input devices. + #: This is the global :class:`~panda3d.core.InputDeviceManager`, which + #: keeps track of connected input devices. self.devices = InputDeviceManager.getGlobalPtr() self.__inputDeviceNodes = {} @@ -466,6 +489,8 @@ class ShowBase(DirectObject.DirectObject): # Transition effects (fade, iris, etc) from . import Transitions + + #: `.Transitions.Transitions` object. self.transitions = Transitions.Transitions(self.loader) if self.win: @@ -486,12 +511,8 @@ class ShowBase(DirectObject.DirectObject): else: self.multiClientSleep = 0 - # Offscreen buffer viewing utility. - # This needs to be allocated even if the viewer is off. - if self.wantRender2dp: - self.bufferViewer = BufferViewer(self.win, self.render2dp) - else: - self.bufferViewer = BufferViewer(self.win, self.render2d) + #: Utility for viewing offscreen buffers, see :mod:`.BufferViewer`. + self.bufferViewer = BufferViewer(self.win, self.render2dp if self.wantRender2dp else self.render2d) if self.windowType != 'none': if fStartDirect: # [gjeon] if this is False let them start direct manually @@ -635,6 +656,8 @@ class ShowBase(DirectObject.DirectObject): Returns a GraphicsPipe from the indicated module, e.g. 'pandagl' or 'pandadx9'. Does not affect base.pipe or base.pipeList. + + :rtype: panda3d.core.GraphicsPipe """ selection = GraphicsPipeSelection.getGlobalPtr() @@ -643,7 +666,7 @@ class ShowBase(DirectObject.DirectObject): def makeAllPipes(self): """ Creates all GraphicsPipes that the system knows about and fill up - self.pipeList with them. + `pipeList` with them. """ selection = GraphicsPipeSelection.getGlobalPtr() selection.loadAuxModules() @@ -685,27 +708,34 @@ class ShowBase(DirectObject.DirectObject): Creates a window and adds it to the list of windows that are to be updated every frame. - props is the WindowProperties that describes the window. + :param props: the :class:`~panda3d.core.WindowProperties` that + describes the window. - type is either 'onscreen', 'offscreen', or 'none'. + :param fbprops: the :class:`~panda3d.core.FrameBufferProperties` + indicating the requested framebuffer properties. - If keepCamera is true, the existing base.cam is set up to - render into the new window. + :param type: Either 'onscreen', 'offscreen', or 'none'. - If keepCamera is false but makeCamera is true, a new camera is - set up to render into the new window. + :param keepCamera: If True, the existing base.cam is set up to + render into the new window. - If unexposedDraw is not None, it specifies the initial value - of GraphicsWindow.setUnexposedDraw(). + :param makeCamera: If True (and keepCamera is False), a new camera is + set up to render into the new window. - If callbackWindowDict is not None, a CallbackGraphicWindow is - created instead, which allows the caller to create the actual - window with its own OpenGL context, and direct Panda's - rendering into that window. + :param unexposedDraw: If not None, it specifies the initial value + of :meth:`~panda3d.core.GraphicsWindow.setUnexposedDraw()`. - If requireWindow is true, it means that the function should - raise an exception if the window fails to open correctly. + :param callbackWindowDict: If not None, a + :class:`~panda3d.core.CallbackGraphicWindow` + is created instead, which allows the caller + to create the actual window with its own + OpenGL context, and direct Panda's rendering + into that window. + :param requireWindow: If True, the function should raise an exception + if the window fails to open correctly. + + :rtype: panda3d.core.GraphicsWindow """ # Save this lambda here for convenience; we'll use it to call @@ -968,16 +998,19 @@ class ShowBase(DirectObject.DirectObject): self.graphicsEngine.renderFrame() def openDefaultWindow(self, *args, **kw): - # Creates the main window for the first time, without being - # too particular about the kind of graphics API that is - # chosen. The suggested window type from the load-display - # config variable is tried first; if that fails, the first - # window type that can be successfully opened at all is - # accepted. Returns true on success, false otherwise. - # - # This is intended to be called only once, at application - # startup. It is normally called automatically unless - # window-type is configured to 'none'. + """ + Creates the main window for the first time, without being too + particular about the kind of graphics API that is chosen. + The suggested window type from the load-display config variable is + tried first; if that fails, the first window type that can be + successfully opened at all is accepted. + + This is intended to be called only once, at application startup. + It is normally called automatically unless window-type is configured + to 'none'. + + :returns: True on success, False on failure. + """ startDirect = kw.get('startDirect', True) if 'startDirect' in kw: @@ -998,9 +1031,8 @@ class ShowBase(DirectObject.DirectObject): previous main window and open a new one, preserving the lens properties in base.camLens. - The return value is true on success, or false on failure (in - which case base.win may be either None, or the previous, - closed window). + :returns: True on success, or False on failure (in which case base.win + may be either None, or the previous, closed window). """ keepCamera = kw.get('keepCamera', False) @@ -1130,7 +1162,6 @@ class ShowBase(DirectObject.DirectObject): self.textureEnabled = 1 self.wireframeEnabled = 0 - def setupRender2d(self): """ Creates the render2d scene graph, the primary scene graph for @@ -1344,9 +1375,10 @@ class ShowBase(DirectObject.DirectObject): return aspectRatio def getSize(self, win = None): - # Returns the actual size of the indicated (or main - # window), or the default size if there is not yet a - # main window. + """ + Returns the actual size of the indicated (or main window), or the + default size if there is not yet a main window. + """ if win == None: win = self.win @@ -1380,6 +1412,8 @@ class ShowBase(DirectObject.DirectObject): If useCamera is not None, it is a NodePath to be used as the camera to apply to the window, rather than creating a new camera. + + :rtype: panda3d.core.NodePath """ # self.camera is the parent node of all cameras: a node that # we can move around to move all cameras as a group. @@ -1462,6 +1496,8 @@ class ShowBase(DirectObject.DirectObject): """ Makes a new camera2d associated with the indicated window, and assigns it to render the indicated subrectangle of render2d. + + :rtype: panda3d.core.NodePath """ dr = win.makeMonoDisplayRegion(*displayRegion) dr.setSort(sort) @@ -1507,6 +1543,8 @@ class ShowBase(DirectObject.DirectObject): """ Makes a new camera2dp associated with the indicated window, and assigns it to render the indicated subrectangle of render2dp. + + :rtype: panda3d.core.NodePath """ dr = win.makeMonoDisplayRegion(*displayRegion) dr.setSort(sort) @@ -1569,14 +1607,13 @@ class ShowBase(DirectObject.DirectObject): using the indicated window. If the mouse has already been set up for a different window, those structures are deleted first. - The return value is the ButtonThrower NodePath created for - this window. + :param fMultiWin: If True, then the previous mouse structures are not + deleted; instead, multiple windows are allowed to + monitor the mouse input. However, in this case, the + trackball controls are not set up, and must be set up + by hand if desired. - If fMultiWin is true, then the previous mouse structures are - not deleted; instead, multiple windows are allowed to monitor - the mouse input. However, in this case, the trackball - controls are not set up, and must be set up by hand if - desired. + :returns: The ButtonThrower NodePath created for this window. """ if not fMultiWin and self.buttonThrowers != None: for bt in self.buttonThrowers: @@ -1707,18 +1744,30 @@ class ShowBase(DirectObject.DirectObject): self.mouseWatcherNode.setGeometry(mouseViz.node()) def getAlt(self): + """ + Returns True if the alt key is currently held down. + """ return self.mouseWatcherNode.getModifierButtons().isDown( KeyboardButton.alt()) def getShift(self): + """ + Returns True if the shift key is currently held down. + """ return self.mouseWatcherNode.getModifierButtons().isDown( KeyboardButton.shift()) def getControl(self): + """ + Returns True if the control key is currently held down. + """ return self.mouseWatcherNode.getModifierButtons().isDown( KeyboardButton.control()) def getMeta(self): + """ + Returns True if the meta key is currently held down. + """ return self.mouseWatcherNode.getModifierButtons().isDown( KeyboardButton.meta()) @@ -1784,6 +1833,11 @@ class ShowBase(DirectObject.DirectObject): del self.__inputDeviceNodes[device] def addAngularIntegrator(self): + """ + Adds a :class:`~panda3d.physics.AngularEulerIntegrator` to the default + physics manager. By default, only a + :class:`~panda3d.physics.LinearEulerIntegrator` is attached. + """ if not self.physicsMgrAngular: physics = importlib.import_module('panda3d.physics') self.physicsMgrAngular = 1 @@ -1791,6 +1845,15 @@ class ShowBase(DirectObject.DirectObject): self.physicsMgr.attachAngularIntegrator(integrator) def enableParticles(self): + """ + Enables the particle and physics managers, which are stored in + `particleMgr` and `physicsMgr` members, respectively. Also starts a + task to periodically update these managers. + + By default, only a :class:`~panda3d.physics.LinearEulerIntegrator` is + attached to the physics manager. To attach an angular integrator, + follow this up with a call to `addAngularIntegrator()`. + """ if not self.particleMgrEnabled: # Use importlib to prevent this import from being picked up # by modulefinder when packaging an application. @@ -1813,21 +1876,34 @@ class ShowBase(DirectObject.DirectObject): self.taskMgr.add(self.updateManagers, 'manager-update') def disableParticles(self): + """ + The opposite of `enableParticles()`. + """ if self.particleMgrEnabled: self.particleMgrEnabled = 0 self.physicsMgrEnabled = 0 self.taskMgr.remove('manager-update') def toggleParticles(self): + """ + Calls `enableParticles()` or `disableParticles()` depending on the + current state. + """ if self.particleMgrEnabled == 0: self.enableParticles() else: self.disableParticles() def isParticleMgrEnabled(self): + """ + Returns True if `enableParticles()` has been called. + """ return self.particleMgrEnabled def isPhysicsMgrEnabled(self): + """ + Returns True if `enableParticles()` has been called. + """ return self.physicsMgrEnabled def updateManagers(self, state): @@ -1839,6 +1915,11 @@ class ShowBase(DirectObject.DirectObject): return Task.cont def createStats(self, hostname=None, port=None): + """ + If want-pstats is set in Config.prc, or the `wantStats` member is + otherwise set to True, connects to the PStats server. + This is normally called automatically from the ShowBase constructor. + """ # You can specify pstats-host in your Config.prc or use ~pstats/~aipstats # The default is localhost if not self.wantStats: @@ -1854,8 +1935,11 @@ class ShowBase(DirectObject.DirectObject): PStatClient.connect(hostname, port) return PStatClient.isConnected() - def addSfxManager(self, extraSfxManager): + """ + Adds an additional SFX audio manager to `sfxManagerList`, the list of + managers managed by ShowBase. + """ # keep a list of sfx manager objects to apply settings to, # since there may be others in addition to the one we create here self.sfxManagerList.append(extraSfxManager) @@ -1865,6 +1949,10 @@ class ShowBase(DirectObject.DirectObject): extraSfxManager.setActive(self.sfxActive) def createBaseAudioManagers(self): + """ + Creates the default SFX and music manager. Called automatically from + the ShowBase constructor. + """ self.sfxPlayer = SfxPlayer.SfxPlayer() sfxManager = AudioManager.createAudioManager() self.addSfxManager(sfxManager) @@ -1881,6 +1969,9 @@ class ShowBase(DirectObject.DirectObject): # to a user request so sfxActive/musicActive represent how things # *should* be, regardless of App/OS/HW state def enableMusic(self, bEnableMusic): + """ + Enables or disables the music manager. + """ # don't setActive(1) if no audiofocus if self.AppHasAudioFocus and self.musicManagerIsValid: self.musicManager.setActive(bEnableMusic) @@ -1900,6 +1991,9 @@ class ShowBase(DirectObject.DirectObject): self.sfxManagerList[i].setActive(bEnabled) def enableSoundEffects(self, bEnableSoundEffects): + """ + Enables or disables SFX managers. + """ # don't setActive(1) if no audiofocus if self.AppHasAudioFocus or (bEnableSoundEffects==0): self.SetAllSfxEnables(bEnableSoundEffects) @@ -1916,6 +2010,10 @@ class ShowBase(DirectObject.DirectObject): # come back ok when the app is switched back to def disableAllAudio(self): + """ + Disables all SFX and music managers, meant to be called when the app + loses audio focus. + """ self.AppHasAudioFocus = 0 self.SetAllSfxEnables(0) if self.musicManagerIsValid: @@ -1923,6 +2021,11 @@ class ShowBase(DirectObject.DirectObject): self.notify.debug("Disabling audio") def enableAllAudio(self): + """ + Reenables the SFX and music managers that were active at the time + `disableAllAudio() was called. Meant to be called when the app regains + audio focus. + """ self.AppHasAudioFocus = 1 self.SetAllSfxEnables(self.sfxActive) if self.musicManagerIsValid: @@ -1933,6 +2036,9 @@ class ShowBase(DirectObject.DirectObject): # backwards compatibility. Please do not add code here, add # it to the loader. def loadSfx(self, name): + """ + :deprecated: Use `.Loader.Loader.loadSfx()` instead. + """ assert self.notify.warning("base.loadSfx is deprecated, use base.loader.loadSfx instead.") return self.loader.loadSfx(name) @@ -1940,6 +2046,9 @@ class ShowBase(DirectObject.DirectObject): # backwards compatibility. Please do not add code here, add # it to the loader. def loadMusic(self, name): + """ + :deprecated: Use `.Loader.Loader.loadMusic()` instead. + """ assert self.notify.warning("base.loadMusic is deprecated, use base.loader.loadMusic instead.") return self.loader.loadMusic(name) @@ -2070,7 +2179,6 @@ class ShowBase(DirectObject.DirectObject): throw_new_frame() return Task.cont - def __igLoopSync(self, state): if __debug__: # We render the watch variables for the onScreenDebug as soon @@ -2164,6 +2272,8 @@ class ShowBase(DirectObject.DirectObject): Returns the current window background color. This assumes the window is set up to clear the color each frame (this is the normal setting). + + :rtype: panda3d.core.VBase4 """ if win == None: win = self.win @@ -2195,47 +2305,74 @@ class ShowBase(DirectObject.DirectObject): win.setClearColor(color) def toggleBackface(self): + """ + Toggles between `backfaceCullingOn()` and `backfaceCullingOff()`. + """ if self.backfaceCullingEnabled: self.backfaceCullingOff() else: self.backfaceCullingOn() def backfaceCullingOn(self): + """ + Disables two-sided rendering on the entire 3D scene graph. + """ if not self.backfaceCullingEnabled: self.render.setTwoSided(0) self.backfaceCullingEnabled = 1 def backfaceCullingOff(self): + """ + Enables two-sided rendering on the entire 3D scene graph. + """ if self.backfaceCullingEnabled: self.render.setTwoSided(1) self.backfaceCullingEnabled = 0 def toggleTexture(self): + """ + Toggles between `textureOn()` and `textureOff()`. + """ if self.textureEnabled: self.textureOff() else: self.textureOn() def textureOn(self): + """ + Undoes the effects of a previous call to `textureOff()`. + """ self.render.clearTexture() self.textureEnabled = 1 def textureOff(self): + """ + Disables texturing on the entire 3D scene graph. + """ self.render.setTextureOff(100) self.textureEnabled = 0 def toggleWireframe(self): + """ + Toggles between `wireframeOn()` and `wireframeOff()`. + """ if self.wireframeEnabled: self.wireframeOff() else: self.wireframeOn() def wireframeOn(self): + """ + Enables wireframe rendering on the entire 3D scene graph. + """ self.render.setRenderModeWireframe(100) self.render.setTwoSided(1) self.wireframeEnabled = 1 def wireframeOff(self): + """ + Undoes the effects of a previous call to `wireframeOn()`. + """ self.render.clearRenderMode() render.setTwoSided(not self.backfaceCullingEnabled) self.wireframeEnabled = 0 @@ -2257,8 +2394,8 @@ class ShowBase(DirectObject.DirectObject): def enableMouse(self): """ - Reverse the effect of a previous call to disableMouse(). - useDrive() also implicitly enables the mouse. + Reverse the effect of a previous call to `disableMouse()`. + `useDrive()` also implicitly enables the mouse. """ if self.mouse2cam: self.mouse2cam.reparentTo(self.mouseInterface) @@ -2266,14 +2403,14 @@ class ShowBase(DirectObject.DirectObject): def silenceInput(self): """ This is a heavy-handed way of temporarily turning off - all inputs. Bring them back with reviveInput(). + all inputs. Bring them back with `reviveInput()`. """ if not self.__deadInputs: self.__deadInputs = taskMgr.remove('dataLoop') def reviveInput(self): """ - Restores inputs after a previous call to silenceInput. + Restores inputs after a previous call to `silenceInput()`. """ if self.__deadInputs: self.eventMgr.doEvents() @@ -2288,7 +2425,7 @@ class ShowBase(DirectObject.DirectObject): def changeMouseInterface(self, changeTo): """ - Switch mouse action + Change the mouse interface used to control the camera. """ # Get rid of the prior interface: self.mouseInterface.detachNode() @@ -2303,7 +2440,7 @@ class ShowBase(DirectObject.DirectObject): def useDrive(self): """ - Switch mouse action to drive mode + Changes the mouse interface used for camera control to drive mode. """ if self.drive: self.changeMouseInterface(self.drive) @@ -2313,14 +2450,16 @@ class ShowBase(DirectObject.DirectObject): def useTrackball(self): """ - Switch mouse action to trackball mode + Changes the mouse interface used for camera control to trackball mode. """ if self.trackball: self.changeMouseInterface(self.trackball) def toggleTexMem(self): - """ Toggles a handy texture memory watcher. See TexMemWatcher - for more information. """ + """ + Toggles a handy texture memory watcher utility. + See :mod:`direct.showutil.TexMemWatcher` for more information. + """ if self.texmem and not self.texmem.cleanedUp: self.texmem.cleanup() @@ -2386,7 +2525,6 @@ class ShowBase(DirectObject.DirectObject): self.showVertices = self.cam.attachNewNode(cam) dr.setCamera(self.showVertices) - def oobe(self, cam = None): """ Enable a special "out-of-body experience" mouse-interface @@ -2397,12 +2535,12 @@ class ShowBase(DirectObject.DirectObject): mouse events, if needed, may be sent to the normal node by holding down the Control key. - This is different than useTrackball(), which simply changes + This is different than `useTrackball()`, which simply changes the existing mouse action to a trackball interface. In fact, - OOBE mode doesn't care whether useDrive() or useTrackball() is + OOBE mode doesn't care whether `useDrive()` or `useTrackball()` is in effect; it just temporarily layers a new trackball interface on top of whatever the basic interface is. You can - even switch between useDrive() and useTrackball() while OOBE + even switch between `useDrive()` and `useTrackball()` while OOBE mode is in effect. This is a toggle; the second time this function is called, it @@ -2594,8 +2732,7 @@ class ShowBase(DirectObject.DirectObject): generated by makeCubeMap(), namePrefix should contain the hash mark ('#') character. - The return value is the filename if successful, or None if - there is a problem. + :returns: The filename if successful, or None if there is a problem. """ if source == None: @@ -2633,15 +2770,14 @@ class ShowBase(DirectObject.DirectObject): the current scene, one in each of the six cube map directions. This requires rendering a new frame. - Unlike screenshot(), source may only be a GraphicsWindow, + Unlike `screenshot()`, source may only be a GraphicsWindow, GraphicsBuffer, or DisplayRegion; it may not be a Texture. camera should be the node to which the cubemap cameras will be parented. The default is the camera associated with source, if source is a DisplayRegion, or base.camera otherwise. - The return value is the filename if successful, or None if - there is a problem. + :returns: The filename if successful, or None if there is a problem. """ if source == None: @@ -2703,8 +2839,7 @@ class ShowBase(DirectObject.DirectObject): texture and because they are supported on a broader range of hardware. - The return value is the filename if successful, or None if there - is a problem. + :returns: The filename if successful, or None if there is a problem. """ if source == None: source = self.win @@ -2875,7 +3010,7 @@ class ShowBase(DirectObject.DirectObject): def adjustWindowAspectRatio(self, aspectRatio): """ This function is normally called internally by - windowEvent(), but it may also be called to explicitly adjust + `windowEvent()`, but it may also be called to explicitly adjust the aspect ratio of the render/render2d DisplayRegion, by a class that has redefined these. """ @@ -2959,6 +3094,10 @@ class ShowBase(DirectObject.DirectObject): self.finalizeExit() def finalizeExit(self): + """ + Called by `userExit()` to quit the application. The default + implementation just calls `sys.exit()`. + """ sys.exit() # [gjeon] start wxPython @@ -3033,9 +3172,9 @@ class ShowBase(DirectObject.DirectObject): self.taskMgr.step() def wxRun(self): - """ This method replaces base.run() after we have called - spawnWxLoop(). Since at this point wxPython now owns the main - loop, this method is a call to wxApp.MainLoop(). """ + """ This method replaces `run()` after we have called `spawnWxLoop()`. + Since at this point wxPython now owns the main loop, this method is a + call to wxApp.MainLoop(). """ if Thread.getCurrentThread().getCurrentTask(): # This happens in the p3d environment during startup. @@ -3117,9 +3256,9 @@ class ShowBase(DirectObject.DirectObject): self.tkRoot.after(self.tkDelay, self.__tkTimerCallback) def tkRun(self): - """ This method replaces base.run() after we have called - spawnTkLoop(). Since at this point Tkinter now owns the main - loop, this method is a call to tkRoot.mainloop(). """ + """ This method replaces `run()` after we have called `spawnTkLoop()`. + Since at this point Tkinter now owns the main loop, this method is a + call to tkRoot.mainloop(). """ if Thread.getCurrentThread().getCurrentTask(): # This happens in the p3d environment during startup. @@ -3146,6 +3285,11 @@ class ShowBase(DirectObject.DirectObject): return None def getAxes(self): + """ + Loads and returns the ``models/misc/xyzAxis.bam`` model. + + :rtype: panda3d.core.NodePath + """ return loader.loadModel("models/misc/xyzAxis.bam") def __doStartDirect(self):