/*==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 "../MaxMain/plMaxNode.h" #include "../MaxExport/plExportProgressBar.h" #include "hsTypes.h" #include "plLODFadeComponent.h" #include "../pfSurface/plFadeOpacityMod.h" #include "../pfSurface/plDistOpacityMod.h" void DummyCodeIncludeFuncLODFade() { } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // LODFadeComponent first, similar and related BlendOnto component further on in file. CLASS_DESC(plLODFadeComponent, gLODFadeCompDesc, "LOD Blend", "LODBlend", COMP_TYPE_GRAPHICS, LODFADE_COMP_CID) ParamBlockDesc2 gLODFadeBk ( plComponent::kBlkComp, _T("LODFade"), 0, &gLODFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_LODFADE, IDS_COMP_LODFADE, 0, 0, NULL, plLODFadeComponent::kHasBase, _T("HasBase"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_HASBASE, end, plLODFadeComponent::kBase, _T("Base"), TYPE_INODE, 0, 0, p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LODFADE_BASE, p_prompt, IDS_COMP_LODFADE_BASE, end, plLODFadeComponent::kDistance, _T("Distance"), TYPE_FLOAT, 0, 0, p_default, 50.0, p_range, 0.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_LODFADE_DISTANCE, IDC_COMP_LODFADE_DISTANCE_SPIN, 1.0, end, plLODFadeComponent::kTransition, _T("Transition"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_LODFADE_TRANSITION, IDC_COMP_LODFADE_TRANSITION_SPIN, 1.0, end, plLODFadeComponent::kFadeBase, _T("FadeBase"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_FADEBASE, p_enable_ctrls, 1, plLODFadeComponent::kBaseFirst, end, plLODFadeComponent::kBaseFirst, _T("BaseFirst"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_LODFADE_BASEFIRST, end, end ); void plLODFadeComponent::ISetToFadeBase(plMaxNode* node, plMaxNode* base, plErrorMsg* pErrMsg) { if( fCompPB->GetInt(kBaseFirst) ) node->AddRenderDependency(base); else base->AddRenderDependency(node); Box3 fade = base->GetFade(); Point3 maxs = fade.Max(); float fadeInStart = fCompPB->GetFloat(kDistance) - fCompPB->GetFloat(kTransition); if( fadeInStart < 0 ) fadeInStart = 0; float fadeInEnd = fCompPB->GetFloat(kDistance); Point3 mins(fadeInStart, fadeInEnd, -1.f); fade = Box3(mins, maxs); base->SetFade(fade); node->SetNoDeferDraw(true); base->SetNoDeferDraw(true); } hsBool plLODFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { if( fCompPB->GetInt(kHasBase) ) { plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBase, TimeValue(0)); if( base ) { if( fCompPB->GetInt(kFadeBase) ) { ISetToFadeBase(node, base, pErrMsg); } else { node->AddRenderDependency(base); node->SetNoDeferDraw(true); } } } Box3 fade = node->GetFade(); Point3 mins = fade.Min(); float fadeOutStart = fCompPB->GetFloat(kDistance); float fadeOutEnd = fadeOutStart + fCompPB->GetFloat(kTransition); Point3 maxs(fadeOutEnd, fadeOutStart, 1.f); fade = Box3(mins, maxs); node->SetFade(fade); return true; } hsBool plLODFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plLODFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plLODFadeComponent::plLODFadeComponent() { fClassDesc = &gLODFadeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // BlendOnto component next. CLASS_DESC(plBlendOntoComponent, gBlendOntoCompDesc, "Blend Onto", "BlendOnto", COMP_TYPE_GRAPHICS, BLENDONTO_COMP_CID) ParamBlockDesc2 gBlendOntoBk ( plComponent::kBlkComp, _T("BlendOnto"), 0, &gBlendOntoCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_BLENDONTO, IDS_COMP_BLENDONTO, 0, 0, NULL, plBlendOntoComponent::kBaseNodes, _T("BaseNodes"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS, p_classID, triObjectClassID, end, plBlendOntoComponent::kSortFaces, _T("SortFaces"), TYPE_BOOL, 0, 0, p_default, TRUE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTO_SORTFACES, end, end ); hsBool plBlendOntoComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { hsBool someBase = false; int numBase = fCompPB->Count(kBaseNodes); int i; for( i = 0; i < numBase; i++ ) { plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBaseNodes, TimeValue(0), i); if( base ) { node->AddRenderDependency(base); node->SetNoDeferDraw(true); if( !fCompPB->GetInt(kSortFaces) ) node->SetNoFaceSort(true); someBase = true; } } if( !someBase ) { node->SetBlendToFB(true); } return true; } hsBool plBlendOntoComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plBlendOntoComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plBlendOntoComponent::plBlendOntoComponent() { fClassDesc = &gBlendOntoCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // BlendOntoAdv component next. CLASS_DESC(plBlendOntoAdvComponent, gBlendOntoAdvCompDesc, "Blend Onto Advanced", "BlendOntoAdv", COMP_TYPE_GRAPHICS, BLENDONTOADV_COMP_CID) ParamBlockDesc2 gBlendOntoAdvBk ( plComponent::kBlkComp, _T("BlendOntoAdv"), 0, &gBlendOntoAdvCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_BLENDONTOADV, IDS_COMP_BLENDONTOADV, 0, 0, NULL, plBlendOntoAdvComponent::kBaseNodes, _T("BaseNodes"), TYPE_INODE_TAB, 0, P_CAN_CONVERT, 0, p_ui, TYPE_NODELISTBOX, IDC_LIST_TARGS, IDC_ADD_TARGS, 0, IDC_DEL_TARGS, p_classID, triObjectClassID, end, plBlendOntoAdvComponent::kSortFaces, _T("SortFaces"), TYPE_BOOL, 0, 0, p_default, TRUE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_SORTFACES, end, plBlendOntoAdvComponent::kSortObjects, _T("SortObjects"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_SORTOBJECTS, end, plBlendOntoAdvComponent::kOntoBlending, _T("OntoBlending"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BLENDONTOADV_ONTOBLENDING, end, end ); hsBool plBlendOntoAdvComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { hsBool someBase = false; int numBase = fCompPB->Count(kBaseNodes); int i; for( i = 0; i < numBase; i++ ) { plMaxNode* base = (plMaxNode*)fCompPB->GetINode(kBaseNodes, TimeValue(0), i); if( base ) { node->AddRenderDependency(base); if( !fCompPB->GetInt(kOntoBlending) ) node->SetNoDeferDraw(true); if( !fCompPB->GetInt(kSortFaces) ) node->SetNoFaceSort(true); someBase = true; } } if( !someBase ) { node->SetBlendToFB(true); } return true; } hsBool plBlendOntoAdvComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plBlendOntoAdvComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plBlendOntoAdvComponent::plBlendOntoAdvComponent() { fClassDesc = &gBlendOntoAdvCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // Force drawing before the avatar. const Class_ID B4AV_COMP_CID(0x14536d5b, 0x17dc623b); class plB4AvComponent : public plComponent { public: plB4AvComponent(); 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(plB4AvComponent, gB4AvCompDesc, "Draw B4 Avatar", "B4Av", COMP_TYPE_GRAPHICS, B4AV_COMP_CID) ParamBlockDesc2 gB4AvBk ( plComponent::kBlkComp, _T("B4Av"), 0, &gB4AvCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_SORT_AS_OPAQUE, IDS_COMP_SORT_AS_OPAQUE, 0, 0, NULL, end ); hsBool plB4AvComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { node->SetSortAsOpaque(true); return true; } hsBool plB4AvComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plB4AvComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plB4AvComponent::plB4AvComponent() { fClassDesc = &gB4AvCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // DistFadeComponent - just feeding them a bit more rope. CLASS_DESC(plDistFadeComponent, gDistFadeCompDesc, "Distance Fade", "DistFade", COMP_TYPE_GRAPHICS, DISTFADE_COMP_CID) ParamBlockDesc2 gDistFadeBk ( plComponent::kBlkComp, _T("DistFade"), 0, &gDistFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_DISTFADE, IDS_COMP_DISTFADE, 0, 0, NULL, plDistFadeComponent::kFadeInActive, _T("FadeInActive"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTFADE_IN_ACTIVE, p_enable_ctrls, 2, plDistFadeComponent::kFadeInStart, plDistFadeComponent::kFadeInEnd, end, plDistFadeComponent::kFadeInStart, _T("FadeInStart"), TYPE_FLOAT, 0, 0, p_default, 5.0, p_range, 0.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_DISTFADE_INSTART, IDC_COMP_DISTFADE_INSTART_SPIN, 1.0, end, plDistFadeComponent::kFadeInEnd, _T("FadeInEnd"), TYPE_FLOAT, 0, 0, p_default, 10.0, p_range, 0.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_DISTFADE_INEND, IDC_COMP_DISTFADE_INEND_SPIN, 1.0, end, plDistFadeComponent::kFadeOutActive, _T("FadeOutActive"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_DISTFADE_OUT_ACTIVE, p_enable_ctrls, 2, plDistFadeComponent::kFadeOutStart, plDistFadeComponent::kFadeOutEnd, end, plDistFadeComponent::kFadeOutStart, _T("FadeOutStart"), TYPE_FLOAT, 0, 0, p_default, 50.0, p_range, 0.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_DISTFADE_OUTSTART, IDC_COMP_DISTFADE_OUTSTART_SPIN, 1.0, end, plDistFadeComponent::kFadeOutEnd, _T("FadeOutEnd"), TYPE_FLOAT, 0, 0, p_default, 100.0, p_range, 0.0, 1000.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_DISTFADE_OUTEND, IDC_COMP_DISTFADE_OUTEND_SPIN, 1.0, end, end ); hsBool plDistFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { // If we're turned off, just return. if( !fCompPB->GetInt(kFadeInActive) && !fCompPB->GetInt(kFadeOutActive) ) return true; Box3 fade; Point3 mins(0.f, 0.f, 0.f); Point3 maxs(0.f, 0.f, 0.f); if( fCompPB->GetInt(kFadeInActive) ) { mins[0] = fCompPB->GetFloat(kFadeInStart); mins[1] = fCompPB->GetFloat(kFadeInEnd); } if( fCompPB->GetInt(kFadeOutActive) ) { maxs[0] = fCompPB->GetFloat(kFadeOutStart); maxs[1] = fCompPB->GetFloat(kFadeOutEnd); } // We're not really sure how the artist has artistically interpreted // the parameters. What we want is: // Nearest point where object starts to fade in == mins[0] // Nearest point where object is opaque == mins[1] // Farthest point where object is opaque == maxs[1] // Farthest point where object fades out completely = maxs[0] // // If the artist says they want it to start off opaque, fade out, then // fade back in once it's far away, we'll explain in person why that's stupid, // and in the meantime prevent them from doing that by assuming they just // have the parameter order flipped. // // So, they've either given us 2 distances or 2 pairs of distances. // If they've just given 2 distances, we use as is, // but if they've given 2 pairs, we have to arrange them to fit the // above model. // // So first thing to do is figure out how many (valid) distances we have. if( (mins[0] == 0) && (mins[1] == 0) && (maxs[0] == 0) && (maxs[1] == 0) ) { // Okay, they gave no valid distances. Just pretend we were never here. return true; } if( (mins[0] == 0) && (mins[1] == 0) ) { // maxs must be valid, just go with them. fade = IFadeFromPoint(maxs); } else if( (maxs[0] == 0) && (maxs[1] == 0) ) { // mins must be valid, just go with them. fade = IFadeFromPoint(mins); } else { // They're both "valid". Give it a shot. fade = IFadeFromPair(mins, maxs); } node->SetFade(fade); return true; } void plDistFadeComponent::ISwap(float& p0, float& p1) { float t = p0; p0 = p1; p1 = t; } Box3 plDistFadeComponent::IFadeFromPoint(Point3& mins) { Point3 maxs(0.f, 0.f, 0.f); if( mins[0] < mins[1] ) mins[2] = -1.f; else if( mins[0] > mins[1] ) mins[2] = 1.f; else mins[2] = 0; return Box3(mins, maxs); } Box3 plDistFadeComponent::IFadeFromPair(Point3& mins, Point3& maxs) { if( mins[0] > maxs[0] ) { ISwap(mins[0], maxs[0]); ISwap(mins[1], maxs[1]); } if( mins[0] > mins[1] ) { ISwap(mins[0], mins[1]); } if( maxs[0] < maxs[1] ) { // Poor confused bastard, take a guess what he wants. ISwap(maxs[0], maxs[1]); } if( mins[0] < mins[1] ) mins[2] = -1.f; else mins[2] = 0; if( maxs[0] > maxs[1] ) maxs[2] = 1.f; else maxs[2] = 0; return Box3(mins, maxs); } hsBool plDistFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plDistFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plDistFadeComponent::plDistFadeComponent() { fClassDesc = &gDistFadeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // LOS Fade component next. class plLOSFadeComponent : public plComponent { public: enum { kBoundsCenter, kFadeInTime, kFadeOutTime }; public: plLOSFadeComponent(); 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(plLOSFadeComponent, gLOSFadeCompDesc, "LOS Fade", "LOSFade", COMP_TYPE_GRAPHICS, LOSFADE_COMP_CID) ParamBlockDesc2 gLOSFadeBk ( plComponent::kBlkComp, _T("LOSFade"), 0, &gLOSFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_LOSFADE, IDS_COMP_LOSFADE, 0, 0, NULL, plLOSFadeComponent::kBoundsCenter, _T("BoundsCenter"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_BOUNDSCENTER, end, plLOSFadeComponent::kFadeInTime, _T("kFadeInTime"), TYPE_FLOAT, 0, 0, p_default, 0.5, p_range, 0.0, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FADEINTIME, IDC_COMP_FADEINTIME_SPIN, 1.0, end, plLOSFadeComponent::kFadeOutTime, _T("kFadeOutTime"), TYPE_FLOAT, 0, 0, p_default, 1.0, p_range, 0.0, 5.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_FADEOUTTIME, IDC_COMP_FADEOUTTIME_SPIN, 1.0, end, end ); hsBool plLOSFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { node->SetForceMatShade(true); node->SetForceLocal(true); node->SetForceMaterialCopy(true); return true; } hsBool plLOSFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plLOSFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { plFadeOpacityMod* fade = TRACKED_NEW plFadeOpacityMod; if( fCompPB->GetInt(kBoundsCenter) ) fade->SetFlag(plFadeOpacityMod::kBoundsCenter); else fade->ClearFlag(plFadeOpacityMod::kBoundsCenter); fade->SetFadeUp(fCompPB->GetFloat(kFadeInTime)); fade->SetFadeDown(fCompPB->GetFloat(kFadeOutTime)); node->AddModifier(fade, node->GetKey()->GetName()); return true; } plLOSFadeComponent::plLOSFadeComponent() { fClassDesc = &gLOSFadeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // GZ Marker Fade component next. const Class_ID GZFADE_COMP_CID(0x27173270, 0x4f4486f); class plGZFadeComponent : public plComponent { public: enum { kOpaque, kTransp }; public: plGZFadeComponent(); 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(plGZFadeComponent, gGZFadeCompDesc, "GZ Fade", "GZFade", COMP_TYPE_GRAPHICS, GZFADE_COMP_CID) ParamBlockDesc2 gGZFadeBk ( plComponent::kBlkComp, _T("GZFade"), 0, &gGZFadeCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_GZFADE, IDS_COMP_GZ_FADE, 0, 0, NULL, plGZFadeComponent::kOpaque, _T("kOpaque"), TYPE_FLOAT, 0, 0, p_default, 15.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_GZ_OPAQUE, IDC_COMP_GZ_OPAQUE_SPIN, 1.0, end, plGZFadeComponent::kTransp, _T("kTransp"), TYPE_FLOAT, 0, 0, p_default, 20.0, p_range, 0.0, 100.0, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_COMP_GZ_TRANSP, IDC_COMP_GZ_TRANSP_SPIN, 1.0, end, end ); hsBool plGZFadeComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { float opaq = fCompPB->GetFloat(kOpaque); float transp = fCompPB->GetFloat(kTransp); pErrMsg->Set(transp <= opaq, node->GetName(), "Distance obj goes transparent must be greater than distance it's opaque").CheckAndAsk(); pErrMsg->Set(false); node->SetForceMatShade(true); node->SetForceLocal(true); node->SetForceMaterialCopy(true); return true; } hsBool plGZFadeComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plGZFadeComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { plDistOpacityMod* fade = TRACKED_NEW plDistOpacityMod; float opaq = fCompPB->GetFloat(kOpaque); float transp = fCompPB->GetFloat(kTransp); fade->SetFarDist(opaq, transp); node->AddModifier(fade, node->GetKey()->GetName()); return true; } plGZFadeComponent::plGZFadeComponent() { fClassDesc = &gGZFadeCompDesc; fClassDesc->MakeAutoParamBlocks(this); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // Force dynamic material - keeps the material colors from getting burnt into the verts. const Class_ID DYNMAT_COMP_CID(0x2ea4671f, 0x163b12ac); class plDynMatComponent : public plComponent { public: enum { kOpaque, kTransp }; public: plDynMatComponent(); 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(plDynMatComponent, gDynMatCompDesc, "Force Dyn Mat", "DynMat", COMP_TYPE_GRAPHICS, DYNMAT_COMP_CID) ParamBlockDesc2 gDynMatBk ( plComponent::kBlkComp, _T("DynMat"), 0, &gDynMatCompDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, IDD_COMP_DYNMAT, IDS_COMP_DYNMAT, 0, 0, NULL, end ); hsBool plDynMatComponent::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg) { node->SetForceMatShade(true); return true; } hsBool plDynMatComponent::PreConvert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } hsBool plDynMatComponent::Convert(plMaxNode* node, plErrorMsg* pErrMsg) { return true; } plDynMatComponent::plDynMatComponent() { fClassDesc = &gDynMatCompDesc; fClassDesc->MakeAutoParamBlocks(this); }