You can use MenuItem.Checked to add and remove a checkmark from a menu item.
Tag Archives: menus
Saturday Snippet: Getting the object under the mouse in a context menu callback
For most context menus, the Target attribute contains both the selected objects (if any) and the object under the mouse.
def MyCustomMenu_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.Filter = "camera" oMenu.AddCallbackitem("Custom Camera Tool","MyCameraTool") return true def MyCameraTool(in_ctxt): obj = in_ctxt.GetAttibute("Target") Application.LogMessage(obj)
I’m pretty sure I’m the one who dug up that info and put it in the docs (on the Menu Item Callback page). I did not, however, write this bit, which to my ear does not sound good at all:
If your menu is attached to a contextual menu, the currently selected objects are passed in to your callback. The target object under the cursor is also passed in as part of the selected objects. However if no objects are selected, then only the target is passed in. The objects can be retrieved through the Context.GetAttribute method with “Target” specified as the value for the AttributeName parameter. The selected/target objects are not passed in to the callback of a custom menu item attached to a regular menu.
I prefer something more like this:
For context menus, the callback gets the currently selected objects and the object under the mouse. You can get these target objects from the Target attribute with Context.GetAttribute.
Getting the ICE tree view from a menu callback
How do you get the ICE Tree view in a menu callback? For example, if you add a menu item to the ICE Tree > User Tools, how does the menu item callback get the ICE Tree view?
The answer is actually in code I posted before, but that was in a blog post titled Getting the selected ICE nodes. So, with that title, you wouldn’t necessarily think to look there.
So what’s the answer? Uses Context.GetAttribute( “Target” ). For custom menus in the views like the ICE Tree view, the Fcurve Editor, and the Material Manager, the Target attribute is the View object. And once you have the View object, you can get the View attributes.
# # Callback added to the menu item with Menu.AddCallbackItem # def My_menuItem_Callback( in_ctxt ): # Get the ICE Tree view oView = in_ctxt.GetAttribute("Target") # LogMessage( 'View: ' + oView.Name ) # get the selected nodes nodes = oView.GetAttributeValue('selection') LogMessage( 'Selected nodes: ' + nodes )
Soapbox alert…
This post illustrates why indexes are a good thing…with them, you can find information no matter what page or heading contains the information.
For ICE trees, you’d have index entries something like this:
- ICE tree
- view attributes
- target
- container
- selected nodes, getting
- view, getting
- ICETree node, getting
- view attributes
Selecting the object master for a clone
Here’s a little addon that adds a Select Clone Object Master command to the viewport context menu for 3d objects.
The addon is a single self-installed plugin that includes a command, a menu, and a filter:
- The menu item calls the command.
- The filter controls whether or not the menu item is enabled…so that the Select Clone Object Master command is enabled only when you ALT+right click a clone.
# SelectCloneMasterObjectPlugin # Initial code generated by Softimage SDK Wizard # Executed Thu Jun 7 10:55:31 EDT 2012 by blairs # # Tip: To add a command to this plug-in, right-click in the # script editor and choose Tools > Add Command. import win32com.client from win32com.client import constants null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "blairs" in_reg.Name = "SelectCloneMasterObjectPlugin" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterCommand("SelectCloneMasterObject","SelectCloneMasterObject") in_reg.RegisterFilter("Clone",constants.siFilter3DObject) in_reg.RegisterMenu(constants.siMenu3DViewObjectSelectContextID,"SelectCloneMasterObject_Menu",false,false) #RegistrationInsertionPoint - do not remove this line return true def XSIUnloadPlugin( in_reg ): strPluginName = in_reg.Name Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose) return true # Match callback for the CloneFilter custom filter. def Clone_Match( in_ctxt ): Application.LogMessage("Clone_Match called",constants.siVerbose) o = in_ctxt.GetAttribute( "Input" ) c = win32com.client.Dispatch( "XSI.Collection" ) c.Items = '%s.%s' % (o.ActivePrimitive.FullName, 'CopyOp') return c.Count > 0 # Return value indicates if the input object matches the filter criterias. def SelectCloneMasterObject_Init( in_ctxt ): oCmd = in_ctxt.Source oCmd.Description = "" oCmd.ReturnValue = true oArgs = oCmd.Arguments # oArgs.AddWithHandler("Arg0","Collection") oArgs.AddWithHandler("Arg1","SingleObj") return true def SelectCloneMasterObject_Execute( Arg1 ): Application.LogMessage("SelectCloneMasterObject_Execute called",constants.siVerbose) Application.Selection.Clear() # by Vladimir Jankijevic # https://groups.google.com/forum/?fromgroups#!searchin/xsi_list/Finding$20the$20source$20mesh$20of$20a$20clone/xsi_list/cyUYARDMooA/J3JVxc6jJtIJ copyop = Arg1.ActivePrimitive.ConstructionHistory[0] Application.Selection.Add(copyop.InputPorts[0].Target2.Parent3DObject) # # TODO: Put your command implementation here. # return true def SelectCloneMasterObject_Menu_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.AddCommandItem("Select Clone Master Object","SelectCloneMasterObject") oMenu.Filter = "Clone" return true
New in Softimage 2013: Getting the selected materials in the Material Manager
In 2013, you can use the selection view attribute to get the materials that are selected in the Material Manager.
Here’s a python custom menu item that shows how to do it. In summary, you do this:
- Add a custom menu in the Manager Manager
- Use a callback item, so you can get the view from the context
- Use selection view attribute to get the names of the selected materials
import win32com.client from win32com.client import constants null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "blairs" in_reg.Name = "MaterialsManagerPlugin" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterMenu(constants.siMenuMaterialManagerTopLevelID,"Custom_Tools",false,false) #RegistrationInsertionPoint - do not remove this line return true def XSIUnloadPlugin( in_reg ): strPluginName = in_reg.Name Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose) return true def Custom_Tools_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.AddCallbackItem("Get Selected Materials","OnGetSelected") return true def OnGetSelected( c ): view = c.GetAttribute( "Target" ) Application.LogMessage( view ) Application.LogMessage( view.GetAttributeValue( "selection" ) ) for mat in view.GetAttributeValue( "selection" ).split(","): Application.LogMessage( mat ) return true
Finding the menu commands added by a plugin
So you installed a plugin, but now you cannot find out how to access the plugin in Softimage.
If the plugin added a menu command, and it’s a scripted plugin, we can find it by checking the plugin code (in the Plugin Manager > Tree, right-click the plugin and click Edit).
Find the definition of XSILoadPlugin.
In the XSILoadPlugin function, look for any calls to RegisterMenu.
def XSILoadPlugin( in_reg ): #{{{ in_reg.Author = "kim" in_reg.Name = "EPSexportPlugin" in_reg.Email = "" in_reg.URL = "" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterProperty("EPSexport") in_reg.RegisterMenu(constants.siMenuMainFileExportID,"EPSexport_Menu",false,false) # register the export command # KA_EpsExport( Application.Selection, OutputFile, CullBackFaces, doInnerLines, doBorderLines, InnerLineThickness, BorderLineThickness, AutoDiscontinuity, Xres ) in_reg.RegisterCommand("KA_EpsExport","KA_EpsExport") return true
RegisterMenu uses what’s called a “menu anchor” to define a new menu command. In this example, the menu anchor is siMenuMainFileExportID.
Google the menu anchor or search the SDK docs, and you’ll find a page that describes the menu anchors:
Scripting – Getting the target in a context menu callback
If you use AddCallbackItem to implement a contextual menu, then you can get the objects to which the context menu applies. A menu item callback gets a Context object from Softimage, and that Context contains a Target context attribute. Target specifies the selected objects, or the object under the mouse:
- If more than one object is selected, then the Target attribute is a collection of all selected objects.
- Otherwise, the Target attribute is a collection that contains just the object under the mouse.
Here’s a Python example of a context menu implemented with AddCallbackItem.
import win32com.client from win32com.client import constants null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "blairs" in_reg.Name = "Test_CommandPlugin" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterCommand("Test_Command","Test_Command") in_reg.RegisterMenu(constants.siMenuSEModelContextID,"Model_Context_Menu",false,false) in_reg.RegisterMenu(constants.siMenuSEObjectContextID,"Object_Context_Menu",false,false) #RegistrationInsertionPoint - do not remove this line return true def XSIUnloadPlugin( in_reg ): strPluginName = in_reg.Name Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose) return true def Model_Context_Menu_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.AddCallbackItem( "Log target model", "SE_ContextCallback" ) return true def Object_Context_Menu_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.AddCallbackItem( "Log target object", "SE_ContextCallback" ) return true # # Menu item callback # def SE_ContextCallback( in_ctxt ): target = in_ctxt.GetAttribute("Target") # Target attribute returns an XSICollection for o in target: Application.LogMessage( o.FullName )