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); }
bool plLODAvatarComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { plArmatureComponent::Convert(node, pErrMsg); // Bone LOD stuff int numSoFar = 0; int i; for (i = 0; i < kMaxNumLODLevels; i++) { int numBones = fCompPB->GetInt(ParamID(kGroupTotals), 0, i); plKeyVector *keyVec = new plKeyVector; int j; for (j = 0; j < numBones; j++) { plMaxNode *compNode = (plMaxNode*)fCompPB->GetINode(ParamID(kBoneList), 0, numSoFar + j); if (compNode) { plAGModifier *agMod = compNode->HasAGMod(); keyVec->push_back(agMod ? agMod->GetKey() : nil); } } plArmatureLODMod::ConvertNoRef(fArmMod)->AppendBoneVec(keyVec); numSoFar += numBones; } return true; }
bool plAnimComponentBase::Convert(plMaxNode *node, plErrorMsg *pErrMsg) { fNeedReset = true; if (!IConvertNodeSegmentBranch(node, fAnims[node], pErrMsg)) { // Either we delete it here, or we make it persistent below and the resMgr handles it delete fAnims[node]; fAnims[node] = nil; return false; } if (fCompPB->GetInt(ParamID(kAnimUseGlobal))) { ((plAgeGlobalAnim *)fAnims[node])->SetGlobalVarName((char*)fCompPB->GetStr(ParamID(kAnimGlobalName))); } else // It's an ATCAnim { // If we're on an "(Entire Animation)" segment. The loops won't know their lengths until // after the nodes have been converted and added. So we adjust them here if necessary. ((plATCAnim *)fAnims[node])->CheckLoop(); } IMakePersistent(node, fAnims[node], pErrMsg); return true; }
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; }
void plLODAvatarComponent::RemoveBone(int index) { int group = GetCurGroupIdx(); int boneIdx = GetStartIndex(group) + index; fCompPB->Delete(ParamID(kBoneList), boneIdx, 1); fCompPB->SetValue(ParamID(kGroupTotals), 0, fCompPB->GetInt(ParamID(kGroupTotals), 0, group) - 1, group); }
Texmap* plClothingMtl::GetSubTexmap(int i) { if (i >= 0 && i < plClothingElement::kLayerMax * kMaxTiles) return fBasicPB->GetTexmap(ParamID(LayerToPBIdx[i / kMaxTiles]), 0, i % kMaxTiles); if (i == plClothingElement::kLayerMax * kMaxTiles) return fBasicPB->GetTexmap(ParamID(kThumbnail)); return NULL; }
void plLODAvatarComponent::AddSelectedBone() { int group = GetCurGroupIdx(); int boneIdx = GetEndIndex(group); INode *node = fCompPB->GetINode(ParamID(kLastPick)); fCompPB->Insert(ParamID(kBoneList), boneIdx, 1, &node); fCompPB->SetValue(ParamID(kGroupTotals), 0, fCompPB->GetInt(ParamID(kGroupTotals), 0, group) + 1, group); }
BOOL plAnimComponentProc::DlgProc(TimeValue t, IParamMap2 *pMap, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HWND gWnd = GetDlgItem(hWnd, IDC_ANIM_GLOBAL_LIST); char buff[512]; switch (msg) { case WM_INITDIALOG: { fPB = pMap->GetParamBlock(); fNoteTrackDlg.Init(GetDlgItem(hWnd, IDC_ANIM_NAMES), GetDlgItem(hWnd, IDC_LOOP_NAMES), kAnimName, kAnimLoopName, fPB, fPB->GetOwner()); fNoteTrackDlg.Load(); EnableWindow(GetDlgItem(hWnd, IDC_LOOP_NAMES), fPB->GetInt(kAnimLoop)); FillAgeGlobalComboBox(gWnd, fPB->GetStr(ParamID(kAnimGlobalName))); SetBoxToAgeGlobal(gWnd, fPB->GetStr(ParamID(kAnimGlobalName))); EnableGlobal(hWnd, fPB->GetInt(ParamID(kAnimUseGlobal))); Button_Enable(GetDlgItem(hWnd, IDC_COMP_ANIM_PHYSANIM), HasPhysicalComponent((plComponentBase*)fPB->GetOwner())); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_ANIM_NAMES) { fNoteTrackDlg.AnimChanged(); return TRUE; } else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_LOOP_NAMES) { // Get the new loop name fNoteTrackDlg.LoopChanged(); return TRUE; } else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_ANIM_GLOBAL_LIST) { ComboBox_GetLBText(gWnd, ComboBox_GetCurSel(gWnd), buff); fPB->SetValue(ParamID(kAnimGlobalName), 0, _T(buff)); } // Catch loop button updates else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_COMP_ANIM_LOOP_CKBX) EnableWindow(GetDlgItem(hWnd, IDC_LOOP_NAMES), fPB->GetInt(kAnimLoop)); else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_COMP_ANIM_USE_GLOBAL) { EnableGlobal(hWnd, fPB->GetInt(ParamID(kAnimUseGlobal))); } break; } return false; }
bool plAnimCompressComp::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) { node->SetAnimCompress(fCompPB->GetInt(ParamID(kAnimCompressLevel))); // We use Max's key reduction code, which doesn't seem to match up with its own UI. // Manually using Max's "Reduce Keys" option with a threshold of .01 seems to give // approximately the same results as calling the function ApplyKeyReduction with // a threshold of .0002. I want the UI to appear consistent to the artist, so we // shrug our shoulders and scale down by 50. node->SetKeyReduceThreshold(fCompPB->GetFloat(ParamID(kAnimCompressThreshold)) / 50.f); return true; }
plClothingMtl::plClothingMtl(BOOL loading) : fBasicPB(NULL) { plClothingMtlDesc.MakeAutoParamBlocks(this); Reset(); int i; for (i = 0; i < plClothingMtl::kMaxTiles; i++) { plLayerTex *tex = new plLayerTex; fBasicPB->SetValue(ParamID(kTexmap), 0, tex, i); } fBasicPB->SetValue(ParamID(kThumbnail), 0, new plLayerTex); }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { int id = LOWORD(wParam); int code = HIWORD(wParam); IParamBlock2 *pb = map->GetParamBlock(); HWND cbox = NULL; char* buffer = NULL; int selection; switch (msg) { case WM_INITDIALOG: int j; for (j = 0; j < plClothingMgr::kMaxGroup; j++) { cbox = GetDlgItem(hWnd, IDC_COMP_AVATAR_CLOTHING_GROUP); SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plClothingMgr::GroupStrings[j]); } selection = pb->GetInt(ParamID(plAvatarComponent::kClothingGroup)); SendMessage(cbox, CB_SETCURSEL, selection, 0); for (j = 0; j < plArmatureMod::kMaxBoneBase; j++) { cbox = GetDlgItem(hWnd, IDC_COMP_AVATAR_SKELETON); SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)plArmatureMod::BoneStrings[j]); } selection = pb->GetInt(ParamID(plAvatarComponent::kSkeleton)); SendMessage(cbox, CB_SETCURSEL, selection, 0); return TRUE; case WM_COMMAND: if (id == IDC_COMP_AVATAR_CLOTHING_GROUP) { selection = SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0); pb->SetValue(plAvatarComponent::kClothingGroup, t, selection); return TRUE; } if (id == IDC_COMP_AVATAR_SKELETON) { selection = SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0); pb->SetValue(plAvatarComponent::kSkeleton, t, selection); return TRUE; } break; } return FALSE; }
void plClothingMtl::SetSubTexmap(int i, Texmap *m) { if (i >= 0 && i < plClothingElement::kLayerMax * kMaxTiles) fBasicPB->SetValue(ParamID(LayerToPBIdx[i / kMaxTiles]), 0, m, i % kMaxTiles); if (i == plClothingElement::kLayerMax * kMaxTiles) fBasicPB->SetValue(kThumbnail, 0, m); }
bool plAnimComponentBase::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) { if (node->IsTMAnimated()) { node->SetMovable(true); node->SetForceLocal(true); // // forceLocal on our parent (since keys work in local space) // plMaxNode *parent = (plMaxNode *)node->GetParentNode(); if (!parent->IsRootNode()) { parent->SetForceLocal(true); //char str[512]; //sprintf(str, "Forcing local on '%s' because of animated child '%s'\n",parent->GetName(),node->GetName() ); //OutputDebugString(str); } } if (fCompPB->GetInt(ParamID(kAnimPhysAnim))) SetPhysAnimRecurse(node, pErrMsg); /* int childCount = node->NumberOfChildren(); for (int i = 0; i < childCount; i++) { SetupProperties((plMaxNode *)node->GetChildNode(i), pErrMsg); } */ return true; }
hsBool plFootstepSoundComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) { plGenRefMsg *msg; plArmatureEffectFootSound *effect = new plArmatureEffectFootSound(); // Note: MUST be a hard-coded keyname, since we search for same name in plArmatureMod.cpp hsgResMgr::ResMgr()->NewKey( _TEMP_CONVERT_FROM_LITERAL("FootstepSounds"), effect, node->GetLocation()); int i; for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++) { plMaxNode *compNode = (plMaxNode*)fCompPB->GetINode(ParamID(kSurfaceList), 0, i); if (compNode) { plRandomSoundComponent *rsComp = (plRandomSoundComponent *)compNode->ConvertToComponent(); if (rsComp) { plRandomSoundMod *mod = rsComp->fSoundMods[node]; if (mod != nil) { msg = new plGenRefMsg(effect->GetKey(), plRefMsg::kOnCreate, i, -1); hsgResMgr::ResMgr()->AddViaNotify(mod->GetKey(), msg, plRefFlags::kActiveRef); } } } } // Add it to the scene node's generic list, so that all avatars can access it. plNodeRefMsg* nodeRefMsg = new plNodeRefMsg(node->GetRoomKey(), plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kGeneric); hsgResMgr::ResMgr()->AddViaNotify(effect->GetKey(), nodeRefMsg, plRefFlags::kActiveRef); return true; }
int plLODAvatarComponent::GetStartIndex(int group) { int result = 0; int i; for (i = 0; i < group; i++) result += fCompPB->GetInt(ParamID(kGroupTotals), 0, i); return result; }
void UpdateDisplay(IParamMap2 *pmap) { HWND hWnd = pmap->GetHWnd(); IParamBlock2 *pb = pmap->GetParamBlock(); HWND cbox; cbox = GetDlgItem(hWnd, IDC_CAM_LAYER_UV_SRC); SendMessage(cbox, CB_SETCURSEL, pb->GetInt(plMAXCameraLayer::kUVSource), 0); bool reflect = (pb->GetInt(ParamID(plMAXCameraLayer::kExplicitCam)) == 0); EnableWindow(GetDlgItem(hWnd, IDC_CAM_LAYER_UV_SRC), !reflect); }
bool plObjectFlockerComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) { node->SetDrawable(!fCompPB->GetInt(ParamID(kHideTarget))); node->SetForceLocal(true); plMaxNode* targNode = (plMaxNode*)fCompPB->GetINode(kBoidObject); if (targNode) targNode->SetForceLocal(true); 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; }
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; }
BOOL plFootstepSoundComponentProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { IParamBlock2 *pb = pm->GetParamBlock(); HWND hSurface = GetDlgItem(hWnd, IDC_COMP_FOOTSTEP_SOUND_SURFACE); HWND hPick = GetDlgItem(hWnd, IDC_COMP_FOOTSTEP_SOUND_PICK); INode *curPick = nil; int curSurface = 0; switch (msg) { case WM_INITDIALOG: { int i; for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++) ComboBox_AddString(hSurface, plArmatureEffectsMgr::SurfaceStrings[i]); curSurface = pb->GetInt(ParamID(plFootstepSoundComponent::kSurface)); ComboBox_SetCurSel(hSurface, curSurface); curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curSurface); Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName())); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { if (LOWORD(wParam) == IDC_COMP_FOOTSTEP_SOUND_PICK) { std::vector<Class_ID> cids; cids.push_back(RANDOM_SOUND_COMPONENT_ID); if (plPick::NodeRefKludge(pb, plFootstepSoundComponent::kNodePicker, &cids, true, false)) { curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kNodePicker)); curSurface = pb->GetInt(ParamID(plFootstepSoundComponent::kSurface)); pb->SetValue(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curPick, curSurface); Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName())); } return TRUE; } } else if (LOWORD(wParam) == IDC_COMP_FOOTSTEP_SOUND_SURFACE) { curSurface = ComboBox_GetCurSel(hSurface); curPick = pb->GetINode(ParamID(plFootstepSoundComponent::kSurfaceList), 0, curSurface); pb->SetValue(ParamID(plFootstepSoundComponent::kSurface), 0, curSurface); Button_SetText(hPick, (curPick == nil ? "None" : curPick->GetName())); } } return FALSE; }
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { int id = LOWORD(wParam); int code = HIWORD(wParam); IParamBlock2 *pb = map->GetParamBlock(); HWND cbox = NULL; int selection; switch (msg) { case WM_INITDIALOG: cbox = GetDlgItem(hWnd, IDC_GRASS_WAVE); SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)"1"); SendMessage(cbox, CB_ADDSTRING, 1, (LPARAM)"2"); SendMessage(cbox, CB_ADDSTRING, 2, (LPARAM)"3"); SendMessage(cbox, CB_ADDSTRING, 3, (LPARAM)"4"); selection = pb->GetInt(plGrassComponent::kWave); ISetToWave(selection, hWnd, pb, map); return TRUE; case WM_COMMAND: case CC_SPINNER_CHANGE: int wave = SendMessage(GetDlgItem(hWnd, IDC_GRASS_WAVE), CB_GETCURSEL, 0, 0); if (id == IDC_GRASS_WAVE) { if (wave != pb->GetInt(ParamID(plGrassComponent::kWave))) ISetToWave(wave, hWnd, pb, map); } else if (id == IDC_GRASS_DIST_X || id == IDC_GRASS_DIST_X_SPIN) pb->SetValue(plGrassComponent::kDistXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistX)), wave); else if (id == IDC_GRASS_DIST_Y || id == IDC_GRASS_DIST_Y_SPIN) pb->SetValue(plGrassComponent::kDistYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistY)), wave); else if (id == IDC_GRASS_DIST_Z || id == IDC_GRASS_DIST_Z_SPIN) pb->SetValue(plGrassComponent::kDistZTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistZ)), wave); else if (id == IDC_GRASS_DIR_X || id == IDC_GRASS_DIR_X_SPIN) pb->SetValue(plGrassComponent::kDirXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirX)), wave); else if (id == IDC_GRASS_DIR_Y || id == IDC_GRASS_DIR_Y_SPIN) pb->SetValue(plGrassComponent::kDirYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirY)), wave); else if (id == IDC_GRASS_SPEED || id == IDC_GRASS_SPEED_SPIN) pb->SetValue(plGrassComponent::kSpeedTab, 0, pb->GetFloat(ParamID(plGrassComponent::kSpeed)), wave); return TRUE; } return FALSE; }
void UpdateBoneDisplay(IParamMap2 *pm) { HWND hWnd = pm->GetHWnd(); HWND hList = GetDlgItem(hWnd, IDC_COMP_LOD_AVATAR_BONELIST); IParamBlock2 *pb = pm->GetParamBlock(); ListBox_ResetContent(hList); int group = fComp->GetCurGroupIdx(); int startIdx = fComp->GetStartIndex(group); int endIdx = fComp->GetEndIndex(group); while (startIdx < endIdx) { INode *curNode = pb->GetINode(ParamID(plLODAvatarComponent::kBoneList), 0, startIdx); if (curNode == nil) { fComp->RemoveBone(startIdx); endIdx--; continue; } ListBox_AddString(hList, curNode->GetName()); startIdx++; } }
Control *plPassMtl::GetRuntimeColorController() { return GetParamBlock2Controller(fBasicPB, ParamID(kPassBasRunColor)); }
Control *plPassMtl::GetSpecularColorController() { return GetParamBlock2Controller(fBasicPB, ParamID(kPassBasSpecColor)); }
Control *plPassMtl::GetOpacityController() { return GetParamBlock2Controller(fBasicPB, ParamID(kPassBasOpacity)); }
Control *plPassMtl::GetAmbColorController() { return GetParamBlock2Controller(fBasicPB, ParamID(kPassBasColorAmb)); }
Control *plPassMtl::GetPreshadeColorController() { return GetParamBlock2Controller(fBasicPB, ParamID(kPassBasColor)); }
const char* plPassMtl::GetGlobalVarName() { return fAnimPB->GetStr(ParamID(kPBAnimGlobalName)); }
int plPassMtl::GetUseGlobal() { return fAnimPB->GetInt(ParamID(kPBAnimUseGlobal)); }
Control *plDecalMtl::GetRuntimeColorController() { return GetParamBlock2Controller(fBasicPB, ParamID(kDecalBasRunColor)); }