__all__ = ['StereoCustom', 'instantiate']
from MessageRegistry import theMessageRegistry
from MessageInterpreter import MessageInterpreter
from ActionRegistry import theActionRegistry
from UserCustomization import UserCustomBase, CustomInfo
from RTFapi import Event, Display, SystemInformation
from RunInUiThread import RunInUiThread
from DisplayUtilities import GetCameras, GetViewStates
import math
STEREO_CAMERA_Doc = \
[(
"""
Enable or disable stereo.
"""
),
[[("enable"),("True to turn it on, False to turn it off.")],
]
]
theMessageRegistry.register("STEREO_CAMERA",
(bool,), 0, STEREO_CAMERA_Doc)
STEREO_CAMERA_AUTO_ADJUST_Doc = \
[(
"""
Automatically adjust the eye distance for stereo.
"""
),
[[("autoDistanceAdjust"),("Automatically adjust the eye spacing based on distance. If true, it is set and the factor specified is used. If false, it is unset and the following argument is not used.")],
[("autoDistanceAdjustFactor"),("Factor for the automatic adjustment")],
]
]
theMessageRegistry.register("STEREO_CAMERA_AUTO_ADJUST",
(bool,float), 0, STEREO_CAMERA_AUTO_ADJUST_Doc)
STEREO_CAMERA_EYE_DISTANCE_Doc = \
[(
"""
Automatically turns off the automatic eye distance setting and sets it to specified value.
"""
),
[[("distance"),("The eye distance to use")],
]
]
theMessageRegistry.register("STEREO_CAMERA_EYE_DISTANCE",
(bool,float), 0, STEREO_CAMERA_EYE_DISTANCE_Doc)
STEREO_CAMERA_FOCUS_DISTANCE_Doc = \
[(
"""
Set or reset the focus distance.
"""
),
[[("reset"),("If true, the distance value is ignored and instead the distance is set to half way between near and far clipping planes.")],
[("distance"),("Focus distance to use.")],
]
]
theMessageRegistry.register("STEREO_CAMERA_FOCUS_DISTANCE",
(bool,float), 0, STEREO_CAMERA_FOCUS_DISTANCE_Doc)
STEREO_ADJUST_PARAMETERS_MODE_Doc = \
[(
"""
Enable or disable eye distance adjustment for stereo. When enabled,
left mouse button will change the eye distance.
"""
),
[[("state"),("True to enable and False to disable")],
]
]
theMessageRegistry.register("STEREO_ADJUST_PARAMETERS_MODE",
(bool,), 0, STEREO_ADJUST_PARAMETERS_MODE_Doc)
class StereoCustom (UserCustomBase):
def __init__(self):
Display.setEnableStereoFormat()
SystemInformation.instance().setDisplayDevice("VirtualDeviceGL",True)
SystemInformation.instance().setDisableThemeSwitch(True)
self.__myCallIdStereo = None
self.__myCallIdAdjust = None
self.__myCallIdReset = None
self.__myFirstTime = True
self.__myInterp = LocalInterp()
def getInterpreter(self,isInteractive):
if isInteractive:
return self.__myInterp
return None
def appendMenuItems(self,id,menu):
if "View" == id:
self.__myMenu = menu
menu.appendSeparator()
self.__myCallIdStereo = \
menu.appendCheckItem(_( 'Stereo Mode' ),
self.__onCameraStereo )
self.__myCallIdAdjust = \
menu.appendCheckItem(_( 'Stereo Adjust' ),
self.__onCameraAdjust)
self.__myCallIdReset = \
menu.appendItem(_( 'Stereo Reset' ),
self.__onCameraReset)
def enableMenuStates(self,id,enableStates):
if "View" == id:
stereoOn = bool(self.__myMenu.IsChecked(self.__myCallIdStereo))
adjustOn = bool(self.__myMenu.IsChecked(self.__myCallIdAdjust))
enableStates[self.__myCallIdStereo] = not adjustOn
enableStates[self.__myCallIdAdjust] = stereoOn
enableStates[self.__myCallIdReset] = stereoOn
def resetMenuStates(self, id):
if "View" == id:
menuItemStates = {}
menuItemStates[self.__myCallIdAdjust] = False
menuItemStates[self.__myCallIdStereo] = False
self.__myMenu.checkMenuItems(menuItemStates)
def __onCameraStereo( self, event ):
isOn = bool(self.__myMenu.IsChecked(self.__myCallIdStereo))
self.__myInterp.sendMessage( "STEREO_CAMERA", (isOn, ) )
if self.__myFirstTime:
self.__onCameraReset( event )
self.__myFirstTime = False
RunInUiThread( self.__myMenu.updateMenu )
def __onCameraAdjust( self, event ):
isOn = bool(self.__myMenu.IsChecked(self.__myCallIdAdjust))
self.__myInterp.sendMessage("STEREO_ADJUST_PARAMETERS_MODE", (isOn,))
RunInUiThread( self.__myMenu.updateMenu )
def __onCameraReset( self, event ):
self.__myInterp.sendMessage( "STEREO_CAMERA_AUTO_ADJUST",(True,0.03) )
self.__myInterp.sendMessage( "STEREO_CAMERA_FOCUS_DISTANCE",(True,1.0))
class LocalInterp( MessageInterpreter ):
__kFactorStartId = "FactorStart"
__kFactorId = "Factor"
__kFocusStartId = "FocusStart"
__kFocusId = "Focus"
def __init__( self ):
MessageInterpreter.__init__( self )
self.__myDisplay = None
self.__myFactor = 0.03
self.__myFocus = 80.0
self.__myLastPosition = (0.0, 0.0)
self.__myFirstTime = True
keyMappings = (
(Event.BUTTON_LMB, (), True, Event.BUTTONDOWN, "MyFactorStart"),
)
theActionRegistry.registerList(LocalInterp.__kFactorStartId,
keyMappings)
keyMappings = (
(Event.BUTTON_LMB, (), False, Event.BUTTONUP, "MyFactorStop"),
(Event.BUTTON_None, (), False, Event.MOVE, "MyFactor")
)
theActionRegistry.registerList(LocalInterp.__kFactorId,
keyMappings)
keyMappings = (
(Event.BUTTON_MMB, (), True, Event.BUTTONDOWN, "MyFocusStart"),
)
theActionRegistry.registerList(LocalInterp.__kFocusStartId,
keyMappings)
keyMappings = (
(Event.BUTTON_MMB, (), False, Event.BUTTONUP, "MyFocusStop"),
(Event.BUTTON_None, (), False, Event.MOVE, "MyFocus")
)
theActionRegistry.registerList(LocalInterp.__kFocusId,
keyMappings)
def __getMainCamera( self ):
return self.__myDisplay.getCamera() if self.__myDisplay else None
def SET_DISPLAY(self, message):
(self.__myDisplay,) = message.data
camera = self.__getMainCamera()
if camera:
self.__myFocus = camera.getFocusDistance()
def APPLICATION_CLOSE_SCENE(self, message):
theActionRegistry.removeSetFromStack(LocalInterp.__kFactorId)
theActionRegistry.removeSetFromStack(LocalInterp.__kFactorStartId)
self.sendMessage( "STEREO_CAMERA", (False, ) )
def STEREO_CAMERA( self, message ):
if self.__myDisplay is None:
return
(enable,) = message.data
if enable:
self.__myDisplay.enableStereo()
self.__messageInfo()
else:
self.__myDisplay.disableStereo()
def STEREO_CAMERA_AUTO_ADJUST( self, message ):
(autoAdjust,factor) = message.data
for viewstate in GetViewStates( self.__myDisplay ):
viewstate.setStereoAutomaticEyeDistanceAdjustment( autoAdjust )
viewstate.setStereoAutomaticEyeDistanceFactor( factor )
def STEREO_CAMERA_EYE_DISTANCE( self, message ):
(dist,) = message.data
for viewstate in GetViewStates( self.__myDisplay ):
viewstate.setStereoAutomaticEyeDistanceAdjustment( False )
viewstate.setStereoEyeDistance( dist )
def STEREO_CAMERA_FOCUS_DISTANCE( self, message ):
(reset,dist) = message.data
for camera in GetCameras( self.__myDisplay ):
if reset:
dist = 0.5 * (camera.getNearClip()+ camera.getFarClip())
camera.setFocusDistance( dist )
camera = self.__getMainCamera()
if camera:
self.__myFocus = camera.getFocusDistance()
def STEREO_ADJUST_PARAMETERS_MODE(self, message):
(isOn,) = message.data
if isOn:
theActionRegistry.addSetToStack(LocalInterp.__kFactorStartId)
theActionRegistry.addSetToStack(LocalInterp.__kFocusStartId)
self.__message()
else:
theActionRegistry.removeSetFromStack(LocalInterp.__kFactorStartId)
theActionRegistry.removeSetFromStack(LocalInterp.__kFocusStartId)
theActionRegistry.activateSet(LocalInterp.__kFactorStartId, isOn)
theActionRegistry.activateSet(LocalInterp.__kFocusStartId, isOn)
def NAVIGATION_POSITION(self, message):
(nav,) = message.data
p = nav.getPosition()
la = nav.getLookAt()
coi = nav.getCOI()
d = (p[0]-la[0],p[1]-la[1],p[2]-la[2])
self.__myFocus = math.sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2])
for camera in GetCameras( self.__myDisplay ):
camera.setFocusDistance( self.__myFocus )
def __message(self):
self.sendMessage( "STATUSBAR_SET_TEXT",
("LMB - offset (%f), MMB - focus (%f)" % \
(self.__myFactor, self.__myFocus),) )
def __messageInfo(self):
self.sendMessage( "STATUSBAR_SET_TEXT",
("Offset (%f), Focus (%f)" % \
(self.__myFactor, self.__myFocus),) )
def __getPosition(self, event):
x = event.getValue(Event.kNormalizedWinX)
y = event.getValue(Event.kNormalizedWinY)
return x, y
def MyFactorStart(self, event):
if self.__myDisplay is None:
return False
self.__myLastPosition = self.__getPosition(event)
theActionRegistry.addSetToStack(LocalInterp.__kFactorId)
theActionRegistry.activateSet(LocalInterp.__kFactorId, True)
return True
def MyFactor(self, event):
x, y = self.__getPosition(event)
lastX, lastY = self.__myLastPosition
self.__myLastPosition = x, y
self.__myFactor += (x - lastX) + (y - lastY)
self.__message()
self.sendMessage( "STEREO_CAMERA_AUTO_ADJUST", (True,self.__myFactor) )
return True
def MyFactorStop(self, event):
theActionRegistry.removeSetFromStack(LocalInterp.__kFactorId)
theActionRegistry.activateSet(LocalInterp.__kFactorId, False)
return True
def MyFocusStart(self, event):
if self.__myDisplay is None:
return False
self.__myLastPosition = self.__getPosition(event)
theActionRegistry.addSetToStack(LocalInterp.__kFocusId)
theActionRegistry.activateSet(LocalInterp.__kFocusId, True)
return True
def MyFocus(self, event):
x, y = self.__getPosition(event)
lastX, lastY = self.__myLastPosition
self.__myLastPosition = x, y
self.__myFocus += 10*((x - lastX) + (y - lastY))
self.__message()
self.sendMessage("STEREO_CAMERA_FOCUS_DISTANCE",(False,self.__myFocus))
return True
def MyFocusStop(self, event):
theActionRegistry.removeSetFromStack(LocalInterp.__kFocusId)
theActionRegistry.activateSet(LocalInterp.__kFocusId, False)
return True
def instantiate():
return StereoCustom()
def info():
customInfo = CustomInfo()
customInfo.vendor = 'Autodesk'
customInfo.version = '5.0'
customInfo.api = '2013'
customInfo.shortInfo = "View in OpenGL stereo mode."
customInfo.longInfo = \
"""Go into stereo mode, specifying eye distance or automatic eye distance based on the focal point. \
To get true stereo, it requires enabling the support in the driver and Showcase Professional license. It will switch Showcase into OpenGL mode, rather than the default DirectX.
"""
return customInfo