You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

790 lines
23 KiB

/*==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 <http://www.gnu.org/licenses/>.
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);
}