0

I have a plugin running inside Maya that needs to perform an 'eye dropper' test against objects in the scene. My Plugin is running as a hosted WPF control, so I have a C# button event callback that wants to operate in a modal fashion until the hit is performed or escape is pressed. This was really easy to do in 3D Studio Max, but I cannot find out how to do this in Maya.

Any advice?

Steven
  • 619
  • 5
  • 24

1 Answers1

2

I do miss that in 3dsMax, but as far as I know, no, there's no built-in functionality to do that.

Most tools in Maya work already having a selection before execution so then the tool can use cmds.ls(sl=True) to capture the selection and preform your validation.

What you can do is mimic an object picker by using a selection callback. There's cmds.scriptJob, but it's more efficient to use OpenMaya's callbacks. Here's an example that uses a class to store the callback's id and auto-manages it:

import maya.cmds as cmds
import maya.OpenMaya as OpenMaya


class ObjectPicker():

    _id = None  # Store callback's id here.

    def __init__(self):
        # When this class is created, add the callback.
        OpenMaya.MGlobal.displayWarning("Please pick an object")
        ObjectPicker.add_callback()

    @staticmethod
    def on_selection_changed(*args):
        # This gets triggered from the callback when the user changes the selection.
        # Auto-remove the callaback afterwards.
        print "Selection:", cmds.ls(sl=True)
        ObjectPicker.remove_callback()

    @staticmethod
    def add_callback():
        # First remove any existing callback, then store the id in this class.
        ObjectPicker.remove_callback()
        ObjectPicker._id = OpenMaya.MEventMessage.addEventCallback("SelectionChanged", ObjectPicker.on_selection_changed)

    @staticmethod
    def remove_callback():
        # Remove the callback so it stops triggering the function.
        if ObjectPicker._id is not None:
            OpenMaya.MEventMessage.removeCallback(ObjectPicker._id)
            ObjectPicker._id = None


# After calling this, pick a new object then it will print it in the Script Editor.
picker = ObjectPicker()

After creating an new instance of the class with picker = ObjectPicker(), a warning will pop-up to the user to pick an object. After the selection changes, it triggers the callback which prints the selection to the Script Editor then removes its own callback.

I think this might work, but Maya isn't 3dsMax, and at the end of the day it might be best to not force one software to work like another. So I'd consider to just stick with what everyone is already used to, and that is to work with the user's current selection.

Edit: Sorry just noticed c++ tag, but the same concept should apply.

Edit #2: I just learned about the command cmds.scriptCtx, so a picker does exist! I think it's an older command as it seems to only support MEL and the implementation doesn't feel that great. If you want to learn more then check out my answer to another question.

Green Cell
  • 4,677
  • 2
  • 18
  • 49
  • This seems like a possible solution. I recognize that the Maya world is different than the 3D Max world - I've adapted where possible in our custom material management tool - but I just don't know exactly how to say 'Assign the material from THIS THING to THAT THING' without a picker. I will investigate further. – Steven Sep 27 '19 at 03:01
  • You can also include a pop-up dialog that prompts the user to pick an object in the scene. This dialog can hold a cancel button that would trigger the callback be removed when clicked. I think Max was right-click to cancel, but might be more hassle to set that up. This should be fairly clear to the user what to do. This dialog should also close when the callback is triggered and an object is picked. I strongly suggest you check out `PySide` for Maya. I remember using .net in Maya being a bit of a pain. – Green Cell Sep 27 '19 at 05:32
  • 1
    Hey Steven, check out my edit for this answer. A picker does exist! – Green Cell Oct 15 '19 at 02:25