admin管理员组

文章数量:1394145

I have created a custom MPxManipContainer, which contains two instances of a custom MPxManipulatorNode. One of the MPxManipulatorNode has been created inside the createChildren() function of the container, and the other is being created upon a doRelease() of a mouse button.

The problem I'm having is that the custom MPxManipulatorNode that was created during the doRelease() function is not selectable, whereas the MPxManipulatorNode that was created during the createChildren() function is selectable.

Can someone explain why that is, and how to make the custom MPxManipulatorNode, from the doRelease() function, selectable?

Code example:

struct LineManip : MPxManipulatorNode
{
   static MTypeId id;
   ...
};
MTypeId LineManip::id = 0x81047;

struct ToyManipContainer : MPxManipContainer
{
   static MTypeId id;
   ...
   MStatus addLineManip( const MString& name_, double y_ = 0.0 )
   {
      MStatus status = MStatus::kSuccess;

      MPxManipulatorNode* proxyManip = 0;
      MString manipTypeName("LineManip");
      status = addMPxManipulatorNode( manipTypeName, name_, proxyManip );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed in addMPxManipulatorNode." );
      
      // Position the new line manip at a certain height.
      LineManip* tmpManipPtr = (LineManip*) proxyManip;
      tmpManipPtr->start.y = y_;
      tmpManipPtr->end.y   = y_;

      return status;
   }
   MStatus createChildren() override
   {
      MStatus status = MS::kSuccess;

      // Creates a new line manip upon initialization.
      // The manip is created and is selectable.
      status = addLineManip( MString("foo"), 0.0 );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed to create the temp LineManip." );

      return status;
   }
   
   MStatus doRelease() override
   {
      MStatus status = MStatus::kSuccess;

      // Creates a new line manip upon the release of a mouse button.
      // Problem: The new manip is created, but it's not selectable.
      status = addLineManip( MString("bar"), 0.5 );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed to add LineManip in ToyManipContainer." );

      return status;
   }
};
MTypeId ToyManipContainer::id   = 0x81559;

Screenshot from plugin:

I have created a custom MPxManipContainer, which contains two instances of a custom MPxManipulatorNode. One of the MPxManipulatorNode has been created inside the createChildren() function of the container, and the other is being created upon a doRelease() of a mouse button.

The problem I'm having is that the custom MPxManipulatorNode that was created during the doRelease() function is not selectable, whereas the MPxManipulatorNode that was created during the createChildren() function is selectable.

Can someone explain why that is, and how to make the custom MPxManipulatorNode, from the doRelease() function, selectable?

Code example:

struct LineManip : MPxManipulatorNode
{
   static MTypeId id;
   ...
};
MTypeId LineManip::id = 0x81047;

struct ToyManipContainer : MPxManipContainer
{
   static MTypeId id;
   ...
   MStatus addLineManip( const MString& name_, double y_ = 0.0 )
   {
      MStatus status = MStatus::kSuccess;

      MPxManipulatorNode* proxyManip = 0;
      MString manipTypeName("LineManip");
      status = addMPxManipulatorNode( manipTypeName, name_, proxyManip );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed in addMPxManipulatorNode." );
      
      // Position the new line manip at a certain height.
      LineManip* tmpManipPtr = (LineManip*) proxyManip;
      tmpManipPtr->start.y = y_;
      tmpManipPtr->end.y   = y_;

      return status;
   }
   MStatus createChildren() override
   {
      MStatus status = MS::kSuccess;

      // Creates a new line manip upon initialization.
      // The manip is created and is selectable.
      status = addLineManip( MString("foo"), 0.0 );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed to create the temp LineManip." );

      return status;
   }
   
   MStatus doRelease() override
   {
      MStatus status = MStatus::kSuccess;

      // Creates a new line manip upon the release of a mouse button.
      // Problem: The new manip is created, but it's not selectable.
      status = addLineManip( MString("bar"), 0.5 );
      CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed to add LineManip in ToyManipContainer." );

      return status;
   }
};
MTypeId ToyManipContainer::id   = 0x81559;

Screenshot from plugin:

Share Improve this question asked Mar 13 at 14:57 Constantinos GlynosConstantinos Glynos 3,2062 gold badges17 silver badges33 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Ok, so I still haven't found an answer to the OP, but I have used the following workaround to unblock my progress. What I can do, in this situation, is define a static array with a fixed number of max manipulators, and hide them at initialization. A manipulator is shown, i.e. becomes active, when a new line is created.

The code example is as follows:

struct LineManip : MPxManipulatorNode
{
    static MTypeId id;
    bool active = false;
    ...
    
    void activate_at( double y_ )
    {
        active = true;
        ...
    }

    void drawUI( MHWRender::MUIDrawManager& drawManager, const MHWRender::MFrameContext& frameContext ) const override
    {
        if (!active)
            return;
        ...
    }
};
MTypeId LineManip::id = 0x81047;

struct ToyManipContainer : MPxManipContainer
{
    static MTypeId id;
    static constexpr unsigned max_num_of_line_manips = 10;
    std::array<LineManip*, max_num_of_line_manips> line_manips;
    ...
    MStatus addLineManip( unsigned counter_, const MString& name_ )
    {
        MStatus status = MStatus::kSuccess;

        MPxManipulatorNode* proxyManip = 0;
        MString manipTypeName("LineManip");
        status = addMPxManipulatorNode( manipTypeName, name_, proxyManip );
        CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed in addMPxManipulatorNode." );
        // Position the new line manip at 0.0 by default ctor.
        line_manips[counter_] = (LineManip*) proxyManip;
        return status;
    }
    
    MStatus createChildren() override
    {
        MStatus status = MS::kSuccess;
        ...
        // Workaround
        for (unsigned i = 0; i < max_num_of_line_manips; i++)
        {
            std::string manip_name = "line_manip" + std::to_string(i);
            status = addLineManip( i, manip_name.c_str() );
        }
        return status;
    }

    MStatus doRelease() override
    {
        MStatus status = MStatus::kSuccess;

        auto line_manip_itr = std::find_if( std::begin(line_manips),
                                            std::end(line_manips),
                                            []( auto lm_ )
                                            {
                                                return (!lm_->active);
                                            } );
        if ( line_manip_itr != std::end(line_manips) )
        {
            (*line_manip_itr)->activate_at( PlaneManip::mouse_position.y );
        }
        else
        {
            std::cout << "You have reached the maximum allowed number of manips." <<std::endl;
        }
        
        return status;
    }
};
MTypeId ToyManipContainer::id   = 0x81559;

本文标签: Make custom MPxManipulatorNodes selectable with Maya C ApiStack Overflow