Пример #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;
}
Пример #2
0
void plAvatarComponent::IAttachModifiers(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plString name = node->GetKey()->GetName();

    plMaxNode *meshNode = (plMaxNode *)fCompPB->GetINode(plAvatarComponent::kMeshNode);
    plKey meshKey = meshNode->GetSceneObject()->GetKey();
    plMaxNode *animRootNode = (plMaxNode *)fCompPB->GetINode(plAvatarComponent::kRootNode);
    plKey animRootKey = animRootNode->GetSceneObject()->GetKey();
            
    plSceneObject * bodySO = node->GetSceneObject();

    plArmatureMod* avMod = new plArmatureMod();
    avMod->SetRootName(name);
    avMod->AppendMeshKey(meshKey);
    int skeletonType = fCompPB->GetInt(ParamID(kSkeleton));
    avMod->SetBodyType( skeletonType );

    // only make a human brain if we're a human
    if (skeletonType == plArmatureMod::kBoneBaseCritter)
        avMod->PushBrain(new plAvBrainCritter());
    else
        avMod->PushBrain(new plAvBrainHuman(skeletonType == plArmatureMod::kBoneBaseActor));

    avMod->SetBodyAgeName(node->GetAgeName());
    avMod->SetBodyFootstepSoundPage(fCompPB->GetStr(ParamID(kBodyFootstepSoundPage)));
    avMod->SetAnimationPrefix(plString::FromUtf8(fCompPB->GetStr(ParamID(kAnimationPrefix))));

    //AddLinkSound(node, node->GetSceneObject()->GetKey(), pErrMsg );

    plKey avKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), avMod, node->GetLocation());
    plObjRefMsg *objRefMsg = new plObjRefMsg(bodySO->GetKey(), plRefMsg::kOnCreate,-1, plObjRefMsg::kModifier);
    hsgResMgr::ResMgr()->AddViaNotify(avKey, objRefMsg, plRefFlags::kActiveRef);

    fArmMod = avMod;
}
Пример #3
0
bool plGrassComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    fShader = new plGrassShaderMod();

    plLoadMask loadMask;
    int qual = 1;
    int cap = plQuality::kPS_1_1;
    plLoadMask::ComputeRepMasks(1, &qual, &cap, &loadMask);
    plKey modKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), fShader, node->GetLocation(), loadMask);

    int i;
    for (i = 0; i < plGrassShaderMod::kNumWaves; i++)
    {
        fShader->fWaves[i].fDistX = fCompPB->GetFloat(ParamID(kDistXTab), 0, i);
        fShader->fWaves[i].fDistY = fCompPB->GetFloat(ParamID(kDistYTab), 0, i);
        fShader->fWaves[i].fDistZ = fCompPB->GetFloat(ParamID(kDistZTab), 0, i);
        fShader->fWaves[i].fDirX = fCompPB->GetFloat(ParamID(kDirXTab), 0, i);
        fShader->fWaves[i].fDirY = fCompPB->GetFloat(ParamID(kDirYTab), 0, i);
        fShader->fWaves[i].fSpeed = fCompPB->GetFloat(ParamID(kSpeedTab), 0, i);
    }

    // Add a ref to the shader.
    fShader->GetKey()->RefObject();

    return true;
}
hsBool plMaintainersMarkerComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plMaintainersMarkerModifier* pSpawn = new plMaintainersMarkerModifier;
    pSpawn->SetCalibrated(fCompPB->GetInt(kCalibrated));
    node->AddModifier(pSpawn, IGetUniqueName(node));
    return true;
}
hsBool plResponderComponent::PreConvert(plMaxNode *node,plErrorMsg *pErrMsg)
{
    plSceneObject* rObj = node->GetSceneObject();
    plLocation loc = node->GetLocation();

    // Create and register the RESPONDER's logic component
    plResponderModifier *responder = new plResponderModifier;
    plKey responderKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), responder, loc);
    hsgResMgr::ResMgr()->AddViaNotify(responderKey, new plObjRefMsg(rObj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);

    // Tell all the activators to notify us
    for (int i = 0; i < fCompPB->Count(kResponderActivators); i++)
    {
        plMaxNode *activatorNode = (plMaxNode*)fCompPB->GetINode(kResponderActivators, 0, i);
        plComponentBase *comp = activatorNode ? activatorNode->ConvertToComponent() : nil;
        if (comp)
        {
            if (fCompPB->GetInt(kResponderLocalDetect))
                comp->AddReceiverKey(responderKey, node);
            else
                comp->AddReceiverKey(responderKey);
        }
    }

    fModKeys[node] = responderKey;

    return true;
}
Пример #6
0
void plLODAvatarComponent::IAttachModifiers(    plMaxNode *node, plErrorMsg *pErrMsg)
{
    plString avatarName = node->GetKey()->GetName();
    plMaxNode *animRoot = (plMaxNode *)fCompPB->GetINode(plLODAvatarComponent::kRootNodeAddBtn);
    plKey animRootKey = animRoot->GetSceneObject()->GetKey();
    plArmatureLODMod* avMod = new plArmatureLODMod(avatarName);

    int skeletonType = fCompPB->GetInt(ParamID(kSkeleton));
    avMod->SetBodyType( skeletonType );
    if (skeletonType == plArmatureLODMod::kBoneBaseCritter)
        avMod->PushBrain(new plAvBrainCritter());
    else
        avMod->PushBrain(new plAvBrainHuman(skeletonType == plArmatureMod::kBoneBaseActor));

    avMod->SetBodyAgeName(node->GetAgeName());
    avMod->SetBodyFootstepSoundPage(fCompPB->GetStr(ParamID(kBodyFootstepSoundPage)));
    avMod->SetAnimationPrefix(plString::FromUtf8(fCompPB->GetStr(ParamID(kAnimationPrefix))));

    int iLODCount = fCompPB->Count(plLODAvatarComponent::kMeshNodeTab);
    for (int i = 0; i < iLODCount; i++)
    {
        plMaxNode *meshNode = (plMaxNode *)fCompPB->GetINode(plLODAvatarComponent::kMeshNodeTab, 0, i);
        plKey meshKey = meshNode->GetSceneObject()->GetKey();
        avMod->AppendMeshKey(meshKey);
    }

    node->AddModifier(avMod, IGetUniqueName(node));
    fArmMod = avMod;
    IAttachShadowCastToLODs(node);
}
Пример #7
0
//
// PreConvert done below
//
bool plMultistageBehComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    //create the modifier here so that other components can find it
    plMultistageBehMod *mod = new plMultistageBehMod;
    hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), mod, node->GetLocation());
    fMods[node] = mod;

    return true;
}
Пример #8
0
// this is a little gross...the armature component shouldn't know that the subclasses
// actually exist....it's a hard-to-detect implementation detail that breaks new subclasses....
bool plArmatureComponent::Convert(plMaxNode* node, plErrorMsg *pErrMsg)
{
//  plHKPhysical *physical = plHKPhysical::ConvertToPhysical(node->GetSceneObject());
 // physical->SetProperty(plSimulationInterface::kUpright, true);

    IAttachModifiers(node, pErrMsg);
    ISetupClothes(node, fArmMod, pErrMsg);

    // ArmatureEffects
    plArmatureEffectsMgr *effects = new plArmatureEffectsMgr();
    hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), effects, node->GetLocation());
    plGenRefMsg *msg = new plGenRefMsg(fArmMod->GetKey(), plRefMsg::kOnCreate, -1, -1);
    hsgResMgr::ResMgr()->AddViaNotify(effects->GetKey(), msg, plRefFlags::kActiveRef); // Attach effects

    plSceneObject *obj = node->GetSceneObject();
    node->MakeCharacterHierarchy(pErrMsg);

    const plAGModifier *temp = static_cast<const plAGModifier *>(FindModifierByClass(obj, plAGModifier::Index()));
    plAGModifier *agMod = const_cast<plAGModifier *>(temp);

    hsAssert(agMod, "Armature root didn't get a agmod. I'll make one for you.");
    if( ! agMod)
    {
        // MakeCharacterHierarchy will attach agmodifiers to all the bones in the hierarchy;
        // have to manually add any for non-bone objects...
        agMod = new plAGModifier("Handle");     // the player root is known as the handle
        node->AddModifier(agMod, IGetUniqueName(node));
    }

    agMod->SetChannelName("Handle");

    // Get the position and radius of the head and torso physicals
    if (ClassID() == AVATAR_CLASS_ID || ClassID() == LOD_AVATAR_CLASS_ID)
    {
        bool isLOD = ((ClassID() == LOD_AVATAR_CLASS_ID) != 0);
        float height = fCompPB->GetFloat(isLOD ? plLODAvatarComponent::kPhysicsHeight : plAvatarComponent::kPhysicsHeight);
        float width = fCompPB->GetFloat(isLOD ? plLODAvatarComponent::kPhysicsWidth : plAvatarComponent::kPhysicsWidth);
        fArmMod->SetPhysicalDims(height, width);
    }

//  node->SetupBonesAliasesRecur(node->GetKey()->GetName());

    return true;
}
hsBool plStrongSpringConstraintComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plStrongSpringConstraintMod* HMod = new plStrongSpringConstraintMod;

    HMod->SetDamp(fCompPB->GetFloat(kStrength));
    HMod->SetRR(fCompPB->GetFloat(kRebound));

    //No MaximumTorque here, might as well use that field for the Pinned state for the Parent...
    HMod->SetParentPin(fCompPB->GetInt(kParentPinnedBool));


        Object *obj = fCompPB->GetINode(kParent)->EvalWorldState(0/*hsConverterUtils::Instance().GetTime(GetInterface())*/).obj;

        plKey ParentKey  = nil;
        if(fCompPB->GetINode(kParent))
            if(((plMaxNode*)fCompPB->GetINode(kParent))->CanConvert() && (obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) || obj->SuperClassID() == GEOMOBJECT_CLASS_ID ))
            {
                plMaxNode* ParentNode = (plMaxNode*)fCompPB->GetINode(kParent);
                ParentKey = ParentNode->GetKey();
            }
            else
            {
                pErrMsg->Set(true, "Ignored Parent Node", "Parent Node %s was set to be Ignored. Bad! Bad!.", (fCompPB->GetINode(kParent)->GetName()));
                pErrMsg->Set(false);
                return false;
            }           
        else
        {

//          pErrMsg->Set(true, "Bad Parent Node", " Parent Node %s wasn't selected. Strong Spring Constraint failed.", (fCompPB->GetINode(kParent)->GetName()));
//          pErrMsg->Set(false);
//          return false;
        }


    //No motor Angle here, might as well use the field for Length Storage...
    HMod->SetFixedLength(fCompPB->GetFloat(kLength));



    node->AddModifier(HMod, IGetUniqueName(node));
    hsgResMgr::ResMgr()->AddViaNotify( ParentKey, new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kParentIdx, 0 ), plRefFlags::kPassiveRef );
    hsgResMgr::ResMgr()->AddViaNotify( node->GetKey(), new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kChildIdx, 0 ), plRefFlags::kPassiveRef );









    return true;

}
Пример #10
0
//
// PreConvert done below
//
bool plOneShotComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    if (IsValid())
    {
        plOneShotMod *mod = new plOneShotMod;
        hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), mod, node->GetLocation());
        fMods[node] = mod;
    }

    return true;
}
hsBool plPhysBridgeComponent::Convert(plMaxNode* node, plErrorMsg* errMsg)
{
    plMaxNode* parent = nil;

    // Find the parent for this section
    int count = fCompPB->Count(kSections);
    for (int i = 0; i < count; i++)
    {
        plMaxNode* curNode = (plMaxNode*)fCompPB->GetINode(kSections, 0, i);
        if (curNode == node)
        {
            if (i < count-1)
                parent = (plMaxNode*)fCompPB->GetINode(kSections, 0, i+1);
            break;
        }
    }

    // No parent, must be the end anchor for the bridge
    if (!parent)
        return false;

    plHingeConstraintMod* mod = new plHingeConstraintMod;

//  mod->SetHCFriction(0, 1.f);
    mod->SetRR(fCompPB->GetFloat(kStrength));//1.f / sqrt(float(count)));
    mod->SetDamp(fCompPB->GetFloat(kStiffness));

    // Grab the pivot point from the child translate
    hsPoint3 pivot = node->GetLocalToWorld44().GetTranslate();
    hsVector3 pivotVec;
    pivotVec.Set(pivot.fX, pivot.fY, pivot.fZ);
    mod->SetPP(pivotVec);

    // Cut'n'Paste
    enum
    {
        kYAxis,
        kXAxis,
        kZAxis,
    };

    hsVector3 hingeVector;
    hingeVector = node->GetLocalToWorld44().GetAxis(hsMatrix44::kRight);
//  mod->SetHCLimits(kXAxis, 0, -1*fCompPB->GetFloat(kUpperAngle));
//  mod->SetHCLimits(kXAxis, 1, -1*fCompPB->GetFloat(kLowerAngle));

    mod->SetRotationAxis(-1*hingeVector);

    node->AddModifier(mod, IGetUniqueName(node));
    hsgResMgr::ResMgr()->AddViaNotify(parent->GetKey(), new plGenRefMsg(mod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kParentIdx, 0), plRefFlags::kPassiveRef);
    hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), new plGenRefMsg(mod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kChildIdx, 0), plRefFlags::kPassiveRef);

    return true;
}
Пример #12
0
// CONVERT
bool plSeekPointComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    const char *objName = node->GetName();
    char *name = new char[strlen(objName) + 1];

    strcpy(name, objName);

    plSeekPointMod* pointMod = new plSeekPointMod(name);
    node->AddModifier(pointMod, IGetUniqueName(node));
    return true;
}
Пример #13
0
bool plMtlEventComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
    if (!fCanExport)
        return false;

    plAnimEventModifier* mod = new plAnimEventModifier;
    plKey modKey = node->AddModifier(mod, IGetUniqueName(node));

    fLogicModKeys[node] = modKey;

    return true;
}
hsBool plSpawnComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    const char *templateName = GetPBString(fCompPB, kTemplateName);
    if (!templateName)
        return false;

    plCloneSpawnModifier* mod = new plCloneSpawnModifier;
    mod->SetExportTime();
    mod->SetTemplateName(templateName);
    node->AddModifier(mod, IGetUniqueName(node));

    return true;
}
Пример #15
0
bool plArmatureComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
    // add audio interface and record/playback component
    pl2WayWinAudible* pAudible = new pl2WayWinAudible;

    // Add a key for it
    plKey key = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pAudible, node->GetLocation() );

    plAudioInterface* ai = new plAudioInterface;
    plKey pAiKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), (hsKeyedObject*)ai,node->GetLocation());
        
    hsgResMgr::ResMgr()->AddViaNotify(pAiKey, new plObjRefMsg(node->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
        
    plIntRefMsg* pMsg = new plIntRefMsg(node->GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kAudible);
    hsgResMgr::ResMgr()->AddViaNotify(pAudible->GetKey(), pMsg, plRefFlags::kActiveRef );

    ISetArmatureSORecurse(node, node->GetSceneObject());
    
    // Uncomment this line to enable a single bone pallete for the entire avatar.
    node->SetupBoneHierarchyPalette();
    return true;

}
Пример #16
0
bool plCompoundCtrlComponent::Convert(plMaxNode* node, plErrorMsg *pErrMsg)
{
    plString name = node->GetKey()->GetName();

    node->MakeCharacterHierarchy(pErrMsg);
    node->SetupBonesAliasesRecur(name.c_str());


    // create and register the player modifier
    plAGMasterMod *agMaster = new plAGMasterMod();
    node->AddModifier(agMaster, IGetUniqueName(node));

    return true;
}
hsBool plVolumeGadgetComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plLocation loc = node->GetLocation();
    plSceneObject *obj = node->GetSceneObject();


    // Create and register the VolumeGadget's logic component
    if(fCompPB->GetInt(kVolumeGadgetEnter) || fCompPB->GetInt(kVolumeTriggerOnFacing))
    {   
        plLogicModifier *logic = new plLogicModifier;
        plString tmpName = plString::Format("%s_Enter", IGetUniqueName(node).c_str());
        plKey logicKey = hsgResMgr::ResMgr()->NewKey(tmpName, logic, node->GetLocation());
        hsgResMgr::ResMgr()->AddViaNotify(logicKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);

        fLogicModKeys[node] = logicKey;
        if (fCompPB->GetInt(kVolumeOneShot))
            logic->SetFlag(plLogicModBase::kOneShot);
        logic->SetFlag(plLogicModBase::kMultiTrigger);
    }

    
    if(fCompPB->GetInt(kVolumeGadgetExit))
    {   
        plLogicModifier *logic = new plLogicModifier;
        plString tmpName = plString::Format("%s_Exit", IGetUniqueName(node).c_str());
        plKey logicKey = hsgResMgr::ResMgr()->NewKey(tmpName, logic, node->GetLocation());
        hsgResMgr::ResMgr()->AddViaNotify(logicKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);

        fLogicModOutKeys[node] = logicKey;
        if (fCompPB->GetInt(kVolumeOneShot))
            logic->SetFlag(plLogicModBase::kOneShot);
        logic->SetFlag(plLogicModBase::kMultiTrigger);
    }

    return true;
}
Пример #18
0
bool plActivatorBaseComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    node->SetForceLocal(true);

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

    // Create and register the VolumeGadget's logic component
    plLogicModifier *logic = new plLogicModifier;
    plKey logicKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), logic, node->GetLocation());
    hsgResMgr::ResMgr()->AddViaNotify(logicKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);

    fLogicModKeys[node] = logicKey;

    return true;
}
Пример #19
0
void plLODAvatarComponent::IAttachShadowCastToLODs(plMaxNode* rootNode)
{
    plShadowCaster* caster = new plShadowCaster;
    hsgResMgr::ResMgr()->NewKey(IGetUniqueName(rootNode), caster, rootNode->GetLocation());
    caster->SetSelfShadow(true);

    int iLODCount = fCompPB->Count(plLODAvatarComponent::kMeshNodeTab);

    for (int i = 0; i < iLODCount; i++)
    {
        plMaxNode *meshNode = (plMaxNode *)fCompPB->GetINode(plLODAvatarComponent::kMeshNodeTab, 0, i);
        if( meshNode )
        {
            plShadowCastComponent::AddShadowCastModifier(meshNode, caster); // The LOD roots are a special case.
            IAttachShadowCastModifiersRecur(meshNode, caster);
        }
    }
}
hsBool plVehicleComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg)
{
    return false;
#if 0
    if (!IIsValid())
        return false;

    fMod = new plVehicleModifier;
    plKey modKey = pNode->AddModifier(fMod, IGetUniqueName(pNode));

    plMaxNode* detectorNode = (plMaxNode*)fCompPB->GetINode(kVehicleDriveDet);
    plComponentBase* comp = detectorNode ? detectorNode->ConvertToComponent() : nil;
    if (comp)
        comp->AddReceiverKey(modKey);

    return true;
#endif
}
Пример #21
0
bool plObjectFlockerComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    if (fFlocker)
        delete fFlocker;

    fFlocker = new pfObjectFlocker;
    hsgResMgr::ResMgr()->NewKey( IGetUniqueName(node), fFlocker, node->GetLocation(), node->GetLoadMask());

    fFlocker->SetGoalWeight(fCompPB->GetFloat(ParamID(kGoalStrength)));
    fFlocker->SetWanderWeight(fCompPB->GetFloat(ParamID(kWanderStrength)));

    fFlocker->SetSeparationWeight(fCompPB->GetFloat(ParamID(kSepStrength)));
    fFlocker->SetSeparationRadius(fCompPB->GetFloat(ParamID(kSepRadius)));

    fFlocker->SetCohesionWeight(fCompPB->GetFloat(ParamID(kCohStrength)));
    fFlocker->SetCohesionRadius(fCompPB->GetFloat(ParamID(kCohRadius)));

    fFlocker->SetMaxForce(fCompPB->GetFloat(ParamID(kMaxForce)));
    fFlocker->SetMaxSpeed(fCompPB->GetFloat(ParamID(kMaxSpeed)));
    fFlocker->SetMinSpeed(fCompPB->GetFloat(ParamID(kMinSpeed)));

    fFlocker->SetUseTargetRotation(fCompPB->GetInt(ParamID(kUseTargetRotation)) != 0);
    fFlocker->SetRandomizeAnimStart(fCompPB->GetInt(ParamID(kRandomAnimStart)) != 0);

    fFlocker->SetNumBoids(fCompPB->GetInt(ParamID(kNumBoids)));

    plKey boidKey = nil;
    plMaxNode* targNode = (plMaxNode*)fCompPB->GetINode(kBoidObject);

    if( targNode->CanConvert() )
    {
        plSceneObject* targObj = targNode->GetSceneObject();
        if( targObj )
        {
            boidKey = targObj->GetKey();
        }
    }
    fFlocker->SetBoidKey(boidKey);

    // Add a ref to the flocker.
    fFlocker->GetKey()->RefObject();

    return true;
}
Пример #22
0
//
// Convert Done below
//
bool plOneShotComponent::Convert(plMaxNode* node, plErrorMsg *pErrMsg)
{
    if (fMods.find(node) != fMods.end())
    {
        const char *animName = fCompPB->GetStr(kAnimName);
        bool drivable = fCompPB->GetInt(kControlSpeedBool);
        bool reversable = fCompPB->GetInt(kPlayBackwardsBool);
        float seekDuration = fCompPB->GetFloat(kSeekTimeFloat);
        bool smartSeek = fCompPB->GetInt(kSmartSeekBool);
        bool noSeek = fCompPB->GetInt(kNoSeekBool);

        plOneShotMod *mod = fMods[node];
        mod->Init(animName, drivable, reversable, seekDuration, smartSeek, noSeek);
        node->AddModifier(mod, IGetUniqueName(node));

        return true;
    }

    return false;
}
hsBool plGameMarkerComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plGameMarkerModifier* markerMod = new plGameMarkerModifier;

    plKey greenKey  = IGetMtlAnimKey(kMarkerGreenAnim, node);
    plKey redKey    = IGetMtlAnimKey(kMarkerRedAnim, node);
    plKey openKey   = IGetMtlAnimKey(kMarkerOpenAnim, node);

    plKey bounceKey = IGetAnimKey(kMarkerBounceNode, kMarkerBounceComp);

    plMaxNode* sndPlaceComp = (plMaxNode*)fCompPB->GetINode(kMarkerSndPlace);
    int sndPlaceIdx = plAudioComp::GetSoundModIdx(sndPlaceComp->ConvertToComponent(), node);

    plMaxNode* sndHitComp = (plMaxNode*)fCompPB->GetINode(kMarkerSndHit);
    int sndHitIdx = plAudioComp::GetSoundModIdx(sndHitComp->ConvertToComponent(), node);

    markerMod->ExportInit(greenKey, redKey, openKey, bounceKey, sndPlaceIdx, sndHitIdx);

    node->AddModifier(markerMod, IGetUniqueName(node));
    return true;
}
hsBool plAvBehaviorSittingComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg)
{
    plMaxNode *detectNode = (plMaxNode*)fCompPB->GetINode(kDetector);
    plComponentBase *detectComp = detectNode ? detectNode->ConvertToComponent() : nil;
    if (detectComp)
    {
        bool hasFrontApproach = fCompPB->GetInt(ParamID(kApproachFront)) ? true : false;
        bool hasLeftApproach = fCompPB->GetInt(ParamID(kApproachLeft)) ? true : false;
        bool hasRightApproach = fCompPB->GetInt(ParamID(kApproachRight)) ? true : false;

        // Create our key here and give it to the detector so it will notify us
        plSittingModifier *sitMod = new plSittingModifier(hasFrontApproach, hasLeftApproach, hasRightApproach);
        if (fCompPB->GetInt(ParamID(kDisableForward)))
            sitMod->fMiscFlags |= plSittingModifier::kDisableForward;

        plKey key = node->AddModifier(sitMod, IGetUniqueName(node));
        detectComp->AddReceiverKey(key);
        fLogicModKeys[node] = key;
    }
    return true;
}
Пример #25
0
bool plClickDragComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plActivatorBaseComponent::PreConvert(node, pErrMsg);
    plLogicModifier *logic = plLogicModifier::ConvertNoRef(fLogicModKeys[node]->GetObjectPtr());

    if (fCompPB->GetInt(kClickDragOneShot))
        logic->SetFlag(plLogicModBase::kOneShot);

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

    // do the same thing for axis animation controllers.
    plAxisAnimModifier* pAxis = new plAxisAnimModifier;
    plKey axisKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), pAxis, loc);
    hsgResMgr::ResMgr()->AddViaNotify(axisKey, new plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef);
    logic->AddNotifyReceiver(axisKey);
    
    fAxisKeys[node] = axisKey;

    return true;
}
Пример #26
0
bool plAnimGroupedComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    bool needSetMaster = fNeedReset;
    if (fNeedReset)
    {
        fForward = new plMsgForwarder;
        plKey forwardKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), fForward, node->GetLocation());

        plNodeRefMsg *refMsg = new plNodeRefMsg(node->GetRoomKey(), plRefMsg::kOnCreate, -1, plNodeRefMsg::kGeneric);
        hsgResMgr::ResMgr()->AddViaNotify(forwardKey, refMsg, plRefFlags::kActiveRef);
    }

    bool ret = plAnimComponentBase::PreConvert(node, pErrMsg);

    plAGMasterMod *mod = fMods[node];

    if (needSetMaster)
        mod->SetIsGroupMaster(true, fForward);
    mod->SetIsGrouped(true);

    fForward->AddForwardKey(mod->GetKey());

    return ret;
}
Пример #27
0
bool plAnimComponentBase::IConvertNodeSegmentBranch(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg)
{
    bool madeAnim = false;
    int i;

    if (IAddTMToAnim(node, anim, pErrMsg))
        madeAnim = true;
    if (IAddLightToAnim(node, anim, pErrMsg))
        madeAnim = true;

    for (i = 0; i < node->NumAttachedComponents(); i++)
    {
        if (node->GetAttachedComponent(i)->AddToAnim(anim, node))
            madeAnim = true;
    }

    if (madeAnim)
    {
        // It has an animation, we're going to need a plAGMod when loading the anim
        if (!node->HasAGMod())
        {
            node->AddModifier(new plAGModifier(ST::string::from_utf8(node->GetName())), IGetUniqueName(node));
        }
        madeAnim = true;
    }
/*
    // let's see if the children have any segments specified...
    int childCount = node->NumberOfChildren();
    for (int i = 0; i < childCount; i++)
    {
        if (IConvertNodeSegmentBranch((plMaxNode *)(node->GetChildNode(i)), anim, pErrMsg))
            madeAnim = true;
    }
*/
    return madeAnim;
}
hsBool plPhysHingeConstraintComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plHingeConstraintMod* HMod = new plHingeConstraintMod;


        plMaxNode* ParentNode = (plMaxNode*)fCompPB->GetINode(kParent);
        if(ParentNode)
        {
            if(!ParentNode->GetPhysicalProps()->IsUsed())
            {
                pErrMsg->Set(true, "Need a Physical Component", "Object %s has a Physical Constraint but no Physical Component. No Constraint was used.", (node->GetName())).Show();
                pErrMsg->Set(false);
            }


        }

        if(!node->GetPhysicalProps()->IsUsed())
        {
            pErrMsg->Set(true, "Need a Physical Component", "Object %s has a Physical Constraint but no Physical Component. No Constraint was used.", (node->GetName())).Show();
            pErrMsg->Set(false);
        }
        
        


        // Using the MotorTorque field, just to keep from creating yet another field in our bloated base class.
        if(fCompPB->GetInt(kParentPinnedBool))
            HMod->SetParentPin(true);

        if(fCompPB->GetInt(kChildPinnedBool))
            HMod->SetChildPin(true);


        if(fCompPB->GetFloat(kFriction))
            HMod->SetHCFriction(0,fCompPB->GetFloat(kFriction));

        //Grab the pivot point from the child translate
        hsPoint3 PP = node->GetLocalToWorld44().GetTranslate();
        hsVector3 PPVector;
        PPVector.Set(PP.fX, PP.fY, PP.fZ);
        HMod->SetPP(PPVector);



        plKey ParentKey  = nil;
        if(fCompPB->GetINode(kParent) && fCompPB->GetInt(kUseParentBool))
            if(((plMaxNode*)fCompPB->GetINode(kParent))->CanConvert())
            {
                plMaxNode* ParentNode = (plMaxNode*)fCompPB->GetINode(kParent);
                ParentKey = ParentNode->GetKey();

            }
            else
            {
                pErrMsg->Set(true, "Ignored Position Value", "Position %s was set to be Ignored. No Physical Proxy selected.", (fCompPB->GetINode(kPositionPtr)->GetName()));
                pErrMsg->Set(false);
                return false;
            }           

        hsVector3 HingeVector;
        if(fCompPB->GetInt(kPositionPtr) == kZAxis)
        {
            HingeVector = node->GetLocalToWorld44().GetAxis(hsMatrix44::kUp);
            HMod->SetHCLimits(kZAxis, 1, fCompPB->GetFloat(kUpperAngle));
            HMod->SetHCLimits(kZAxis, 0, fCompPB->GetFloat(kLowerAngle));


        }       
        else if(fCompPB->GetInt(kPositionPtr) == kYAxis)
        {
            HingeVector = node->GetLocalToWorld44().GetAxis(hsMatrix44::kView);
            HMod->SetHCLimits(kYAxis, 0, -1*fCompPB->GetFloat(kUpperAngle));
            HMod->SetHCLimits(kYAxis, 1, -1*fCompPB->GetFloat(kLowerAngle));

        }
        else
        {
            HingeVector = node->GetLocalToWorld44().GetAxis(hsMatrix44::kRight);
            HMod->SetHCLimits(kXAxis, 0, -1*fCompPB->GetFloat(kUpperAngle));
            HMod->SetHCLimits(kXAxis, 1, -1*fCompPB->GetFloat(kLowerAngle));

        }
        HMod->SetRotationAxis(-1*HingeVector);

        HMod->SetRR(fCompPB->GetFloat(kRebound));
        HMod->SetDamp(fCompPB->GetFloat(kStrength));
        
        node->AddModifier(HMod, IGetUniqueName(node));
        if(ParentKey)
            hsgResMgr::ResMgr()->AddViaNotify( ParentKey, new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kParentIdx, 0 ), plRefFlags::kPassiveRef );
        hsgResMgr::ResMgr()->AddViaNotify( node->GetKey(), new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kChildIdx, 0 ), plRefFlags::kPassiveRef );









    return true;

}
Пример #29
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);
}