Ejemplo n.º 1
0
bool plMultistageBehComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    // Create the stage vector
    plAnimStageVec* animStages = new plAnimStageVec;
    int numStages = fStages.size();
    animStages->reserve(numStages);

    // Convert the stages and add them to the vector
    for (int i = 0; i < numStages; i++)
    {
        plBaseStage* stage = fStages[i];
        plAnimStage* animStage = stage->CreateStage();

        animStages->push_back(animStage);
    }

    // re-find the mod and attach it
    plMultistageBehMod* mod = fMods[node];
    std::vector<plKey> receivers;
    IGetReceivers(node, receivers);
    mod->Init(animStages, fFreezePhys, fSmartSeek, fReverseFBOnRelease, &receivers);
    node->AddModifier(mod, IGetUniqueName(node));

    return true;
}
Ejemplo n.º 2
0
bool plMtlEventComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    if (!fCanExport)
        return false;

    plKey modKey = fLogicModKeys[node];
    plAnimEventModifier* mod = plAnimEventModifier::ConvertNoRef(modKey->GetObjectPtr());

    Mtl* mtl = fCompPB->GetMtl(kMtlMtl);
    plMaxNodeBase* mtlNode = (plMaxNodeBase*)fCompPB->GetINode(kMtlNode);
    ST::string mtlAnim = ST::string::from_utf8(fCompPB->GetStr(kMtlAnim));

    //
    // Create and setup the callback message
    //
    hsTArray<plKey> animKeys;
    GetMatAnimModKey(mtl, mtlNode, mtlAnim, animKeys);

    plAnimCmdMsg *animMsg = new plAnimCmdMsg;
    animMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
    animMsg->SetSender(modKey);
    animMsg->SetAnimName(mtlAnim);
    animMsg->AddReceivers(animKeys);

    if (fCompPB->GetInt(kMtlBegin))
    {
        plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
        eventMsg->fEvent = kBegin;
    }
    if (fCompPB->GetInt(kMtlEnd))
    {
        plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
        eventMsg->fEvent = kEnd;
    }
    if (fCompPB->Count(kMtlMarkers) > 0)
    {
        plNotetrackAnim anim(mtl, nil);
        plAnimInfo info = anim.GetAnimInfo(mtlAnim);

        int numMarkers = fCompPB->Count(kMtlMarkers);
        for (int i = 0; i < numMarkers; i++)
        {
            ST::string marker = ST::string::from_utf8(fCompPB->GetStr(kMtlMarkers, 0, i));
            float time = info.GetMarkerTime(marker);

            plEventCallbackMsg *eventMsg = CreateCallbackMsg(animMsg, modKey);
            eventMsg->fEvent = kTime;
            eventMsg->fEventTime = time;
        }
    }

    mod->SetCallback(animMsg);

    hsTArray<plKey> receivers;
    IGetReceivers(node, receivers);
    mod->SetReceivers(receivers);

    return true;
}
hsBool plAvBehaviorSittingComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plKey logicKey = fLogicModKeys[node];
    if (logicKey)
    {
        plSittingModifier *sitMod = plSittingModifier::ConvertNoRef(logicKey->GetObjectPtr());

        // XXX sitMod->SetSeekTime(fCompPB->GetFloat(kSeekTimeFloat));

        // Get all the keys who want to be notified when the avatar ass hits the seat
        hsTArray<plKey> receivers;
        IGetReceivers(node, receivers);
        for (int i = 0; i < receivers.Count(); i++)
            sitMod->AddNotifyKey(receivers[i]);
    }

    return true;
}
Ejemplo n.º 4
0
bool plClickDragComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plLocation loc = node->GetLocation();
    plSceneObject *obj = node->GetSceneObject();
    
    plKey logicKey = fLogicModKeys[node];
    plLogicModifier *logic = plLogicModifier::ConvertNoRef(logicKey->GetObjectPtr());
    logic->fMyCursor = plCursorChangeMsg::kCursorOpen;

        // Create the detector
    plDetectorModifier *detector = nil;
    detector = new plPickingDetector;

    // Register the detector
    plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc);
    hsgResMgr::ResMgr()->AddViaNotify(detectorKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);

    // set up the axis anim controller
    
    plKey axisKey = fAxisKeys[node];
    plAxisAnimModifier* pAxis = plAxisAnimModifier::ConvertNoRef(axisKey->GetObjectPtr());
    // attach the animation controller to the animation objects:
    // find an animation controller:
    
    hsTArray<plKey> receivers;
    IGetReceivers(node, receivers);
    
    int i;
    for (i = 0; i < receivers.Count(); i++)
        pAxis->GetNotify()->AddReceiver(receivers[i]);

    pAxis->SetNotificationKey(logicKey);
    uint32_t count = node->NumAttachedComponents();
    bool bHasAnim = false;
    plAnimComponentBase* pAnim = nil;

    for (i = 0; i < count; i++)
    {
        plComponentBase *comp = node->GetAttachedComponent(i);
        if (comp->ClassID() == ANIM_COMP_CID || comp->ClassID() == ANIM_GROUP_COMP_CID)
        {
            pAnim = (plAnimComponentBase*)comp;
            break;
        }
    }
    if (!pAnim)
    {
        pErrMsg->Set(true, "WARNING", "Object %s has click-drag component attached but NO animation component!", ((INode*)node)->GetName()).Show();
        pErrMsg->Set(false);
    }
    else
    {
        if (fCompPB->GetInt(kClickDragUseX))
        {
            pAxis->SetXAnim( pAnim->GetModKey(node) );
        }   
        else // take out this else when we support multiple channels
        if (fCompPB->GetInt(kClickDragUseY))
        {
            pAxis->SetYAnim( pAnim->GetModKey(node) );
        }
        pAxis->SetAllOrNothing(fCompPB->GetInt(kClickDragAllOrNothing));

        // add callbacks for beginning and end of animation
        plEventCallbackMsg* pCall1 = new plEventCallbackMsg;
        pCall1->fEvent = kBegin;
        pCall1->fRepeats = -1;
        pCall1->AddReceiver(axisKey);
        
        plEventCallbackMsg* pCall2 = new plEventCallbackMsg;
        pCall2->fEvent = kEnd;
        pCall2->fRepeats = -1;
        pCall2->AddReceiver(axisKey);

        plAnimCmdMsg* pMsg = new plAnimCmdMsg;
        plString tempAnimName = pAnim->GetAnimName();
        if (tempAnimName.IsNull())
        {
            //pMsg->SetAnimName(ENTIRE_ANIMATION_NAME);
            pMsg->SetAnimName(pAnim->GetModKey(node)->GetName());
            pAxis->SetAnimLabel(ENTIRE_ANIMATION_NAME);
        }
        else
        {
            //pMsg->SetAnimName(tempAnimName);
            pMsg->SetAnimName(pAnim->GetModKey(node)->GetName());
            pAxis->SetAnimLabel(tempAnimName);
        }
        

        pMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
        pMsg->AddCallback(pCall1);
        pMsg->AddCallback(pCall2);

        hsRefCnt_SafeUnRef( pCall1 );
        hsRefCnt_SafeUnRef( pCall2 );

        pMsg->AddReceiver( pAnim->GetModKey(node) );
        plgDispatch::MsgSend(pMsg);
    }


    // is this a using a proxy primitive?
    plPickingDetector* det2 = nil;
    plKey det2Key  = nil;
    plMaxNode* pProxyNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxy);
    
    if (pProxyNode && fCompPB->GetInt(kClickDragUseProxy))
    {
        
        // verify that there is a physical proxy attached to this scene object:
        uint32_t count = ((plMaxNodeBase*)pProxyNode)->NumAttachedComponents();
        bool bHasPhys = false;
//      for (uint32_t i = 0; i < count; i++)
        //      {
        //          plComponentBase *comp = ((plMaxNodeBase*)pProxyNode)->GetAttachedComponent(i);
        //          if (comp->ClassID() == Class_ID(0x11e81ee4, 0x36b81450))
        //          {
        //              bHasPhys = true;
        //              break;
        //          }
        //      }
        //      if (!bHasPhys)
        //      {
        //          pErrMsg->Set(true, "WARNING", "Object %s listed as draggable component proxy physical for %s but has NO physical component.\n  Please attach a proxyTerrain componet!\n Export will continue but this gadget will not function",pProxyNode->GetName(), ((INode*)node)->GetName()).Show();
        //          pErrMsg->Set(false);
        //      }
        

        if(pProxyNode->CanConvert())
        {
            det2 = new plPickingDetector;
            // Register the detector
            det2Key = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), det2, loc);
            hsgResMgr::ResMgr()->AddViaNotify(det2Key, new plObjRefMsg(((plMaxNode*)pProxyNode)->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
            hsgResMgr::ResMgr()->AddViaNotify(logicKey, new plObjRefMsg( det2Key, plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
            det2->SetProxyKey(node->GetSceneObject()->GetKey());
        }
        else
        {
            pErrMsg->Set(true, "Unknown Error", "Invalid proxy physical detector set for draggable %s.", ((INode*)pProxyNode)->GetName()).Show();
            pErrMsg->Set(false);
            return false;
        }
    
    }



    // create and register the CONDITIONS for the DETECTOR's Logic Modifier
    plActivatorConditionalObject* activatorCond = new plActivatorConditionalObject;
    plKey activatorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), activatorCond, loc);

    // do we have a required region?
    plMaxNode* pProxyRegNode = (plMaxNode*)fCompPB->GetINode(kClickDragProxyRegion);
    if (pProxyRegNode)
    {
        // verify that there is a physical detector attached to this scene object:
        uint32_t count = ((plMaxNodeBase*)pProxyRegNode)->NumAttachedComponents();
        bool bHasPhys = false;
//      for (uint32_t i = 0; i < count; i++)
        //      {
        //          plComponentBase *comp = ((plMaxNodeBase*)pProxyRegNode)->GetAttachedComponent(i);
        //          if (comp->ClassID() == Class_ID(0x33b60376, 0x7e5163e0))
        //          {
        //              bHasPhys = true;
        //              break;
        //          }
        //      }
        //      if (!bHasPhys)
        //      {
        //          pErrMsg->Set(true, "WARNING", "Object %s listed as draggable component detector region for %s but has NO physical detector component!\n  Please attach a detector componet.\n Export will continue but this gadget will not function",((INode*)pProxyRegNode)->GetName(), ((INode*)node)->GetName()).Show();
        //          pErrMsg->Set(false);
        //      }
        

        if(pProxyRegNode->CanConvert())
        {
            // need a player in box condition here...
            // first a detector-any for the box
            plObjectInVolumeDetector* pCDet = new plObjectInVolumeDetector(plCollisionDetector::kTypeAny);
            plKey cDetKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pCDet, loc);
            hsgResMgr::ResMgr()->AddViaNotify(cDetKey, new plObjRefMsg(((plMaxNode*)pProxyRegNode)->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
            pCDet->AddLogicObj(logicKey);
            // then an object-in-box condition for the logic mod
            plObjectInBoxConditionalObject* boxCond = new plObjectInBoxConditionalObject;
            plKey boxCondKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), boxCond, loc);
            logic->AddCondition(boxCond);
        }
        else
        {       
            pErrMsg->Set(true, "Problem with region", "Can't convert region component on  %s.  This component will not be exported.\n", ((INode*)pProxyRegNode)->GetName()).Show();
            pErrMsg->Set(false);
            return false;
        }
    }
    else
    {
        pErrMsg->Set(true, "Must specify trigger region", "No required trigger region specified for click-drag component on %s.  This component will not be exported.\n", ((INode*)node)->GetName()).Show();
        pErrMsg->Set(false);
        return false;
    }


    // How do we feel about player facing
    plFacingConditionalObject* facingCond = new plFacingConditionalObject;
    facingCond->SetDirectional(fCompPB->GetInt(kClickDragDirectional));
    int deg = fCompPB->GetInt(kClickDragDegrees);
    if (deg > 180)
        deg = 180;
    float rad = hsDegreesToRadians(deg);
    facingCond->SetTolerance(cos(rad));
    plKey facingKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), facingCond, loc);
    
    
    // link everything up:
    if (det2) // set up the remote detector (if any)
    {
        activatorCond->SetActivatorKey(det2Key);
        det2->AddLogicObj(logicKey);
    }
    else
    {
        detector->AddLogicObj(logicKey);     // send messages to this logic component
        activatorCond->SetActivatorKey(detectorKey); // Tells the activator condition to look for stimulus from the detector
    }
    logic->AddCondition(activatorCond); // add this activator condition
    logic->AddCondition(facingCond);
    logic->SetDisabled(fCompPB->GetInt(kClikDragEnabled) == 0);

    
    // If this is for the SceneViewer, set the local only flag since the read function will never be called
    if (plConvert::Instance().IsForSceneViewer())
        logic->SetLocalOnly(true);

    return true;
}
void plVolumeGadgetComponent::ICreateConditions(plMaxNode* node, plErrorMsg* errMsg, bool enter)
{
    bool disabled = (fCompPB->GetInt(kVolumeEnabled) == 0);

    plLocation loc = node->GetLocation();
    plSceneObject *obj = node->GetSceneObject();

    plKey logicKey;
    if (enter)
        logicKey = fLogicModKeys[node];
    else
        logicKey = fLogicModOutKeys[node];

    plLogicModifier *logic = plLogicModifier::ConvertNoRef(logicKey->GetObjectPtr());

    hsTArray<plKey> receivers;
    IGetReceivers(node, receivers);
    for (int i = 0; i < receivers.Count(); i++)
        logic->AddNotifyReceiver(receivers[i]);


    // Create the detector
    plDetectorModifier* detector = nil;
    if (enter && fCompPB->GetInt(kVolumeTriggerOnFacing))
    {
        plObjectInVolumeAndFacingDetector* newDetector = new plObjectInVolumeAndFacingDetector;

        int deg = fCompPB->GetInt(kVolumeDegrees);
        if (deg > 180)
            deg = 180;
        newDetector->SetFacingTolerance(deg);

        bool walkingForward = (fCompPB->GetInt(kVolumeWalkingForward) != 0);
        newDetector->SetNeedWalkingForward(walkingForward);

        detector = newDetector;
    }
    else
        detector = new plObjectInVolumeDetector;

    const char* prefix = "Exit";
    if (enter)
        prefix = "Enter";

    // Register the detector
    plString tmpName = plString::Format("%s_%s", IGetUniqueName(node).c_str(), prefix);
    plKey detectorKey = hsgResMgr::ResMgr()->NewKey(tmpName, detector, loc);
    hsgResMgr::ResMgr()->AddViaNotify(detectorKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
    plVolumeSensorConditionalObject* boxCond=nil;
    if((fCompPB->GetInt(kSkipServerArbitration)==0))
    {//we want server arbitration
        boxCond = new plVolumeSensorConditionalObject;
    }
    else
    {
        boxCond = new plVolumeSensorConditionalObjectNoArbitration;
    }
    tmpName = plString::Format("%s_%s", IGetUniqueName(node).c_str(), prefix);
    plKey boxKey = hsgResMgr::ResMgr()->NewKey(tmpName, boxCond, loc);

    if (enter)
        boxCond->SetType(plVolumeSensorConditionalObject::kTypeEnter);
    else
        boxCond->SetType(plVolumeSensorConditionalObject::kTypeExit);

    if (enter && !fCompPB->GetInt(kVolumeTriggerOnFacing))
    {
        int trigType = fCompPB->GetInt(kVolumeEnterType);
        switch (trigType)
        {
        case kEnterTypeEach:
            break;

        case kEnterTypeCount:
            {
                int count = fCompPB->GetInt(kVolumeEnterNum);
                boxCond->SetTrigNum(count);
                break;
            }
        }
    }
    else if (!enter)
    {
        int trigType = fCompPB->GetInt(kVolumeExitType);
        switch (trigType)
        {
        case kExitTypeEach:
            break;

        case kExitTypeFirst:
            boxCond->SetFirst(true);
            break;

        case kExitTypeCount:
            {
                int count = fCompPB->GetInt(kVolumeExitNum);
                boxCond->SetTrigNum(count);
                break;
            }
        }
    }

    // link everything up:
    detector->AddLogicObj(boxKey);      // This MUST be first!!
    detector->AddLogicObj(logicKey);     // send messages to this logic component
    logic->AddCondition(boxCond);
    logic->SetDisabled(disabled);

    // If this is for the SceneViewer, set the local only flag since the read function will never be called
    if (plConvert::Instance().IsForSceneViewer())
        logic->SetLocalOnly(true);
}