__all__ = ['ClickBehaviorCustom', 'instantiate']
from ActionRegistry import theActionRegistry
from MessageInterpreter import MessageInterpreter
from RTFapi import Event, Node, kScene
from SceneGraphUtilities import GetIntersectionData
from UserCustomization import UserCustomBase, CustomInfo
import BehaviorIO, ModelIO
kClickKeyMappingId = 'ClickBehavior'
class ClickBehaviorCustom (UserCustomBase):
def __init__(self):
self.__myClickMenu = None
self.__myClickId = None
self.__myInterpreter = ClickBehaviorInterpreter()
def getInterpreter(self,isInteractive):
if isInteractive:
return self.__myInterpreter
return None
def appendMenuItems(self,id,menu):
if "Help" == id:
self.__myClickMenu = menu
self.__myClickId = \
menu.appendCheckItem(_( 'Click behaviors\tCtrl+P' ),
self.__onClickedObject )
theActionRegistry.register( 'Global',
Event.BUTTON_p,
( Event.BUTTON_Control, ),
True,
Event.BUTTONUP,
'ClickBehaviorObjectMode' )
def enableMenuStates(self,id,enableStates):
if "Help" == id:
enableStates[self.__myClickId] = True
def resetMenuStates(self, id):
if "Help" == id:
menuItemStates = {}
menuItemStates[self.__myClickId] = False
self.__myClickMenu.checkMenuItems(menuItemStates)
def __onClickedObject( self, event ):
isOn = bool(self.__myClickMenu.IsChecked(self.__myClickId))
self.__myInterpreter.ClickBehaviorObjectMode( isOn )
class ClickBehaviorInterpreter( MessageInterpreter ):
def __init__( self ):
MessageInterpreter.__init__( self )
self.__myDisplay = None
self.__myModels = None
self.__myBehaviors = None
self.__myIsClicking = False
keyMappings = (
(Event.BUTTON_LMB, (Event.BUTTON_Control,),
True, Event.BUTTONDOWN, "MyClickBehaviorObjectStart"),
(Event.BUTTON_MMB, (Event.BUTTON_Control,),
True, Event.BUTTONDOWN, "MyClickBehaviorObjectStop"),
(Event.BUTTON_RMB, (Event.BUTTON_Control,),
True, Event.BUTTONDOWN, "MyClickBehaviorObjectReset"),
)
theActionRegistry.registerList(kClickKeyMappingId, keyMappings)
def __getHitPath( self, event, modelRoot, display ) :
'''
Returns a list of nodes from the node that was clicked on,
to the root node of the model. Any one of these nodes
could be associated with a light.
'''
x = event.getValue( Event.kNormalizedWinX )
y = event.getValue( Event.kNormalizedWinY )
intersector = display.createIntersector( kScene )
intersector.intersect( x, y )
(path,node,isp,norm,patch,dist) = GetIntersectionData( intersector,
modelRoot,
conditions = [lambda node: node.hasProperty( Node.kIsSelectable )],
needPatchInfo=False,
filterCut=False)
return path
def MyClickBehaviorObjectStart(self, event ):
self.MyClickBehaviorObjectDo(event, 1)
def MyClickBehaviorObjectStop(self, event ):
self.MyClickBehaviorObjectDo(event, 0)
def MyClickBehaviorObjectReset(self, event ):
self.MyClickBehaviorObjectDo(event, -1)
def MyClickBehaviorObjectDo(self, event, startOrStopOrReset):
'''
Shows all lights that are illuminating the clicked-on
object. If all applicable lights are already on, then
nothing is done.
'''
if self.__myDisplay is None or \
self.__myModels is None or \
self.__myBehaviors is None:
return False
pathToClickedNode = self.__getHitPath( event, self.__myModels.root,
self.__myDisplay )
if pathToClickedNode is not None:
"""
print "Hit: %d" % (len(pathToClickedNode))
for each in pathToClickedNode :
print " hit %s" % each.getUniqueId()
"""
for each in pathToClickedNode:
if self.ProcessNode(each, startOrStopOrReset):
break
return True
def ProcessNode( self, node, startOrStopOrReset ):
id = node.getUniqueId()
for name, behavior in self.__myBehaviors.iteritems():
nodes = behavior.getParameterValue( 'Nodes' )
nodesList = behavior.getParameterValue( 'NodesList' )
if (nodes is not None and id in nodes) or \
(nodesList is not None and id in nodesList):
"""
print "Start behavior %s" % name
"""
if 1 == startOrStopOrReset:
self.sendMessage( "BEHAVIOR_METHOD_EXECUTE",
( name, "Continue", ) )
elif 0 == startOrStopOrReset:
self.sendMessage( "BEHAVIOR_METHOD_EXECUTE",
( name, "Pause", ) )
else:
self.sendMessage( "BEHAVIOR_METHOD_EXECUTE",
( name, "StopAndResetToStart", ) )
def ClickBehaviorObjectMode( self, isOn ):
if self.__myDisplay and self.__myModels and self.__myBehaviors :
if isOn != self.__myIsClicking:
self.__myIsClicking = isOn
if isOn :
theActionRegistry.addSetToStack(kClickKeyMappingId)
else:
theActionRegistry.removeSetFromStack(kClickKeyMappingId)
theActionRegistry.activateSet( kClickKeyMappingId,
self.__myIsClicking )
def APPLICATION_CLOSE_SCENE( self, message ) :
self.ClickBehaviorObjectMode( False )
self.__myModels = None
self.__myBehaviors = None
def SET_DOCUMENT( self, message ) :
self.ClickBehaviorObjectMode( False )
( document, ) = message.data
self.__myModels = document.get( ModelIO.id )
self.__myBehaviors = document.get( BehaviorIO.id )
def SET_DISPLAY( self, message ):
( self.__myDisplay, ) = message.data
def instantiate():
return ClickBehaviorCustom()
def info():
customInfo = CustomInfo()
customInfo.vendor = 'Autodesk'
customInfo.version = '1.0'
customInfo.api = '2013'
customInfo.shortInfo = "A sample add-in to switch the mouse click's behavior."
customInfo.longInfo = \
"""Use Ctrl-P to get into a mode where the left mouse button click on an \
object with an assigned behavior starts the behavior, the middle \
mouse button click pauses and the right mouse button click resets it.
"""
return customInfo