/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "HeadSpin.h" #include "max.h" #include "resource.h" #include "plComponent.h" #include "plComponentReg.h" #include "../MaxMain/plPlasmaRefMsgs.h" #include "plPickNode.h" #include "../MaxMain/plMaxNode.h" #include "../MaxExport/plExportProgressBar.h" #include "../MaxConvert/hsMaterialConverter.h" #include "hsTypes.h" #include "plTweak.h" #include "hsResMgr.h" #include "../pnMessage/plNodeRefMsg.h" #include "../pnMessage/plObjRefMsg.h" #include "../plDrawable/plDynaFootMgr.h" #include "../plDrawable/plDynaRippleMgr.h" #include "../plDrawable/plDynaRippleVSMgr.h" #include "../plDrawable/plDynaBulletMgr.h" #include "../plDrawable/plDynaPuddleMgr.h" #include "../plDrawable/plDynaTorpedoMgr.h" #include "../plDrawable/plDynaTorpedoVSMgr.h" #include "../plDrawable/plDynaWakeMgr.h" #include "../plDrawable/plCutter.h" #include "../plModifier/plDecalEnableMod.h" #include "../plDrawable/plPrintShape.h" #include "../plDrawable/plActivePrintShape.h" #include "../plSurface/hsGMaterial.h" #include "../plSurface/plLayer.h" #include "plWaterComponent.h" #include "../plDrawable/plWaveSetBase.h" #include "plParticleComponents.h" void DummyCodeIncludeFuncFootPrint() { } const Class_ID FOOTPRINT_COMP_CID(0x5d553f57, 0x42344c5e); const Class_ID RIPPLE_COMP_CID(0x750e1b2a, 0x4ad10f15); const Class_ID PUDDLE_COMP_CID(0x2f800331, 0x640f4914); const Class_ID WAKE_COMP_CID(0x714b6b6b, 0xa937ff4); const Class_ID BULLET_COMP_CID(0x208c05d7, 0x41540df2); const Class_ID TORPEDO_COMP_CID(0x72b85c86, 0xe2b0b40); const Class_ID DIRTY_COMP_CID(0x500f1fd3, 0x508c4486); class plFootPrintComponent : public plComponent { protected: plDynaDecalMgr* fDecalMgr; bool fValid; bool fNotifiesSetup; hsBool ISetupNotifies(plMaxNode* node, plErrorMsg* pErrMsg); hsBool ISetupDecalMgr(plMaxNode* node, plErrorMsg* pErrMsg, plDynaDecalMgr* decalMgr); hsBool ICreateDecalMaterials(plMaxNode* node, plErrorMsg* pErrMsg); hsBool ISetupColorDecalMaterials(plMaxNode* node, plErrorMsg* pErrMsg); hsBool ISetupParticles(plMaxNode* node, plErrorMsg* pErrMsg); static plParticleComponent* IGetParticleComp(INode* node); virtual void IFakeParams(); public: enum { kWidth, kLength, kFadeIn, kFadeOut, kLifeSpan, kLayer, kBlend, kDirtyTime, kNotifies, kIntensity, kParticles, kPartyTime }; enum { kAlpha, kMADD, kAdd, kMult }; plFootPrintComponent(); virtual ~plFootPrintComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool DeInit(plMaxNode *node, plErrorMsg *pErrMsg); static plDynaDecalMgr* GetDecalMgr(INode* node); }; CLASS_DESC(plFootPrintComponent, gFootPrintCompDesc, "Foot Print", "FootPrint", COMP_TYPE_FOOTPRINT, FOOTPRINT_COMP_CID) class plWetProc : public ParamMap2UserDlgProc { public: BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { } return true; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD_NOTIFY) { std::vector cids; cids.push_back(FOOTPRINT_COMP_CID); cids.push_back(RIPPLE_COMP_CID); cids.push_back(PUDDLE_COMP_CID); cids.push_back(WAKE_COMP_CID); IParamBlock2 *pb = map->GetParamBlock(); plPick::Node(pb, plFootPrintComponent::kNotifies, &cids, false, false); map->Invalidate(plFootPrintComponent::kNotifies); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD_PARTICLE) { std::vector cids; cids.push_back(PARTICLE_SYSTEM_COMPONENT_CLASS_ID); IParamBlock2 *pb = map->GetParamBlock(); plPick::Node(pb, plFootPrintComponent::kParticles, &cids, false, false); map->Invalidate(plFootPrintComponent::kParticles); return TRUE; } break; } return false; } void DeleteThis() {} }; static plWetProc gWetProc; ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gFootPrintBk ( plComponent::kBlkComp, _T("FootPrint"), 0, &gFootPrintCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_FOOTPRINT, IDS_COMP_FOOTPRINT, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 400.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_WIDTH, IDC_COMP_FP_WIDTH_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 400.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 1.0, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 10.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, p_default, 30.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.1, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, p_default, 0.25, p_range, 0.1, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); hsBool plFootPrintComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { // If we don't have a valid layer, we're screwed. Throw up a warning // and shutdown. if( !fCompPB->GetTexmap(kLayer) ) { pErrMsg->Set(true, GetINode()->GetName(), "No layer setup. Ignoring Footprint generator").CheckAndAsk(); pErrMsg->Set(false); fValid = false; return true; } fDecalMgr = nil; fValid = true; fNotifiesSetup = false; return true; } hsBool plFootPrintComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { ISetupDecalMgr(node, pErrMsg, TRACKED_NEW plDynaFootMgr); } return true; } hsBool plFootPrintComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; if( !fNotifiesSetup ) ISetupNotifies(node, pErrMsg); // Add this node's object to our DynaDecalMgr. hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefTarget), plRefFlags::kActiveRef); return true; } hsBool plFootPrintComponent::DeInit(plMaxNode *node, plErrorMsg *pErrMsg) { fDecalMgr = nil; return true; } plFootPrintComponent::plFootPrintComponent() : fDecalMgr(nil) { fClassDesc = &gFootPrintCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plFootPrintComponent::~plFootPrintComponent() { } void plFootPrintComponent::IFakeParams() { fCompPB->SetValue(kFadeIn, TimeValue(0), 0.1f); fCompPB->SetValue(kFadeOut, TimeValue(0), fCompPB->GetFloat(kLifeSpan) * 0.25f); } hsBool plFootPrintComponent::ISetupDecalMgr(plMaxNode* node, plErrorMsg* pErrMsg, plDynaDecalMgr* decalMgr) { IFakeParams(); fDecalMgr = decalMgr; plKey mgrKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), fDecalMgr, node->GetLocation()); float width = fCompPB->GetFloat(kWidth) * 1.e-2f; float length = fCompPB->GetFloat(kLength) * 1.e-2f; float wetTime = fCompPB->GetFloat(kDirtyTime); float fadeIn = fCompPB->GetFloat(kFadeIn); float fadeOut = fCompPB->GetFloat(kFadeOut); float lifeSpan = fCompPB->GetFloat(kLifeSpan); float intensity = fCompPB->GetFloat(kIntensity) * 1.e-2f; float partyTime = fCompPB->GetFloat(kPartyTime); const hsScalar kHeightHack = 1.f; fDecalMgr->SetScale(hsVector3(width, length, kHeightHack)); const float kMinFadeOut = 1.e-2f; if( fadeOut > lifeSpan - kMinFadeOut) fadeOut = lifeSpan - kMinFadeOut; if( fadeIn > lifeSpan - fadeOut ) fadeIn = lifeSpan - fadeOut; fDecalMgr->SetWetLength(wetTime); fDecalMgr->SetRampEnd(fadeIn); fDecalMgr->SetDecayStart(lifeSpan - fadeOut); fDecalMgr->SetLifeSpan(lifeSpan); fDecalMgr->SetIntensity(intensity); fDecalMgr->SetPartyTime(partyTime); if( !ICreateDecalMaterials(node, pErrMsg) ) { delete fDecalMgr; fDecalMgr = nil; return fValid = false; } hsgResMgr::ResMgr()->AddViaNotify(mgrKey, TRACKED_NEW plNodeRefMsg(node->GetRoomKey(), plRefMsg::kOnCreate, -1, plNodeRefMsg::kGeneric), plRefFlags::kActiveRef); ISetupParticles(node, pErrMsg); return true; } hsBool plFootPrintComponent::ISetupNotifies(plMaxNode* node, plErrorMsg* pErrMsg) { int num = fCompPB->Count(kNotifies); int i; for( i = 0; i < num; i++ ) { plDynaDecalMgr* slave = GetDecalMgr(fCompPB->GetINode(kNotifies, TimeValue(0), i)); if( slave ) { slave->SetWaitOnEnable(true); fDecalMgr->AddNotify(slave->GetKey()); } } fNotifiesSetup = true; return true; } hsBool plFootPrintComponent::ISetupParticles(plMaxNode* node, plErrorMsg* pErrMsg) { int num = fCompPB->Count(kParticles); if( !num ) return true; int i; for( i = 0; i < num; i++ ) { plParticleComponent* partyComp = IGetParticleComp(fCompPB->GetINode(kParticles, TimeValue(0), i)); if( partyComp && partyComp->NumTargets() ) { plMaxNodeBase* partyNode = nil; const int numTarg = partyComp->NumTargets(); int j; for( j = 0; j < numTarg; j++ ) { partyNode = partyComp->GetTarget(j); if( partyNode ) break; } if( partyNode ) { plSceneObject* obj = partyNode->GetSceneObject(); if( obj ) { hsgResMgr::ResMgr()->AddViaNotify(obj->GetKey(), new plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefPartyObject), plRefFlags::kPassiveRef); } } plConst(int) kNumEmitters(3); partyComp->SetEmitterReserve(kNumEmitters); } } return true; } hsBool plFootPrintComponent::ICreateDecalMaterials(plMaxNode* node, plErrorMsg* pErrMsg) { if( fCompPB->GetInt(kBlend) != kAlpha ) return ISetupColorDecalMaterials(node, pErrMsg); hsGMaterial* matRTShade = hsMaterialConverter::Instance().NonAlphaHackPrint(node, fCompPB->GetTexmap(kLayer), hsGMatState::kBlendAlpha); if( !matRTShade ) return fValid = false; hsgResMgr::ResMgr()->AddViaNotify(matRTShade->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefMatRTShade), plRefFlags::kActiveRef); hsGMaterial* matPreShade = hsMaterialConverter::Instance().AlphaHackPrint(node, fCompPB->GetTexmap(kLayer), hsGMatState::kBlendAlpha); hsgResMgr::ResMgr()->AddViaNotify(matPreShade->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefMatPreShade), plRefFlags::kActiveRef); return true; } hsBool plFootPrintComponent::ISetupColorDecalMaterials(plMaxNode* node, plErrorMsg* pErrMsg) { UInt32 blendFlags = 0; switch( fCompPB->GetInt(kBlend) ) { case kMADD: blendFlags = hsGMatState::kBlendMADD; break; case kAdd: blendFlags = hsGMatState::kBlendAdd; break; case kMult: blendFlags = hsGMatState::kBlendMult; break; default: hsAssert(false, "Unknown blend mode"); blendFlags = hsGMatState::kBlendMADD; // cuz it's my fave. break; } hsGMaterial* matRTShade = hsMaterialConverter::Instance().NonAlphaHackPrint(node, fCompPB->GetTexmap(kLayer), blendFlags); if( blendFlags & hsGMatState::kBlendMult ) { plLayer* layer = plLayer::ConvertNoRef(matRTShade->GetLayer(0)->BottomOfStack()); if( !layer ) return fValid = false; layer->SetBlendFlags(layer->GetBlendFlags() | hsGMatState::kBlendInvertFinalColor); } hsgResMgr::ResMgr()->AddViaNotify(matRTShade->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefMatRTShade), plRefFlags::kActiveRef); return true; } plParticleComponent* plFootPrintComponent::IGetParticleComp(INode* node) { if( !node ) return nil; plComponentBase *comp = ((plMaxNodeBase*)node)->ConvertToComponent(); if( comp == nil ) return nil; if( comp->ClassID() == PARTICLE_SYSTEM_COMPONENT_CLASS_ID ) { plParticleComponent* party = (plParticleComponent*)comp; return party; } return nil; } plDynaDecalMgr* plFootPrintComponent::GetDecalMgr(INode* node) { if( !node ) return nil; plComponentBase *comp = ((plMaxNodeBase*)node)->ConvertToComponent(); if( comp == nil ) return nil; if( (comp->ClassID() == FOOTPRINT_COMP_CID) || (comp->ClassID() == RIPPLE_COMP_CID) || (comp->ClassID() == PUDDLE_COMP_CID) || (comp->ClassID() == WAKE_COMP_CID) ) { plFootPrintComponent* foot = (plFootPrintComponent*)comp; return foot->fDecalMgr; } return nil; } ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// class plRippleComponent : public plFootPrintComponent { protected: virtual void IFakeParams(); public: plRippleComponent(); virtual ~plRippleComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plRippleComponent, gRippleCompDesc, "Ripple", "Ripple", COMP_TYPE_FOOTPRINT, RIPPLE_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gRippleBk ( plComponent::kBlkComp, _T("Ripple"), 0, &gRippleCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_RIPPLE, IDS_COMP_RIPPLE, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_WIDTH, IDC_COMP_FP_WIDTH_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, // p_default, 1.0, // p_range, 0.25, 10.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 0.1, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 3.5, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, // p_default, 5.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.25, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, p_default, 0.25, p_range, 0.1, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); void plRippleComponent::IFakeParams() { fCompPB->SetValue(kLength, TimeValue(0), fCompPB->GetFloat(kWidth)); fCompPB->SetValue(kFadeIn, TimeValue(0), 0.25f); fCompPB->SetValue(kLifeSpan, TimeValue(0), fCompPB->GetFloat(kWidth) * 1.e-2f * 0.5f); fCompPB->SetValue(kFadeOut, TimeValue(0), fCompPB->GetFloat(kLifeSpan) * 0.80f); } hsBool plRippleComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return plFootPrintComponent::SetupProperties(node, pErrMsg); } hsBool plRippleComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { plDynaRippleMgr* ripple = nil; if( node->GetVS() || node->UserPropExists("XXXWaterColor") ) { ripple = TRACKED_NEW plDynaRippleVSMgr; } else { ripple = TRACKED_NEW plDynaRippleMgr; } ISetupDecalMgr(node, pErrMsg, ripple); if( fValid ) { ripple->SetUVWAnim(hsVector3(3.f, 3.f, 3.f), hsVector3(1.f, 1.f, 1.f)); } } return true; } hsBool plRippleComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; if( !fNotifiesSetup ) { plWaveSetBase* waveSet = plWaterComponent::GetWaveSetFromNode(node); if( waveSet ) { plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaRippleVSMgr::kRefWaveSetBase); hsgResMgr::ResMgr()->AddViaNotify(waveSet->GetKey(), refMsg, plRefFlags::kPassiveRef); } ISetupNotifies(node, pErrMsg); } // Add this node's object to our DynaDecalMgr. hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefTarget), plRefFlags::kActiveRef); return true; } plRippleComponent::plRippleComponent() { fClassDesc = &gRippleCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plRippleComponent::~plRippleComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// class plPuddleComponent : public plRippleComponent { protected: public: plPuddleComponent(); virtual ~plPuddleComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plPuddleComponent, gPuddleCompDesc, "Puddle", "Puddle", COMP_TYPE_FOOTPRINT, PUDDLE_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gPuddleBk ( plComponent::kBlkComp, _T("Puddle"), 0, &gPuddleCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_PUDDLE, IDS_COMP_PUDDLE, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_WIDTH, IDC_COMP_FP_WIDTH_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, // p_default, 1.0, // p_range, 0.25, 10.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 0.1, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 3.5, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, // p_default, 5.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.25, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, p_default, 0.25, p_range, 0.1, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); hsBool plPuddleComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return plRippleComponent::SetupProperties(node, pErrMsg); } hsBool plPuddleComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { plDynaRippleMgr* puddle = TRACKED_NEW plDynaPuddleMgr; ISetupDecalMgr(node, pErrMsg, puddle); if( fValid ) { puddle->SetUVWAnim(hsVector3(5.f, 5.f, 5.f), hsVector3(1.f, 1.f, 1.f)); } } return true; } hsBool plPuddleComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; if( !fNotifiesSetup ) ISetupNotifies(node, pErrMsg); // Add this node's object to our DynaDecalMgr. hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefTarget), plRefFlags::kActiveRef); return true; } plPuddleComponent::plPuddleComponent() { fClassDesc = &gPuddleCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plPuddleComponent::~plPuddleComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// class plBulletComponent : public plFootPrintComponent { protected: virtual void IFakeParams(); public: plBulletComponent(); virtual ~plBulletComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plBulletComponent, gBulletCompDesc, "Bullet", "Bullet", COMP_TYPE_FOOTPRINT, BULLET_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gBulletBk ( plComponent::kBlkComp, _T("Bullet"), 0, &gBulletCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_BULLET, IDS_COMP_FP_BULLET, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 400.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_SCALE, IDC_COMP_FP_SCALE_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, // p_default, 100.0, // p_range, 25.0, 400.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 1.0, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 10.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, p_default, 15.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.1, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, // p_default, 10.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, // p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, p_default, 0.25, p_range, 0.1, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); void plBulletComponent::IFakeParams() { fCompPB->SetValue(kLength, TimeValue(0), fCompPB->GetFloat(kWidth)); plFootPrintComponent::IFakeParams(); } hsBool plBulletComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return plFootPrintComponent::SetupProperties(node, pErrMsg); } hsBool plBulletComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { plDynaBulletMgr* bullet = TRACKED_NEW plDynaBulletMgr; ISetupDecalMgr(node, pErrMsg, bullet); } return true; } hsBool plBulletComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; if( !fNotifiesSetup ) ISetupNotifies(node, pErrMsg); // Add this node's object to our DynaDecalMgr. hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefTarget), plRefFlags::kActiveRef); return true; } plBulletComponent::plBulletComponent() { fClassDesc = &gBulletCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plBulletComponent::~plBulletComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// class plTorpedoComponent : public plRippleComponent { protected: virtual void IFakeParams(); public: plTorpedoComponent(); virtual ~plTorpedoComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plTorpedoComponent, gTorpedoCompDesc, "Water Bullet", "WetBullet", COMP_TYPE_FOOTPRINT, TORPEDO_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gTorpedoBk ( plComponent::kBlkComp, _T("Torpedo"), 0, &gTorpedoCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_TORPEDO, IDS_COMP_FP_TORPEDO, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_WIDTH, IDC_COMP_FP_WIDTH_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, // p_default, 1.0, // p_range, 0.25, 10.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 0.1, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 3.5, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, p_default, 5.0, p_range, 0.0, 10.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.25, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, p_default, 0.25, p_range, 0.1, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); void plTorpedoComponent::IFakeParams() { fCompPB->SetValue(kLength, TimeValue(0), fCompPB->GetFloat(kWidth)); fCompPB->SetValue(kFadeIn, TimeValue(0), 0.25f); fCompPB->SetValue(kFadeOut, TimeValue(0), fCompPB->GetFloat(kLifeSpan) * 0.80f); } hsBool plTorpedoComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return plRippleComponent::SetupProperties(node, pErrMsg); } hsBool plTorpedoComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { plDynaRippleMgr* torpedo; if( node->GetVS() ) torpedo = TRACKED_NEW plDynaTorpedoVSMgr; else torpedo = TRACKED_NEW plDynaTorpedoMgr; ISetupDecalMgr(node, pErrMsg, torpedo); if( fValid ) { torpedo->SetUVWAnim(hsVector3(5.f, 5.f, 5.f), hsVector3(1.f, 1.f, 1.f)); } } return true; } hsBool plTorpedoComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return plRippleComponent::Convert(node, pErrMsg); } plTorpedoComponent::plTorpedoComponent() { fClassDesc = &gTorpedoCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plTorpedoComponent::~plTorpedoComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// class plWakeComponent : public plFootPrintComponent { protected: virtual void IFakeParams(); public: plWakeComponent(); virtual ~plWakeComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plWakeComponent, gWakeCompDesc, "Wake", "Wake", COMP_TYPE_FOOTPRINT, WAKE_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gWakeBk ( plComponent::kBlkComp, _T("Wake"), 0, &gWakeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_WAKE, IDS_COMP_FP_WAKE, 0, 0, &gWetProc, plFootPrintComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_WIDTH, IDC_COMP_FP_WIDTH_SPIN, 1.0, end, plFootPrintComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 25.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_LENGTH, IDC_COMP_FP_LENGTH_SPIN, 0.1, end, plFootPrintComponent::kFadeOut, _T("FadeOut"), TYPE_FLOAT, 0, 0, // p_default, 3.5, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_FADEOUT, IDC_COMP_FP_FADEOUT_SPIN, 0.1, end, plFootPrintComponent::kLifeSpan, _T("LifeSpan"), TYPE_FLOAT, 0, 0, // p_default, 5.0, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_LIFESPAN2, IDC_COMP_FP_LIFESPAN_SPIN2, 0.1, end, plFootPrintComponent::kFadeIn, _T("FadeIn"), TYPE_FLOAT, 0, 0, // p_default, 0.25, // p_range, 0.0, 300.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_RAMPEND, IDC_COMP_FP_RAMPEND_SPIN, 0.1, end, plFootPrintComponent::kLayer, _T("Layer"), TYPE_TEXMAP, 0, 0, p_ui, TYPE_TEXMAPBUTTON, IDC_COMP_FP_TEXMAP, end, plFootPrintComponent::kBlend, _T("Blend"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 4, IDC_RADIO_ALPHA, IDC_RADIO_MADD, IDC_RADIO_ADD, IDC_RADIO_MULT, p_vals, plFootPrintComponent::kAlpha, plFootPrintComponent::kMADD, plFootPrintComponent::kAdd, plFootPrintComponent::kMult, p_default, plFootPrintComponent::kAlpha, end, plFootPrintComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, plFootPrintComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plFootPrintComponent::kIntensity, _T("Intensity"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_INTENSITY, IDC_COMP_FP_INTENSITY_SPIN, 1.0, end, plFootPrintComponent::kParticles, _T("Particles"), TYPE_INODE_TAB, 0, 0, 0, // p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS2, 0, 0, IDC_DEL_TARGS2, end, plFootPrintComponent::kPartyTime, _T("PartyTime"), TYPE_FLOAT, 0, 0, // p_default, 0.25, // p_range, 0.1, 5.0, // p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, // IDC_COMP_FP_PARTYTIME, IDC_COMP_FP_PARTYTIME_SPIN, 0.1, end, end ); void plWakeComponent::IFakeParams() { fCompPB->SetValue(kFadeIn, TimeValue(0), 0.25f); fCompPB->SetValue(kLifeSpan, TimeValue(0), fCompPB->GetFloat(kWidth) * 1.e-2f * 0.5f); fCompPB->SetValue(kFadeOut, TimeValue(0), fCompPB->GetFloat(kLifeSpan) * 0.80f); } hsBool plWakeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return plFootPrintComponent::SetupProperties(node, pErrMsg); } hsBool plWakeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; // If we haven't already, create our DynaDecalMgr and stash it away. if( !fDecalMgr ) { plDynaWakeMgr* wake = TRACKED_NEW plDynaWakeMgr; ISetupDecalMgr(node, pErrMsg, wake); if( fValid ) { wake->SetUVWAnim(hsVector3(5.f, 5.f, 5.f), hsVector3(1.f, 1.f, 1.f)); } } return true; } hsBool plWakeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { if( !fValid ) return true; if( !fNotifiesSetup ) ISetupNotifies(node, pErrMsg); // Add this node's object to our DynaDecalMgr. hsgResMgr::ResMgr()->AddViaNotify(node->GetKey(), TRACKED_NEW plGenRefMsg(fDecalMgr->GetKey(), plRefMsg::kOnCreate, 0, plDynaDecalMgr::kRefTarget), plRefFlags::kActiveRef); return true; } plWakeComponent::plWakeComponent() { fClassDesc = &gWakeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plWakeComponent::~plWakeComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// class plDirtyComponent : public plComponent { public: enum { kDecals, kDirtyTime }; protected: public: plDirtyComponent(); virtual ~plDirtyComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plDirtyComponent, gDirtyCompDesc, "Dirty/Wet Region", "Dirty/Wet", COMP_TYPE_FOOTPRINT, DIRTY_COMP_CID) class plDirtyProc : public ParamMap2UserDlgProc { public: BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { } return true; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD_DECAL) { std::vector cids; cids.push_back(FOOTPRINT_COMP_CID); cids.push_back(RIPPLE_COMP_CID); cids.push_back(PUDDLE_COMP_CID); cids.push_back(WAKE_COMP_CID); IParamBlock2 *pb = map->GetParamBlock(); plPick::Node(pb, plDirtyComponent::kDecals, &cids, false, false); map->Invalidate(plDirtyComponent::kDecals); return TRUE; } break; } return false; } void DeleteThis() {} }; static plDirtyProc gDirtyProc; ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gDirtyBk ( plComponent::kBlkComp, _T("Dirty"), 0, &gDirtyCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_DIRTY, IDS_COMP_FP_DIRTY, 0, 0, &gDirtyProc, plDirtyComponent::kDecals, _T("Decals"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, plDirtyComponent::kDirtyTime, _T("DirtyTime"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 300.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FP_DIRTYTIME, IDC_COMP_FP_DIRTYTIME_SPIN, 0.1, end, end ); hsBool plDirtyComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plDirtyComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plDirtyComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { // Check that this node has a physical interface, or all is for nought. // Should throw up a warning if it doesn't have one, seems an easy thing // to miss. if( !node->IsPhysical() ) { pErrMsg->Set(true, node->GetName(), "Has no physical component to notify %s Dirty/Wet component", GetINode()->GetName()).CheckAndAsk(); pErrMsg->Set(false); return true; } plDecalEnableMod* enable = TRACKED_NEW plDecalEnableMod; plKey modKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), enable, node->GetLocation()); int numDecals = fCompPB->Count(kDecals); int i; for( i = 0; i < numDecals; i++ ) { INode* decalNode = fCompPB->GetINode(kDecals, TimeValue(0), i); plDynaDecalMgr* decal = plFootPrintComponent::GetDecalMgr(decalNode); if( decal ) { decal->SetWaitOnEnable(true); enable->AddDecalKey(decal->GetKey()); } } enable->SetWetLength(fCompPB->GetFloat(kDirtyTime)); hsgResMgr::ResMgr()->AddViaNotify(modKey, TRACKED_NEW plObjRefMsg(node->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); return true; } plDirtyComponent::plDirtyComponent() { fClassDesc = &gDirtyCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plDirtyComponent::~plDirtyComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// const Class_ID PRINTSHAPE_COMP_CID(0x208226a1, 0x2a6e67ba); class plPrintShapeComponent : public plComponent { public: enum { kWidth, kLength, kHeight }; protected: public: plPrintShapeComponent(); virtual ~plPrintShapeComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plPrintShapeComponent, gPrintShapeCompDesc, "Print Shape", "PrintShape", COMP_TYPE_FOOTPRINT, PRINTSHAPE_COMP_CID) ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gPrintShapeBk ( plComponent::kBlkComp, _T("PrintShape"), 0, &gPrintShapeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_PRINTSHAPE, IDS_COMP_FP_PRINTSHAPE, 0, 0, NULL, plPrintShapeComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 0.45, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_WIDTH, IDC_COMP_WIDTH_SPIN, 0.1, end, plPrintShapeComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, p_default, 0.9, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_LENGTH, IDC_COMP_LENGTH_SPIN, 0.1, end, plPrintShapeComponent::kHeight, _T("Height"), TYPE_FLOAT, 0, 0, p_default, 1.0, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_HEIGHT, IDC_COMP_HEIGHT_SPIN, 0.1, end, end ); hsBool plPrintShapeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { node->SetForceLocal(true); return true; } hsBool plPrintShapeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plPrintShapeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { plSceneObject* obj = node->GetSceneObject(); if( !obj ) return true; plPrintShape* shape = TRACKED_NEW plPrintShape(); plKey shapeKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), shape, node->GetLocation()); shape->SetWidth(fCompPB->GetFloat(kWidth)); shape->SetLength(fCompPB->GetFloat(kLength)); shape->SetHeight(fCompPB->GetFloat(kHeight)); hsgResMgr::ResMgr()->AddViaNotify(shapeKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef); return true; } plPrintShapeComponent::plPrintShapeComponent() { fClassDesc = &gPrintShapeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plPrintShapeComponent::~plPrintShapeComponent() { } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// const Class_ID ACTIVEPRINTSHAPE_COMP_CID(0x61b52046, 0x787734a5); class plActivePrintShapeComponent : public plComponent { public: enum { kWidth, kLength, kHeight, kNotifies }; protected: public: plActivePrintShapeComponent(); virtual ~plActivePrintShapeComponent(); void DeleteThis() { delete this; } // SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading // of properties on the MaxNode, as it's still indeterminant. virtual hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); virtual hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); }; CLASS_DESC(plActivePrintShapeComponent, gActivePrintShapeCompDesc, "Active Shape", "ActiveShape", COMP_TYPE_FOOTPRINT, ACTIVEPRINTSHAPE_COMP_CID) class plActiveProc : public ParamMap2UserDlgProc { public: BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { } return true; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD_NOTIFY2) { std::vector cids; cids.push_back(FOOTPRINT_COMP_CID); cids.push_back(RIPPLE_COMP_CID); cids.push_back(PUDDLE_COMP_CID); cids.push_back(WAKE_COMP_CID); IParamBlock2 *pb = map->GetParamBlock(); plPick::Node(pb, plActivePrintShapeComponent::kNotifies, &cids, false, false); map->Invalidate(plActivePrintShapeComponent::kNotifies); return TRUE; } break; } return false; } void DeleteThis() {} }; static plActiveProc gActiveProc; ///////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gActivePrintShapeBk ( plComponent::kBlkComp, _T("ActivePrintShape"), 0, &gActivePrintShapeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_FP_ACTIVEPRINTSHAPE, IDS_COMP_FP_ACTIVEPRINTSHAPE, 0, 0, &gActiveProc, plActivePrintShapeComponent::kWidth, _T("Width"), TYPE_FLOAT, 0, 0, p_default, 0.45, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_WIDTH, IDC_COMP_WIDTH_SPIN, 0.1, end, plActivePrintShapeComponent::kLength, _T("Length"), TYPE_FLOAT, 0, 0, p_default, 0.9, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_LENGTH, IDC_COMP_LENGTH_SPIN, 0.1, end, plActivePrintShapeComponent::kHeight, _T("Height"), TYPE_FLOAT, 0, 0, p_default, 1.0, p_range, 0.1, 30.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_HEIGHT, IDC_COMP_HEIGHT_SPIN, 0.1, end, plActivePrintShapeComponent::kNotifies, _T("Notifies"), TYPE_INODE_TAB, 0, 0, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, 0, 0, IDC_DEL_TARGS, end, end ); hsBool plActivePrintShapeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { node->SetForceLocal(true); return true; } hsBool plActivePrintShapeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plActivePrintShapeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { plSceneObject* obj = node->GetSceneObject(); if( !obj ) return true; plActivePrintShape* shape = TRACKED_NEW plActivePrintShape(); plKey shapeKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), shape, node->GetLocation()); shape->SetWidth(fCompPB->GetFloat(kWidth)); shape->SetLength(fCompPB->GetFloat(kLength)); shape->SetHeight(fCompPB->GetFloat(kHeight)); int num = fCompPB->Count(kNotifies); int i; for( i = 0; i < num; i++ ) { plDynaDecalMgr* notify = plFootPrintComponent::GetDecalMgr(fCompPB->GetINode(kNotifies, TimeValue(0), i)); if( notify ) { shape->AddDecalKey(notify->GetKey()); } } hsgResMgr::ResMgr()->AddViaNotify(shapeKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef); return true; } plActivePrintShapeComponent::plActivePrintShapeComponent() { fClassDesc = &gActivePrintShapeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } plActivePrintShapeComponent::~plActivePrintShapeComponent() { } //////////////////////////////////////////////////////////////////////////////////////////////////////