disabling/enabling mouse controlled camera movement

OMG, this thing is shaking my head again.

Showbase.py v.1.3.2 :

def disableMouse(self):
    """
    Temporarily disable the mouse control of the camera, either
    via the drive interface or the trackball, whichever is
    currently in use.
    """
    # We don't reparent the drive interface or the trackball;
    # whichever one was there before will remain in the data graph
    # and active.  This way they won't lose button events while
    # the mouse is disabled.  However, we do move the mouse2cam
    # object out of there, so we won't be updating the camera any
    # more.
    if self.mouse2cam:
        self.mouse2cam.reparentTo(self.dataUnused)

def enableMouse(self):
    """
    Reverse the effect of a previous call to disableMouse().
    useDrive() also implicitly enables the mouse.
    """
    if self.mouse2cam:
        self.mouse2cam.reparentTo(self.mouseInterface)

Why would one need button events while it’s disabled ? Is there any such case possible ?
Doesn’t by disabling the mouse, one want to block any mouse (& keyboard) buttons responsible for camera movement?
I couldn’t figure it out.
Obviously this does the job :

def disableMouse2Cam(self):
    base.mouseInterface.detachNode()

def enableMouse2Cam(self):
    base.mouseInterface.reparentTo(base.mouseWatcher)

Try this simple scene :

import direct.directbase.DirectStart
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import sys

class World(DirectObject):
  def __init__(self):
      self.mouseActive=0
      self.mouseStdSG=1
      self.mouseState=['disableMouse2Cam','enableMouse2Cam']
      self.mouseStateTextList=['disabled','enabled']
      self.mouseSGTextList=['ALTERED','Showbase STANDARD']
      self.accept('escape',sys.exit)
      self.accept('mouse1',self.clickOn,[1])
      self.accept('mouse1-up',self.clickOn,[0])
      self.accept('mouse2',self.clickOn,[1])
      self.accept('mouse2-up',self.clickOn,[0])
      self.accept('mouse3',self.clickOn,[1])
      self.accept('mouse3-up',self.clickOn,[0])
      self.accept('space',self.toggleMouseActive,[1])
      self.accept('enter',self.toggleMouseSceneGraph)

      self.clickText=OnscreenText(text = '', pos = (0,.45), scale=.06, fg=(1,1,1,1), shadow=(0,0,0,1),mayChange=1)
      self.notifText=OnscreenText(text = '', pos = (0,-.45), scale=.06, fg=(1,1,1,1), shadow=(0,0,0,1),mayChange=1)
      self.mouseStateText=OnscreenText(text = '', pos = (0,-.95), fg=(1,1,1,1), shadow=(0,0,0,1),mayChange=1)
      SGtext='[enter] : Scene Graph [%s]' %self.mouseSGTextList[self.mouseStdSG]
      self.mouseSGText=OnscreenText(text = SGtext, pos = (0,-.85), fg=(1,1,1,1), shadow=(0,0,0,1),mayChange=1)
      self.toggleMouseActive(0)

      smiley=loader.loadModel('smiley')
      smiley.reparentTo(render)
      base.cam.setY(-10)
      base.mouseInterfaceNode.setForwardScale(.05)

  def disableMouse2Cam(self,x):
      if self.mouseStdSG:
         base.disableMouse()
      else:
         base.mouseInterface.detachNode()
      self.notifText.setText("now while it's disabled,\nuse the mouse to move/rotate/zoom the camera,\njust like it's enabled,\nand enable it back to see the result")

  def enableMouse2Cam(self,textOn):
      if self.mouseStdSG:
         base.enableMouse()
         if textOn: self.notifText.setText('what happened ???')
      else:
         base.mouseInterface.reparentTo(base.mouseWatcher)
         if textOn: self.notifText.setText('stays still :D')

  def toggleMouseActive(self,textOn):
      self.mouseActive=not self.mouseActive
      getattr(self, self.mouseState[self.mouseActive])(textOn)
      self.mouseStateText.setText('[space] : mouse state [%s]' %self.mouseStateTextList[self.mouseActive])

  def toggleMouseSceneGraph(self):
      if not self.mouseActive:
         return
      self.mouseStdSG=not self.mouseStdSG
      self.mouseSGText.setText('[enter] : Scene Graph [%s]' %self.mouseSGTextList[self.mouseStdSG])
      self.notifText.setText('')

  def clickOn(self,state):
      if state:
         self.clickText.setText('CLICK !!')
      else:
         self.clickText.setText('')

World()
run()

I think the comment is referring to the button “up” events. If the user is holding down the mouse button while you reparent the trackball object out of the data graph, and the user releases the mouse button later, the trackball object will not see the button release, and will believe the button is still held down. This is only a problem if you later reparent the trackball back into the data graph and want to use it, of course.

David

The problem I see here is that disabling the mouse does NOT suppress camera movement at all. As long as mouseInterface is still under mouseWatcher (when disabled), the camera’s transform will keep updated, and the transform will be applied on the next enableMouse(). I’m wondering why it’s designed that way, because I’m not sure which probability is bigger than the other :

  1. the user is holding down the mouse button while reparent the trackball object out of the data graph, and the user releases the mouse button later, OR
  2. the usage of mouse disable/enable to block mouse-camera relationship when the user need to use the mouse for something else.

An excellent point. I think the original intention was always to reset the trackball/drive interface to a known position (specifically, the current camera position) when it is re-enabled, but it is possible the code to do that has been lost over the years.

In any case, I don’t think much thought was put into it originally. You certainly raise some persuasive arguments that it makes more sense to remove the interface node altogether.

David

As you can see.
I just did what I need.
Thanks.