You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使Maya C++ API中doRelease创建的MPxManipulatorNode可选中

问题:动态创建的MPxManipulatorNode无法选中

我自定义了一个MPxManipContainer,其中包含两个自定义MPxManipulatorNode实例:一个在容器的createChildren()函数内创建,另一个在鼠标按钮doRelease()事件触发时创建。目前遇到的问题是:createChildren()中创建的MPxManipulatorNode可被选中,但doRelease()中创建的实例无法被选中。

代码示例

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." );
      
      // 定位新的线条操纵器到指定高度
      LineManip* tmpManipPtr = (LineManip*) proxyManip;
      tmpManipPtr->start.y = y_;
      tmpManipPtr->end.y   = y_;

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

      // 初始化阶段创建的操纵器,可正常选中
      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 = MS::kSuccess;

      // 鼠标释放时创建的操纵器,无法被选中
      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;

插件效果截图

插件运行效果截图


原因解释

  • Maya的MPxManipContainer在初始化阶段(createChildren()执行期间),会自动完成子操纵器的选择注册流程:包括将操纵器的碰撞检测区域(hit test)纳入Maya的交互检测体系,确保鼠标能识别到操纵器的可选中状态。
  • 而在doRelease()这类运行时事件中调用addMPxManipulatorNode(),仅完成了操纵器的实例创建和添加,但Maya不会自动触发后续的选择注册逻辑,导致新创建的操纵器无法被鼠标检测到。

解决方法

在doRelease()中创建完新操纵器后,需要手动触发容器的更新和操纵器的注册操作,具体步骤:

  1. 调用MPxManipContainer::refresh(),强制容器重新同步所有子操纵器的状态。
  2. 调用新创建的MPxManipulatorNode::addToManipulatorManager(),将其手动注册到Maya的操纵器管理器中,确保碰撞检测区域被纳入交互体系。

修改后的核心代码

// 修改addLineManip方法,返回创建的操纵器指针
MStatus addLineManip( const MString& name_, double y_ = 0.0, LineManip*& outManip_ )
{
   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." );
   
   outManip_ = (LineManip*) proxyManip;
   outManip_->start.y = y_;
   outManip_->end.y   = y_;

   return status;
}

// 更新doRelease方法,添加手动注册逻辑
MStatus doRelease() override
{
   MStatus status = MS::kSuccess;

   LineManip* newManip = nullptr;
   status = addLineManip( MString("bar"), 0.5, newManip );
   CHECK_STATUS_AND_RETURN_IF_FAIL( status, "Failed to add LineManip in ToyManipContainer." );

   // 手动注册操纵器并刷新容器
   if (newManip) {
       newManip->addToManipulatorManager();
       refresh();
   }

   return status;
}

内容的提问来源于stack exchange,提问作者Constantinos Glynos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:17:32