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.
2015 lines
76 KiB
2015 lines
76 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/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
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" |
|
|
|
// singular |
|
#include "plPhysicalComponents.h" |
|
|
|
// local |
|
#include "plComponentReg.h" |
|
#include "resource.h" |
|
|
|
// global |
|
#include "hsResMgr.h" |
|
|
|
// other |
|
#include "plPhysical/plSimDefs.h" |
|
#include "plPhysicsGroups.h" |
|
|
|
#include "MaxMain/plMaxNode.h" |
|
#include "MaxMain/plPhysicalProps.h" |
|
#include "MaxMain/plPlasmaRefMsgs.h" |
|
|
|
#include "plPhysical/plCollisionDetector.h" |
|
#include "pnMessage/plObjRefMsg.h" |
|
#include "plMessage/plSwimMsg.h" |
|
#include "plAvatar/plSwimRegion.h" |
|
#include "plMessage/plRideAnimatedPhysMsg.h" |
|
|
|
///////////////////////////////////////////////////////////////// |
|
// |
|
// THE DUMMY |
|
// |
|
///////////////////////////////////////////////////////////////// |
|
|
|
// Necessary to keep the compiler from throwing away this file. |
|
void DummyCodeIncludeFuncPhys() |
|
{ |
|
} |
|
|
|
///////////////////////////////////////////////////////////////// |
|
// |
|
// plPhysicCoreComponent |
|
// |
|
///////////////////////////////////////////////////////////////// |
|
|
|
// SetupProperties ----------------------------------------------------------------- |
|
// ---------------- |
|
hsBool plPhysicCoreComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
// PreConvert ---------------------------------------------------------------- |
|
// ----------- |
|
hsBool plPhysicCoreComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
// IFixBounds -------------------------- |
|
// ----------- |
|
void plPhysicCoreComponent::IFixBounds() |
|
{ |
|
if (fCompPB->GetInt(kBoundCondRadio) == 0) |
|
{ |
|
// zero is a bad value left over from an old version of the GUI: upgrade in place |
|
fCompPB->Reset(kBoundCondRadio); // reset to default |
|
} |
|
} |
|
|
|
// IGetProxy ---------------------------------------------------------------- |
|
// ---------- |
|
hsBool plPhysicCoreComponent::IGetProxy(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
if (fCompPB->GetInt(kCustomBoundField)) |
|
{ |
|
plMaxNode *boundNode = (plMaxNode*)fCompPB->GetINode(kCustomBoundListStuff); |
|
if (boundNode && boundNode->CanConvert()) |
|
return node->GetPhysicalProps()->SetProxyNode(boundNode, node, pErrMsg); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
// Convert ---------------------------------------------------------------- |
|
// -------- |
|
hsBool plPhysicCoreComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
//! Global Accessor Class, used in ParamBlock2 processing. |
|
/*! |
|
|
|
When one of our parameters that is a ref changes, send out the component ref |
|
changed message. Normally, messages from component refs are ignored since |
|
they pass along all the messages of the ref, which generates a lot of false |
|
converts. |
|
*/ |
|
|
|
class plPhysCoreAccessor : public PBAccessor |
|
{ |
|
public: |
|
void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t) |
|
{ |
|
if (id == plPhysicCoreComponent::kCustomBoundListStuff) |
|
{ |
|
plComponentBase *comp = (plComponentBase*)owner; |
|
comp->NotifyDependents(FOREVER, PART_ALL, REFMSG_USER_COMP_REF_CHANGED); |
|
} |
|
} |
|
}; |
|
plPhysCoreAccessor gPhysCoreAccessor; |
|
/* |
|
//! Physics Debug Component Class |
|
class plPhysDebugComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysDebugComponent(); |
|
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables); |
|
}; |
|
*/ |
|
OBSOLETE_CLASS(plPhysDebugComponent, gPhysDebugDesc, "Physics Debug", "PhysDebug", COMP_TYPE_PHYSICAL, PHYSICS_DEBUG_CID) |
|
|
|
enum |
|
{ |
|
kPhysMain, |
|
kPhysMember, |
|
kPhysBounce, |
|
kPhysReport, |
|
}; |
|
/* |
|
ParamBlockDesc2 gPhysicalBk |
|
( |
|
plComponent::kBlkComp, _T("physicsDebug"), 0, &gPhysDebugDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
4, |
|
kPhysMain, IDD_COMP_PHYSICAL, IDS_COMP_PHYS_DEBUG, 0, 0, NULL, |
|
kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
kPhysReport, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_REPORT, 0, APPENDROLL_CLOSED, &gReportGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kMass, _T("Mass"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 500.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYSICAL_EDIT1, IDC_COMP_PHYSICAL_SPIN1, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYSICAL_EDIT2, IDC_COMP_PHYSICAL_SPIN2, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYSICAL_EDIT3, IDC_COMP_PHYSICAL_SPIN3, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartForceX, _T("StartForceX"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3SF_EDIT1,IDC_COMP_PHYSICAL_P3SF_SPIN1, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartForceY, _T("StartForceY"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3SF_EDIT2,IDC_COMP_PHYSICAL_P3SF_SPIN2, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartForceZ, _T("StartForceZ"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3SF_EDIT3,IDC_COMP_PHYSICAL_P3SF_SPIN3, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartTorqueX, _T("StartTorqueX"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3ST_EDIT1,IDC_COMP_PHYSICAL_P3ST_SPIN1, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartTorqueY, _T("StartTorqueY"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3ST_EDIT2,IDC_COMP_PHYSICAL_P3ST_SPIN2, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartTorqueZ, _T("StartTorqueZ"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0f, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_COMP_PHYSICAL_P3ST_EDIT3,IDC_COMP_PHYSICAL_P3ST_SPIN3, 0.1f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundListStuff, _T("UserBoundChoice"), TYPE_INODE, 0, 0, |
|
p_ui, kPhysMain, TYPE_PICKNODEBUTTON, IDC_COMP_PHYS_PICKSTATE_BASE, |
|
p_sclassID, GEOMOBJECT_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
p_accessor, &gPhysCoreAccessor, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundField, _T("UserBoundCheckBx"), TYPE_BOOL, 0, 0, |
|
p_default, false, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_CUSTOMCHK, |
|
p_enable_ctrls, 1, plPhysicCoreComponent::kCustomBoundListStuff, |
|
end, |
|
|
|
plPhysicCoreComponent::kLOSChkBx, _T("LOSChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_CHECK_LOS, |
|
end, |
|
|
|
plPhysicCoreComponent::kAlignProxyShape, _T("AlignShapeChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_ALIGN_SHAPE_BOOL, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kReportGroups, _T("memberGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kGroup, _T("group"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysDebugComponent::plPhysDebugComponent() |
|
{ |
|
fClassDesc = &gPhysDebugDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
void plPhysDebugComponent::CollectNonDrawables(INodeTab& nonDrawables) |
|
{ |
|
if (fCompPB->GetInt(kCustomBoundField)) |
|
{ |
|
INode* boundsNode = fCompPB->GetINode(kCustomBoundListStuff); |
|
if( boundsNode ) |
|
nonDrawables.Append(1, &boundsNode); |
|
} |
|
} |
|
|
|
|
|
hsBool plPhysDebugComponent::SetupProperties(plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
plPhysicalProps *physProps = node->GetPhysicalProps(); |
|
|
|
physProps->SetMass(fCompPB->GetFloat(kMass), node, errMsg); |
|
|
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), node, errMsg); |
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), node, errMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), node, errMsg); |
|
if(fCompPB->GetInt(kLOSChkBx)) |
|
physProps->SetLOSBlockCamera(true, node, errMsg); // *** we really need to have four check boxes now.... |
|
physProps->SetPinned(false, node, errMsg); |
|
physProps->SetAlignToOwner(fCompPB->GetInt(kAlignProxyShape) != 0, node, errMsg); |
|
|
|
|
|
physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD), node, errMsg); |
|
physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups_DEAD), node, errMsg); |
|
physProps->SetReportGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kReportGroups), node, errMsg); |
|
|
|
return IGetProxy(node, errMsg); |
|
} |
|
*/ |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plPhysTerrainComponent |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
class plPhysTerrainComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysTerrainComponent(); |
|
hsBool SetupProperties(plMaxNode* node,plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables); |
|
}; |
|
|
|
|
|
CLASS_DESC(plPhysTerrainComponent, gPhysTerrainDesc, "Terrain", "Terrain", COMP_TYPE_PHYSICAL, PHYSICS_TERRAIN_CID) |
|
|
|
|
|
ParamBlockDesc2 gPhysTerrainBk |
|
( |
|
plComponent::kBlkComp, _T("Terrain"), 0, &gPhysTerrainDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_TERRAIN, IDS_COMP_PHYS_TERRAIN, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT2, IDC_COMP_PHYS_TERRAIN_SPIN2, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundListStuff, _T("UserBoundChoice"), TYPE_INODE, 0, 0, |
|
p_ui, kPhysMain, TYPE_PICKNODEBUTTON, IDC_COMP_PHYS_PICKSTATE_TERRAIN, |
|
p_sclassID, GEOMOBJECT_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_TERRAIN, |
|
p_accessor, &gPhysCoreAccessor, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundField, _T("UserBoundCheckBx"), TYPE_BOOL, 0, 0, |
|
p_default, false, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_CUSTOMCHK, |
|
p_enable_ctrls, 1, plPhysicCoreComponent::kCustomBoundListStuff, |
|
end, |
|
|
|
plPhysicCoreComponent::kAlignProxyShape, _T("AlignShapeChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_ALIGN_SHAPE_BOOL, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysTerrainComponent::plPhysTerrainComponent() |
|
{ |
|
fClassDesc = &gPhysTerrainDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
void plPhysTerrainComponent::CollectNonDrawables(INodeTab& nonDrawables) |
|
{ |
|
if (fCompPB->GetInt(kCustomBoundField)) |
|
{ |
|
INode* boundsNode = fCompPB->GetINode(kCustomBoundListStuff); |
|
if( boundsNode ) |
|
nonDrawables.Append(1, &boundsNode); |
|
} |
|
} |
|
|
|
void ValidateGroups(IParamBlock2* pb, int memberID, int bounceID, plComponent* comp, plErrorMsg* pErrMsg) |
|
{ |
|
uint32_t defMember = pb->GetParamDef(memberID).def.i; |
|
uint32_t member = pb->GetInt(memberID); |
|
|
|
uint32_t defCollide = pb->GetParamDef(bounceID).def.i; |
|
uint32_t collide = pb->GetInt(bounceID); |
|
|
|
if (defMember != member || defCollide != collide) |
|
{ |
|
pErrMsg->Set(true, |
|
"Physics Conflict", |
|
"The legacy physical component \"%s\" has non-default member or collide groups.\nPlease recreate it.", |
|
comp->GetINode()->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
} |
|
} |
|
|
|
hsBool plPhysTerrainComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
|
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), pNode, pErrMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), pNode, pErrMsg); |
|
physProps->SetAlignToOwner(fCompPB->GetInt(kAlignProxyShape) != 0, pNode, pErrMsg); |
|
|
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupStatic, pNode, pErrMsg); |
|
|
|
physProps->SetLOSBlockCamera(true, pNode, pErrMsg); |
|
physProps->SetLOSBlockUI(true, pNode, pErrMsg); |
|
physProps->SetLOSAvatarWalkable(true, pNode, pErrMsg); |
|
|
|
return IGetProxy(pNode, pErrMsg); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plProxyTerrainComponent |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
class plProxyTerrainComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plProxyTerrainComponent(); |
|
hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plProxyTerrainComponent, gProxyTerrainDesc, "Proxy Terrain", "ProxyTerrain", COMP_TYPE_PHYSICAL, PHYSICS_INVISIBLE_CID) |
|
|
|
ParamBlockDesc2 gPhysInvisibleBk |
|
( |
|
plComponent::kBlkComp, _T("ProxyTerrain"), 0, &gProxyTerrainDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_PROXY_TERRAIN, IDS_COMP_PHYS_PROXY_TERRAIN, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kUILOSChkBx, _T("UILOSChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_CHECK_LOS, |
|
end, |
|
|
|
plPhysicCoreComponent::kCamLOSChkBx, _T("CamLOSChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_CHECK_LOS2, |
|
end, |
|
|
|
plPhysicCoreComponent::kCamAvoidChkBx, _T("CamLOSChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_CHECK_LOS3, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_INVIS_BOUNCE_EDIT, IDC_COMP_PHYS_INVIS_BOUNCE_SPIN, 0.0001f, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plProxyTerrainComponent::plProxyTerrainComponent() |
|
{ |
|
fClassDesc = &gProxyTerrainDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plProxyTerrainComponent::SetupProperties(plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
IFixBounds(); |
|
node->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = node->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, node, errMsg); |
|
|
|
if (fCompPB->GetInt(kUILOSChkBx) || fCompPB->GetInt(kCamLOSChkBx)) |
|
{ |
|
// XXX physProps->SetAllowLOS(false, pNode, pErrMsg); |
|
|
|
|
|
if (fCompPB->GetInt(kUILOSChkBx)) |
|
physProps->SetLOSBlockUI(true, node, errMsg); |
|
if (fCompPB->GetInt(kCamLOSChkBx)) |
|
physProps->SetLOSBlockCamera(true, node, errMsg); |
|
if (fCompPB->GetInt(kCamAvoidChkBx)) |
|
physProps->SetCameraAvoidFlag(true, node, errMsg); |
|
} |
|
|
|
physProps->SetLOSAvatarWalkable(true, node, errMsg); |
|
|
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), node, errMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), node, errMsg); |
|
|
|
physProps->SetGroup(plSimDefs::kGroupStatic, node, errMsg); |
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, errMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), node, errMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), node, errMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plCameraBlockerComponent |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
class plCameraBlockerComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plCameraBlockerComponent(); |
|
|
|
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plCameraBlockerComponent, gCameraBlockerDesc, "(ex) Camera Blocker", "CameraBlocker", COMP_TYPE_PHYSICAL, PHYS_CAMERA_BLOCK_CID) |
|
|
|
ParamBlockDesc2 gCameraOccludeBlock |
|
( |
|
plComponent::kBlkComp, _T("cameraBlocker"), 0, &gCameraBlockerDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_CAMERA_OCCLUDER, IDS_CAMERA_OCCLUDERS, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
plPhysicCoreComponent::kBoundCondRadio, _T("BlockerBounds"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plCameraBlockerComponent::plCameraBlockerComponent() |
|
{ |
|
fClassDesc = &gCameraBlockerDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plCameraBlockerComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
physProps->SetFriction(0, pNode, pErrMsg); |
|
// physProps->SetAllowLOS(false, pNode, pErrMsg); |
|
physProps->SetLOSBlockCamera(true, pNode, pErrMsg); |
|
// physProps->SetUILOSFlag(true, pNode, pErrMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), pNode, pErrMsg); |
|
|
|
physProps->SetGroup(plSimDefs::kGroupLOSOnly, pNode, pErrMsg); |
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plPhysSimpleComponent |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
class plPhysSimpleComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysSimpleComponent(); |
|
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables); |
|
}; |
|
|
|
CLASS_DESC(plPhysSimpleComponent, gPhysSimpleDesc, "Simple", "Simple", COMP_TYPE_PHYSICAL, PHYSICS_SIMPLE_CID) |
|
|
|
ParamBlockDesc2 gPhysSimpleBk |
|
( |
|
plComponent::kBlkComp, _T("Simple"), 0, &gPhysSimpleDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_SIMPLE, IDS_COMP_PHYS_SIMPLE, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kMass, _T("Mass"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 1.0, |
|
p_range, 0.001, 500.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_SIMP_EDIT1, IDC_COMP_PHYS_SIMP_SPIN1, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_SIMP_EDIT2, IDC_COMP_PHYS_SIMP_SPIN2, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_SIMP_EDIT3, IDC_COMP_PHYS_SIMP_SPIN3, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundListStuff, _T("UserBoundChoice"), TYPE_INODE, 0, 0, |
|
p_ui, kPhysMain, TYPE_PICKNODEBUTTON, IDC_COMP_PHYS_PICKSTATE_SIMP, |
|
p_sclassID, GEOMOBJECT_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_SIMP, |
|
p_accessor, &gPhysCoreAccessor, |
|
end, |
|
|
|
plPhysicCoreComponent::kCustomBoundField, _T("UserBoundCheckBx"), TYPE_BOOL, 0, 0, |
|
p_default, false, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_CUSTOMCHK, |
|
p_enable_ctrls, 1, plPhysicCoreComponent::kCustomBoundListStuff, |
|
end, |
|
|
|
plPhysicCoreComponent::kAlignProxyShape, _T("AlignShapeChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_PHYS_ALIGN_SHAPE_BOOL, |
|
end, |
|
|
|
plPhysicCoreComponent::kNoSynchronize, _T("DontSynchronizeChkBx"), TYPE_BOOL, 0, 0, |
|
p_default, false, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_PH_NO_SYNC_CHK, |
|
end, |
|
|
|
plPhysicCoreComponent::kStartInactive, _T("StartInactiveChkBx"), TYPE_BOOL, 0, 0, |
|
p_default, true, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_PH_INACTIVE_CHK, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kDynamicSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated | |
|
plPhysicsGroups_DEAD::kDynamicSimulated | |
|
plPhysicsGroups_DEAD::kAnimated, |
|
end, |
|
|
|
plPhysicCoreComponent::kAvAnimPushable, _T("AvAnimPushable"), TYPE_BOOL, 0, 0, |
|
p_default, false, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_PH_AVANIMPUSHABLE, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysSimpleComponent::plPhysSimpleComponent() |
|
{ |
|
fClassDesc = &gPhysSimpleDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
void plPhysSimpleComponent::CollectNonDrawables(INodeTab& nonDrawables) |
|
{ |
|
if (fCompPB->GetInt(kCustomBoundField)) |
|
{ |
|
INode* boundsNode = fCompPB->GetINode(kCustomBoundListStuff); |
|
if( boundsNode ) |
|
nonDrawables.Append(1, &boundsNode); |
|
} |
|
} |
|
|
|
hsBool plPhysSimpleComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(fCompPB->GetFloat(kMass), pNode, pErrMsg); |
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), pNode, pErrMsg); |
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), pNode, pErrMsg); |
|
physProps->SetAlignToOwner(fCompPB->GetInt(kAlignProxyShape) != 0, pNode, pErrMsg); |
|
|
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupDynamic, pNode, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
|
|
physProps->SetNoSynchronize(fCompPB->GetInt(kNoSynchronize)); |
|
physProps->SetStartInactive(fCompPB->GetInt(kStartInactive)); |
|
physProps->SetAvAnimPushable(fCompPB->GetInt(kAvAnimPushable)); |
|
|
|
if( !pNode->IsAnimated() ) |
|
pNode->SetItinerant(true); |
|
|
|
return IGetProxy(pNode, pErrMsg); |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
//! Invisible Blocker Component Class |
|
|
|
class plPhysBlockerComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysBlockerComponent(); |
|
hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plPhysBlockerComponent, gPhysBlockerDesc, "(ex) Invisible Blocker", "InvisBlocker", COMP_TYPE_PHYSICAL, PHYSICS_BLOCKER_CID) |
|
|
|
ParamBlockDesc2 gPhysBlockerBk |
|
( |
|
plComponent::kBlkComp, _T("invisibleBlocker"), 0, &gPhysBlockerDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_INVISIBLE, IDS_COMP_PHYS_INVISIBLE, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kLOSChkBx, _T("LOSChkBx"), TYPE_BOOL, P_ANIMATABLE, 0, |
|
p_default, FALSE, |
|
p_ui, kPhysMain, TYPE_SINGLECHEKBOX, IDC_COMP_CHECK_LOS, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_INVIS_BOUNCE_EDIT, IDC_COMP_PHYS_INVIS_BOUNCE_SPIN, 0.0001f, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kGroup, _T("group"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 2, IDC_RADIO_BLOCK_AVATAR, IDC_RADIO_BLOCK_DYNAMIC, |
|
p_vals, plSimDefs::kGroupAvatarBlocker, plSimDefs::kGroupDynamicBlocker, |
|
p_default, plSimDefs::kGroupAvatarBlocker, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysBlockerComponent::plPhysBlockerComponent() |
|
{ |
|
fClassDesc = &gPhysBlockerDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPhysBlockerComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
|
|
if(fCompPB->GetInt(kLOSChkBx)) |
|
{ |
|
physProps->SetLOSBlockUI(true, pNode, pErrMsg); |
|
physProps->SetLOSBlockCamera(true, pNode, pErrMsg); |
|
} |
|
|
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
|
|
physProps->SetGroup(fCompPB->GetInt(kGroup), pNode, pErrMsg); |
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Walkable |
|
|
|
class plPhysWalkableComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysWalkableComponent(); |
|
hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plPhysWalkableComponent, gPhysWalkableDesc, "Walkable", "Walkable", COMP_TYPE_PHYS_TERRAINS, PHYS_WALKABLE_CID) |
|
|
|
ParamBlockDesc2 gPhysWalkableBk |
|
( |
|
plComponent::kBlkComp, _T("Walkable"), 0, &gPhysWalkableDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_INVISIBLE, IDS_COMP_PHYS_WALKABLE, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_INVIS_BOUNCE_EDIT, IDC_COMP_PHYS_INVIS_BOUNCE_SPIN, 0.0001f, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysWalkableComponent::plPhysWalkableComponent() |
|
{ |
|
fClassDesc = &gPhysWalkableDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPhysWalkableComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), pNode, pErrMsg); |
|
|
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupStatic, pNode, pErrMsg); |
|
// physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Climable |
|
class plPhysClimbableComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysClimbableComponent(); |
|
hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plPhysClimbableComponent, gPhysClimbableDesc, "Climbable", "Climbable", COMP_TYPE_PHYS_TERRAINS, PHYS_CLIMBABLE_CID) |
|
|
|
ParamBlockDesc2 gPhysClimbableBk |
|
( |
|
plComponent::kBlkComp, _T("Climbable"), 0, &gPhysClimbableDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_CLIMBABLE, IDS_COMP_PHYS_CLIMBABLE, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_INVIS_BOUNCE_EDIT, IDC_COMP_PHYS_INVIS_BOUNCE_SPIN, 0.0001f, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysClimbableComponent::plPhysClimbableComponent() |
|
{ |
|
fClassDesc = &gPhysClimbableDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPhysClimbableComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), pNode, pErrMsg); |
|
|
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupStatic, pNode, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
// physProps->SetReportGroup(1<<plSimDefs::kAvatars, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plSwim2DComponent |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
class Swim2DDlgProc : public ParamMap2UserDlgProc |
|
{ |
|
public: |
|
Swim2DDlgProc() {} |
|
~Swim2DDlgProc() {} |
|
|
|
void IValidateSpinners(TimeValue t, IParamBlock2 *pb, IParamMap2 *map, uint32_t id) |
|
{ |
|
uint32_t minIndex, maxIndex; |
|
hsBool adjustMin; |
|
switch(id) |
|
{ |
|
case IDC_SWIM_CURRENT_PULL_NEAR_DIST: |
|
case IDC_SWIM_CURRENT_PULL_NEAR_DIST_SPIN: |
|
minIndex = plPhysicCoreComponent::kSwimCurrentPullNearDist; maxIndex = plPhysicCoreComponent::kSwimCurrentPullFarDist; adjustMin = false; |
|
break; |
|
|
|
case IDC_SWIM_CURRENT_PULL_FAR_DIST: |
|
case IDC_SWIM_CURRENT_PULL_FAR_DIST_SPIN: |
|
minIndex = plPhysicCoreComponent::kSwimCurrentPullNearDist; maxIndex = plPhysicCoreComponent::kSwimCurrentPullFarDist; adjustMin = true; |
|
break; |
|
|
|
case IDC_SWIM_CURRENT_STRAIGHT_NEAR_DIST: |
|
case IDC_SWIM_CURRENT_STRAIGHT_NEAR_DIST_SPIN: |
|
minIndex = plPhysicCoreComponent::kSwimCurrentStraightNearDist; maxIndex = plPhysicCoreComponent::kSwimCurrentStraightFarDist; adjustMin = false; |
|
break; |
|
|
|
case IDC_SWIM_CURRENT_STRAIGHT_FAR_DIST: |
|
case IDC_SWIM_CURRENT_STRAIGHT_FAR_DIST_SPIN: |
|
minIndex = plPhysicCoreComponent::kSwimCurrentStraightNearDist; maxIndex = plPhysicCoreComponent::kSwimCurrentStraightFarDist; adjustMin = true; |
|
break; |
|
|
|
default: |
|
return; |
|
} |
|
|
|
float min, max; |
|
min = pb->GetFloat(minIndex, t); |
|
max = pb->GetFloat(maxIndex, t); |
|
|
|
if (min > max) |
|
{ |
|
if (adjustMin) |
|
pb->SetValue(minIndex, t, max); |
|
else |
|
pb->SetValue(maxIndex, t, min); |
|
|
|
map->Invalidate(minIndex); |
|
map->Invalidate(maxIndex); |
|
} |
|
} |
|
|
|
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
int id = LOWORD(wParam); |
|
|
|
IParamBlock2 *pb = map->GetParamBlock(); |
|
|
|
switch (msg) |
|
{ |
|
case WM_COMMAND: |
|
case CC_SPINNER_CHANGE: |
|
IValidateSpinners(t, pb, map, id); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
void DeleteThis() {} |
|
}; |
|
static Swim2DDlgProc gSwim2DDlgProc; |
|
|
|
CLASS_DESC(plSwim2DComponent, gPhysSwimSurfaceDesc, "Swim 2D", "Swim 2D", COMP_TYPE_PHYS_TERRAINS, PHYS_SWIMSURFACE_CID) |
|
|
|
ParamBlockDesc2 gPhysSwimSurfaceBk |
|
( |
|
plComponent::kBlkComp, _T("Swim 2D"), 0, &gPhysSwimSurfaceDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_SWIMSURF, IDS_COMP_PHYS_SWIMSURF, 0, 0, &gSwim2DDlgProc, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentType, _T("CurrentType"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 3, IDC_SWIM_CURRENT_NONE, IDC_SWIM_CURRENT_SPIRAL, IDC_SWIM_CURRENT_STRAIGHT, |
|
p_vals, plSwim2DComponent::kCurrentNone, plSwim2DComponent::kCurrentSpiral, plSwim2DComponent::kCurrentStraight, |
|
p_default, plSwim2DComponent::kCurrentNone, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentRotation, _T("SwimRotation"), TYPE_FLOAT, 0, 0, |
|
p_default, 1.0, |
|
p_range, -100.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_ROTATION, IDC_SWIM_CURRENT_ROTATION_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimDetectorNode, _T("swimDetector"), TYPE_INODE, 0, 0, |
|
p_ui, kPhysMain, TYPE_PICKNODEBUTTON, IDC_SWIM_DETECTOR_NODE, |
|
p_sclassID, GEOMOBJECT_CLASS_ID, |
|
p_prompt, IDS_SWIM_DETECTOR_NODE, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentNode, _T("swimCurrentNode"), TYPE_INODE, 0, 0, |
|
p_ui, kPhysMain, TYPE_PICKNODEBUTTON, IDC_SWIM_CURRENT_NODE, |
|
//p_sclassID, DUMMY_CLASS_ID, |
|
p_prompt, IDS_SWIM_CURRENT_NODE, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimBuoyancyDown, _T("BuoyancyDown"), TYPE_FLOAT, 0, 0, |
|
p_default, 3.0, |
|
p_range, 0.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_SWIM_BUOYANCY_DOWN, IDC_SWIM_BUOYANCY_DOWN_SPIN, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimBuoyancyUp, _T("BuoyancyUp"), TYPE_FLOAT, 0, 0, |
|
p_default, 0.05, |
|
p_range, 0.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_SWIM_BUOYANCY_UP, IDC_SWIM_BUOYANCY_UP_SPIN, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimMaxUpVel, _T("MaxUpVel"), TYPE_FLOAT, 0, 0, |
|
p_default, 3.0, |
|
p_range, 0.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_SWIM_MAX_UP_VEL, IDC_SWIM_MAX_UP_VEL_SPIN, 0.1, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentPullNearDist, _T("PullNearDist"), TYPE_FLOAT, 0, 0, |
|
p_default, 1.0, |
|
p_range, 0.0, 10000.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_SWIM_CURRENT_PULL_NEAR_DIST, IDC_SWIM_CURRENT_PULL_NEAR_DIST_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentPullNearVel, _T("PullNearVel"), TYPE_FLOAT, 0, 0, |
|
p_default, 0.0, |
|
p_range, -100.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_PULL_NEAR_VEL, IDC_SWIM_CURRENT_PULL_NEAR_VEL_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentPullFarDist, _T("PullFarDist"), TYPE_FLOAT, 0, 0, |
|
p_default, 1.0, |
|
p_range, 0.0, 10000.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_SWIM_CURRENT_PULL_FAR_DIST, IDC_SWIM_CURRENT_PULL_FAR_DIST_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentPullFarVel, _T("PullFarVel"), TYPE_FLOAT, 0, 0, |
|
p_default, 0.0, |
|
p_range, -100.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_PULL_FAR_VEL, IDC_SWIM_CURRENT_PULL_FAR_VEL_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentStraightNearDist, _T("StraightNearDist"), TYPE_FLOAT, 0, 0, |
|
p_default, 1.0, |
|
p_range, -10000.0, 10000.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_STRAIGHT_NEAR_DIST, IDC_SWIM_CURRENT_STRAIGHT_NEAR_DIST_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentStraightNearVel, _T("StraightNearVel"), TYPE_FLOAT, 0, 0, |
|
p_default, 0.0, |
|
p_range, -100.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_STRAIGHT_NEAR_VEL, IDC_SWIM_CURRENT_STRAIGHT_NEAR_VEL_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentStraightFarDist, _T("StraightFarDist"), TYPE_FLOAT, 0, 0, |
|
p_default, 1.0, |
|
p_range, -10000.0, 10000.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_STRAIGHT_FAR_DIST, IDC_SWIM_CURRENT_STRAIGHT_FAR_DIST_SPIN, 1.0, |
|
end, |
|
|
|
plPhysicCoreComponent::kSwimCurrentStraightFarVel, _T("StraightFarVel"), TYPE_FLOAT, 0, 0, |
|
p_default, 0.0, |
|
p_range, -100.0, 100.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_SWIM_CURRENT_STRAIGHT_FAR_VEL, IDC_SWIM_CURRENT_STRAIGHT_FAR_VEL_SPIN, 1.0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
// plSwim2DComponent ----------------- |
|
// ------------------ |
|
plSwim2DComponent::plSwim2DComponent() |
|
{ |
|
fClassDesc = &gPhysSwimSurfaceDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
// SetUpProperties ----------------------------------------------------------- |
|
// ---------------- |
|
hsBool plSwim2DComponent::SetupProperties(plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
IFixBounds(); |
|
plPhysicalProps *physProps = nil; |
|
plMaxNode *detectorNode = (plMaxNode *)fCompPB->GetINode(kSwimDetectorNode); |
|
if (detectorNode) |
|
{ |
|
detectorNode->SetDrawable(false); |
|
physProps = detectorNode->GetPhysicalProps(); |
|
physProps->SetMass(0, detectorNode, errMsg); |
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, errMsg); |
|
physProps->SetGroup(plSimDefs::kGroupDetector, node, errMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), detectorNode, errMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), detectorNode, errMsg); |
|
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, detectorNode, errMsg); |
|
physProps->SetBoundsType(plSimDefs::kBoxBounds, detectorNode, errMsg); |
|
} |
|
|
|
physProps = node->GetPhysicalProps(); |
|
physProps->SetMass(0, node, errMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), node, errMsg); |
|
physProps->SetLOSSwimRegion(true, node, errMsg); |
|
|
|
plMaxNode *currentNode = (plMaxNode *)fCompPB->GetINode(kSwimCurrentNode); |
|
if (currentNode) |
|
currentNode->SetForceLocal(true); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plSwim2DComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plSwimRegionInterface *swimInt = nil; |
|
int type = fCompPB->GetInt(ParamID(kSwimCurrentType)); |
|
if (type != kCurrentNone && fCompPB->GetINode(ParamID(kSwimCurrentNode)) == nil) |
|
{ |
|
pErrMsg->Set(true, node->GetName(), "No dummy box set to define current. Forcing current to \"none\"").Show(); |
|
type = kCurrentNone; |
|
} |
|
|
|
switch (type) |
|
{ |
|
case kCurrentSpiral: |
|
{ |
|
fSwimRegions[node] = TRACKED_NEW plSwimCircularCurrentRegion(); |
|
hsgResMgr::ResMgr()->NewKey(node->GetName(), fSwimRegions[node], node->GetLocation(), node->GetLoadMask()); |
|
break; |
|
} |
|
case kCurrentStraight: |
|
{ |
|
fSwimRegions[node] = TRACKED_NEW plSwimStraightCurrentRegion(); |
|
hsgResMgr::ResMgr()->NewKey(node->GetName(), fSwimRegions[node], node->GetLocation(), node->GetLoadMask()); |
|
break; |
|
} |
|
default: |
|
{ |
|
fSwimRegions[node] = TRACKED_NEW plSwimRegionInterface(); |
|
hsgResMgr::ResMgr()->NewKey(node->GetName(), fSwimRegions[node], node->GetLocation(), node->GetLoadMask()); |
|
break; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
// Convert ------------------------------------------------------------ |
|
// -------- |
|
hsBool plSwim2DComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plMaxNode *detectorNode = (plMaxNode *)fCompPB->GetINode(kSwimDetectorNode); |
|
if (detectorNode && detectorNode->GetSceneObject()) |
|
{ |
|
if (!detectorNode->GetSceneObject()->GetModifierByType(plSwimDetector::Index())) |
|
{ |
|
plKey nilKey; |
|
plSwimMsg *enterMsg = TRACKED_NEW plSwimMsg(detectorNode->GetKey(), nilKey, true, nil); |
|
plSwimMsg *exitMsg = TRACKED_NEW plSwimMsg(detectorNode->GetKey(), nilKey, false, nil); |
|
enterMsg->SetBCastFlag(plMessage::kPropagateToModifiers); |
|
exitMsg->SetBCastFlag(plMessage::kPropagateToModifiers); |
|
plSwimDetector *swimMod = TRACKED_NEW plSwimDetector(enterMsg, exitMsg); |
|
detectorNode->AddModifier(swimMod, IGetUniqueName(node)); |
|
|
|
// the mod doesn't have a valid key until AddModifier is called, so this comes last. |
|
enterMsg->fSwimRegionKey = swimMod->GetKey(); |
|
exitMsg->fSwimRegionKey = swimMod->GetKey(); |
|
} |
|
} |
|
|
|
int type = fCompPB->GetInt(ParamID(kSwimCurrentType)); |
|
switch (type) |
|
{ |
|
case kCurrentSpiral: |
|
{ |
|
plSwimCircularCurrentRegion *circInt = plSwimCircularCurrentRegion::ConvertNoRef(fSwimRegions[node]); |
|
circInt->fRotation = fCompPB->GetFloat(ParamID(kSwimCurrentRotation)); |
|
circInt->fPullNearDistSq = fCompPB->GetFloat(ParamID(kSwimCurrentPullNearDist)); |
|
circInt->fPullNearDistSq *= circInt->fPullNearDistSq; |
|
circInt->fPullNearVel = fCompPB->GetFloat(ParamID(kSwimCurrentPullNearVel)); |
|
circInt->fPullFarDistSq = fCompPB->GetFloat(ParamID(kSwimCurrentPullFarDist)); |
|
circInt->fPullFarDistSq *= circInt->fPullFarDistSq; |
|
circInt->fPullFarVel = fCompPB->GetFloat(ParamID(kSwimCurrentPullFarVel)); |
|
|
|
plMaxNode *currentNode = (plMaxNode *)fCompPB->GetINode(ParamID(kSwimCurrentNode)); |
|
if (currentNode) |
|
{ |
|
plGenRefMsg *msg= TRACKED_NEW plGenRefMsg(circInt->GetKey(), plRefMsg::kOnCreate, -1, -1); |
|
hsgResMgr::ResMgr()->AddViaNotify(currentNode->GetSceneObject()->GetKey(), msg, plRefFlags::kActiveRef); |
|
} |
|
break; |
|
} |
|
case kCurrentStraight: |
|
{ |
|
plSwimStraightCurrentRegion *strInt = plSwimStraightCurrentRegion::ConvertNoRef(fSwimRegions[node]); |
|
strInt->fNearDist = fCompPB->GetFloat(ParamID(kSwimCurrentStraightNearDist)); |
|
strInt->fNearVel = fCompPB->GetFloat(ParamID(kSwimCurrentStraightNearVel)); |
|
strInt->fFarDist = fCompPB->GetFloat(ParamID(kSwimCurrentStraightFarDist)); |
|
strInt->fFarVel = fCompPB->GetFloat(ParamID(kSwimCurrentStraightFarVel)); |
|
|
|
plMaxNode *currentNode = (plMaxNode *)fCompPB->GetINode(ParamID(kSwimCurrentNode)); |
|
if (currentNode) |
|
{ |
|
plGenRefMsg *msg= TRACKED_NEW plGenRefMsg(strInt->GetKey(), plRefMsg::kOnCreate, -1, -1); |
|
hsgResMgr::ResMgr()->AddViaNotify(currentNode->GetSceneObject()->GetKey(), msg, plRefFlags::kActiveRef); |
|
} |
|
break; |
|
} |
|
default: |
|
{ |
|
// Already done all the work in PreConvert |
|
break; |
|
} |
|
} |
|
|
|
fSwimRegions[node]->fDownBuoyancy = fCompPB->GetFloat(ParamID(kSwimBuoyancyDown)) + 1; |
|
fSwimRegions[node]->fUpBuoyancy = fCompPB->GetFloat(ParamID(kSwimBuoyancyUp)) + 1; |
|
fSwimRegions[node]->fMaxUpwardVel = fCompPB->GetFloat(ParamID(kSwimMaxUpVel)); |
|
|
|
hsgResMgr::ResMgr()->AddViaNotify(fSwimRegions[node]->GetKey(), TRACKED_NEW plObjRefMsg(node->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kInterface), plRefFlags::kActiveRef); |
|
|
|
return true; |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// Swim 3D |
|
|
|
class plPhysSwim3DComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysSwim3DComponent(); |
|
hsBool SetupProperties(plMaxNode* node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
CLASS_DESC(plPhysSwim3DComponent, gPhysSwim3DDesc, "Swim 3D", "Swim 3D", COMP_TYPE_PHYS_TERRAINS, PHYS_SWIM3D_CID) |
|
|
|
ParamBlockDesc2 gPhysSwim3DBk |
|
( |
|
plComponent::kBlkComp, _T("Swim 3D"), 0, &gPhysSwim3DDesc, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, plComponent::kRefComp, |
|
|
|
//Roll out |
|
1, |
|
kPhysMain, IDD_COMP_PHYS_SWIM3D, IDS_COMP_PHYS_SWIM3D, 0, 0, NULL, |
|
// kPhysMember, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_MEMBER, 0, APPENDROLL_CLOSED, &gMemberGroupProc, |
|
// kPhysBounce, IDD_COMP_PHYS_CORE_GROUP, IDS_COMP_PHYS_BOUNCE, 0, APPENDROLL_CLOSED, &gBounceGroupProc, |
|
|
|
// params |
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, kPhysMain, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kProxyBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
|
|
plPhysicCoreComponent::kFriction, _T("Friction"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.5, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_TERRAIN_EDIT1, IDC_COMP_PHYS_TERRAIN_SPIN1, 0.0001f, |
|
end, |
|
|
|
plPhysicCoreComponent::kBounce, _T("Bounce"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_default, 0.0, |
|
p_range, 0.0, 1.0, |
|
p_ui, kPhysMain, TYPE_SPINNER, EDITTYPE_POS_FLOAT, |
|
IDC_COMP_PHYS_INVIS_BOUNCE_EDIT, IDC_COMP_PHYS_INVIS_BOUNCE_SPIN, 0.0001f, |
|
end, |
|
|
|
// Event Groups |
|
plPhysicCoreComponent::kMemberGroups_DEAD, _T("memberGroups"), TYPE_INT, 0,0, |
|
p_default, plPhysicsGroups_DEAD::kStaticSimulated, |
|
end, |
|
plPhysicCoreComponent::kBounceGroups_DEAD, _T("bounceGroups"), TYPE_INT, 0,0, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPhysSwim3DComponent::plPhysSwim3DComponent() |
|
{ |
|
fClassDesc = &gPhysSwim3DDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPhysSwim3DComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
IFixBounds(); |
|
|
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(0, pNode, pErrMsg); |
|
physProps->SetFriction(fCompPB->GetFloat(kFriction), pNode, pErrMsg); |
|
physProps->SetRestitution(fCompPB->GetFloat(kBounce), pNode, pErrMsg); |
|
|
|
ValidateGroups(fCompPB, plPhysicCoreComponent::kMemberGroups_DEAD, plPhysicCoreComponent::kBounceGroups_DEAD, this, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupStatic, pNode, pErrMsg); |
|
// physProps->SetMemberGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kMemberGroups), pNode, pErrMsg); |
|
// physProps->SetBounceGroup(plEventGroupProc::GetGroups(fCompPB, plPhysicCoreComponent::kBounceGroups), pNode, pErrMsg); |
|
// physProps->SetReportGroup(plPhysicsGroups_DEAD::kAvatars, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// DEAD |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
class plPhysPlayerComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysPlayerComponent(); |
|
}; |
|
|
|
OBSOLETE_CLASS_DESC(plPhysPlayerComponent, gPhysPlayerDesc, "Player", "Player", COMP_TYPE_PHYSICAL, PHYSICS_PLAYER_CID) |
|
|
|
ParamBlockDesc2 gPhysPlayerBk |
|
( |
|
plComponent::kBlkComp, _T("Player"), 0, &gPhysPlayerDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
end |
|
); |
|
|
|
plPhysPlayerComponent::plPhysPlayerComponent() |
|
{ |
|
fClassDesc = &gPhysPlayerDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
///// |
|
|
|
class plPhysBoundBlockerComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysBoundBlockerComponent(); |
|
}; |
|
|
|
OBSOLETE_CLASS_DESC(plPhysBoundBlockerComponent, gPhysBoundBlockerDesc, "(ex) Boundary Blocker", "BoundaryBlocker", COMP_TYPE_PHYSICAL, PHYSICS_BOUND_BLOCKER_CID) |
|
|
|
ParamBlockDesc2 gPhysBoundBlockerBk |
|
( |
|
plComponent::kBlkComp, _T("(ex)Boundary Blocker"), 0, &gPhysBoundBlockerDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
end |
|
); |
|
|
|
plPhysBoundBlockerComponent::plPhysBoundBlockerComponent() |
|
{ |
|
fClassDesc = &gPhysBoundBlockerDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
///// |
|
|
|
class plPhysDetectorComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysDetectorComponent(); |
|
}; |
|
|
|
OBSOLETE_CLASS_DESC(plPhysDetectorComponent, gPhysDetectorDesc, "Detector", "Detector", COMP_TYPE_PHYSICAL, PHYSICS_DETECTOR_CID) |
|
|
|
ParamBlockDesc2 gPhysDetectorBk |
|
( |
|
plComponent::kBlkComp, _T("Detector"), 0, &gPhysDetectorDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
end |
|
); |
|
|
|
plPhysDetectorComponent::plPhysDetectorComponent() |
|
{ |
|
fClassDesc = &gPhysDetectorDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
//! Physical Simple Component Class |
|
|
|
class plPhysSubWorldComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plPhysSubWorldComponent(); |
|
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
void IAddChildren(plMaxNode *node, plMaxNode* worldKey); |
|
}; |
|
|
|
CLASS_DESC(plPhysSubWorldComponent, gPhysSubWorldDesc, "Subworld", "Subworld", COMP_TYPE_PHYSICAL, PHYS_SUBWORLD_CID) |
|
|
|
ParamBlockDesc2 gPhysSubWorldBk |
|
( |
|
plComponent::kBlkComp, _T("Subworld\t"), 0, &gPhysSubWorldDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
//Roll out |
|
IDD_COMP_PHYS_SUBWORLD, IDS_COMP_PHYS_SUBWORLD, 0, 0, NULL, |
|
|
|
end |
|
); |
|
|
|
plPhysSubWorldComponent::plPhysSubWorldComponent() |
|
{ |
|
fClassDesc = &gPhysSubWorldDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPhysSubWorldComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
IAddChildren(node, node); |
|
|
|
node->SetForceLocal(true); |
|
node->SetMovable(true); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plPhysSubWorldComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
void plPhysSubWorldComponent::IAddChildren(plMaxNode* node, plMaxNode* subworld) |
|
{ |
|
int numChildren = node->NumberOfChildren(); |
|
for (int i = 0; i < numChildren; i++) |
|
{ |
|
plMaxNode* child = (plMaxNode*)node->GetChildNode(i); |
|
const char* childName = child->GetName(); |
|
|
|
bool hasSubworld = false; |
|
|
|
uint32_t numComps = child->NumAttachedComponents(); |
|
for (int j = 0; j < numComps; j++) |
|
{ |
|
plComponentBase* comp = child->GetAttachedComponent(j); |
|
if (comp && comp->ClassID() == PHYS_SUBWORLD_CID) |
|
{ |
|
hasSubworld = true; |
|
break; |
|
} |
|
} |
|
|
|
// If we've reached another subworld, terminate our descent so we don't file |
|
// children in our subworld instead. |
|
// This has to happen *after* we've converted this node, because it may be a physical |
|
// in the parent subworld. |
|
if (!hasSubworld) |
|
{ |
|
plPhysicalProps* props = child->GetPhysicalProps(); |
|
if (props) |
|
props->SetSubworld(subworld); |
|
IAddChildren(child, subworld); |
|
} |
|
} |
|
} |
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// the detector for triggering subworld changes |
|
/////////////////////////////////////////////////////// |
|
|
|
class plSubworldDetectorComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plSubworldDetectorComponent(); |
|
|
|
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
|
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
|
|
|
|
CLASS_DESC(plSubworldDetectorComponent, gSubworldDetectorDesc, "Subworld Region", "SubworldRegion", COMP_TYPE_PHYSICAL, SUBWORLD_REGION_CID) |
|
|
|
enum |
|
{ |
|
kSubworldTarget, |
|
kInclusive_DEAD, |
|
kSubworldTriggerOn, |
|
}; |
|
|
|
enum |
|
{ |
|
kSubTriggerOnEnter, |
|
kSubTriggerOnExit, |
|
}; |
|
|
|
ParamBlockDesc2 gSubworldRegionBlock |
|
( |
|
plComponent::kBlkComp, _T("subworldRegion"), 0, &gSubworldDetectorDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_SUBWORLD_REGION, IDS_COMP_SUBWORLD_REGION, 0, 0, NULL, |
|
|
|
kSubworldTarget, _T("SubworldTarget"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERARGN_PICKSTATE_BASE, |
|
p_sclassID, HELPER_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
end, |
|
|
|
kSubworldTriggerOn, _T("triggerOn"), TYPE_INT, 0, 0, |
|
p_ui, TYPE_RADIO, 2, IDC_RADIO_ENTER, IDC_RADIO_EXIT, |
|
p_vals, kSubTriggerOnEnter, kSubTriggerOnExit, |
|
p_default, kSubTriggerOnEnter, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plSubworldDetectorComponent::plSubworldDetectorComponent() |
|
{ |
|
fClassDesc = &gSubworldDetectorDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plSubworldDetectorComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
pNode->SetForceLocal(true); |
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(1.0, pNode, pErrMsg); |
|
physProps->SetFriction(0.0, pNode, pErrMsg); |
|
physProps->SetRestitution(0.0, pNode, pErrMsg); |
|
//physProps->SetBoundsType(plSimDefs::kExplicitBounds, pNode, pErrMsg); |
|
physProps->SetBoundsType(plSimDefs::kHullBounds, pNode, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupDetector, pNode, pErrMsg); |
|
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plSubworldDetectorComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plSubworldDetectorComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plSceneObject *obj = node->GetSceneObject(); |
|
plLocation loc = node->GetLocation(); |
|
|
|
plSubworldRegionDetector *detector = TRACKED_NEW plSubworldRegionDetector; |
|
|
|
// Register the detector |
|
plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc); |
|
hsgResMgr::ResMgr()->AddViaNotify(detectorKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); |
|
|
|
// need to get the key for the camera here... |
|
plMaxNode* pSubNode = (plMaxNode*)fCompPB->GetINode(kSubworldTarget); |
|
if (pSubNode) |
|
{ |
|
if(pSubNode->CanConvert()) |
|
{ |
|
detector->SetSubworldKey(pSubNode->GetKey()); |
|
} |
|
} |
|
else |
|
{ |
|
detector->SetSubworldKey(nil); |
|
} |
|
|
|
bool onExit = (fCompPB->GetInt(kSubworldTriggerOn) == kSubTriggerOnExit); |
|
detector->SetTriggerOnExit(onExit); |
|
|
|
return true; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// the detector for triggering panic links |
|
/////////////////////////////////////////////////////// |
|
|
|
class plPanicLinkDetectorComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
enum |
|
{ |
|
kPlayAnim, |
|
}; |
|
|
|
plPanicLinkDetectorComponent(); |
|
void DeleteThis() { delete this; } |
|
|
|
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
|
|
|
|
CLASS_DESC(plPanicLinkDetectorComponent, gPanicLinkDetectorDesc, "Panic Link Region", "PanicLinkRegion", COMP_TYPE_PHYSICAL, PANIC_LINK_REGION_CID) |
|
|
|
ParamBlockDesc2 gPanicLinkRegionBlock |
|
( |
|
plComponent::kBlkComp, _T("panicLinkRegion"), 0, &gPanicLinkDetectorDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_PANIC, IDS_COMP_PANIC, 0, 0, NULL, |
|
|
|
plPanicLinkDetectorComponent::kPlayAnim, _T("PlayAnim"), TYPE_BOOL, 0, 0, |
|
p_default, true, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_PANIC_ANIM, |
|
end, |
|
|
|
end |
|
); |
|
|
|
|
|
plPanicLinkDetectorComponent::plPanicLinkDetectorComponent() |
|
{ |
|
fClassDesc = &gPanicLinkDetectorDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plPanicLinkDetectorComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
pNode->SetForceLocal(true); |
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(1.0, pNode, pErrMsg); |
|
physProps->SetFriction(0.0, pNode, pErrMsg); |
|
physProps->SetRestitution(0.0, pNode, pErrMsg); |
|
physProps->SetBoundsType(plSimDefs::kHullBounds, pNode, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupDetector, pNode, pErrMsg); |
|
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plPanicLinkDetectorComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plPanicLinkDetectorComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plSceneObject *obj = node->GetSceneObject(); |
|
plLocation loc = node->GetLocation(); |
|
|
|
plPanicLinkRegion *detector = TRACKED_NEW plPanicLinkRegion; |
|
detector->fPlayLinkOutAnim = fCompPB->GetInt(ParamID(kPlayAnim)); |
|
|
|
// Register the detector |
|
plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc); |
|
hsgResMgr::ResMgr()->AddViaNotify(detectorKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); |
|
return true; |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// Shootable COMPONENT |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
//Class that accesses the paramblock below. |
|
class plShootableComponent : public plComponent |
|
{ |
|
public: |
|
plShootableComponent(); |
|
|
|
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading |
|
// of properties on the MaxNode, as it's still indeterminant. |
|
hsBool SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
}; |
|
|
|
//Max desc stuff necessary below. |
|
CLASS_DESC(plShootableComponent, gShootableDesc, "Shootable", "Shootable", COMP_TYPE_PHYSICAL, Class_ID(0x77b94f4a, 0x6d3851fc)) |
|
|
|
ParamBlockDesc2 gShootableBk |
|
( |
|
// 1, _T(""), 0, &gShootableDesc, P_AUTO_CONSTRUCT, 0, |
|
plComponent::kBlkComp, _T("Shootable"), 0, &gShootableDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_SHOOTABLE, IDS_COMP_SHOOTABLE, 0, 0, NULL, |
|
|
|
end |
|
); |
|
|
|
plShootableComponent::plShootableComponent() |
|
{ |
|
fClassDesc = &gShootableDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
// SetupProperties - Internal setup and write-only set properties on the MaxNode. No reading |
|
// of properties on the MaxNode, as it's still indeterminant. |
|
hsBool plShootableComponent::SetupProperties(plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
plPhysicalProps *props = node->GetPhysicalProps(); |
|
|
|
props->SetMass(0.0, node, errMsg); |
|
props->SetFriction(0.0, node, errMsg); |
|
props->SetRestitution(0.0, node, errMsg); |
|
props->SetBoundsType(plSimDefs::kExplicitBounds, node, errMsg); |
|
props->SetGroup(plSimDefs::kGroupLOSOnly, node, errMsg); |
|
props->SetPinned(true, node, errMsg); |
|
props->SetLOSShootable(true, node, errMsg); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plShootableComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
class plRideAnimatedPhysicalComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
plRideAnimatedPhysicalComponent(); |
|
void DeleteThis(){delete this;} |
|
hsBool SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
hsBool PreConvert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
virtual void CollectNonDrawables(INodeTab& nonDrawables) { AddTargetsToList(nonDrawables); } |
|
}; |
|
CLASS_DESC(plRideAnimatedPhysicalComponent , gRideAnimatedPhysicalComponent, "RideAnimPhysReg", "RideAnimatedPhysicalRegion", COMP_TYPE_PHYSICAL, Class_ID(0xaf305963, 0x63a246df)); |
|
ParamBlockDesc2 gSRideAnimatedPhysBk |
|
( |
|
plComponent::kBlkComp, _T("rideAnimated"), 0, &gRideAnimatedPhysicalComponent, P_AUTO_CONSTRUCT + P_AUTO_UI , plComponent::kRefComp, |
|
//Roll out |
|
|
|
IDD_COMP_RIDE_ANIMATED_PHYS, IDS_COMP_RIDE_ANIMATED_PHYS, 0, 0, NULL, |
|
|
|
plPhysicCoreComponent::kBoundCondRadio, _T("BoundingConditions"), TYPE_INT, 0, 0, |
|
p_ui, TYPE_RADIO, 4, IDC_RADIO_BSPHERE, IDC_RADIO_BBOX, IDC_RADIO_BHULL, IDC_RADIO_PICKSTATE, |
|
p_vals, plSimDefs::kSphereBounds, plSimDefs::kBoxBounds, plSimDefs::kHullBounds, plSimDefs::kExplicitBounds, |
|
p_default, plSimDefs::kHullBounds, |
|
end, |
|
end |
|
); |
|
plRideAnimatedPhysicalComponent::plRideAnimatedPhysicalComponent() |
|
{ |
|
fClassDesc = &gRideAnimatedPhysicalComponent; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
hsBool plRideAnimatedPhysicalComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
pNode->SetForceLocal(true); |
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetMass(1.0, pNode, pErrMsg); |
|
physProps->SetFriction(0.0, pNode, pErrMsg); |
|
physProps->SetRestitution(0.0, pNode, pErrMsg); |
|
physProps->SetGroup(plSimDefs::kGroupDetector, pNode, pErrMsg); |
|
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, pNode, pErrMsg); |
|
physProps->SetBoundsType(fCompPB->GetInt(kBoundCondRadio), pNode, pErrMsg); |
|
return true; |
|
} |
|
hsBool plRideAnimatedPhysicalComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plRideAnimatedPhysicalComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plSceneObject *obj = node->GetSceneObject(); |
|
plLocation loc = node->GetLocation(); |
|
plRideAnimatedPhysMsg* enter = TRACKED_NEW plRideAnimatedPhysMsg(obj->GetKey(), nil, true, nil); |
|
enter->SetBCastFlag(plMessage::kPropagateToModifiers); |
|
plRideAnimatedPhysMsg* exit = TRACKED_NEW plRideAnimatedPhysMsg(obj->GetKey(), nil, false, nil); |
|
exit->SetBCastFlag(plMessage::kPropagateToModifiers); |
|
plRidingAnimatedPhysicalDetector *detector = TRACKED_NEW plRidingAnimatedPhysicalDetector(enter, exit); |
|
// Register the detector |
|
//node->AddModifier(detector, IGetUniqueName(node)); |
|
plKey detectorKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), detector, loc); |
|
hsgResMgr::ResMgr()->AddViaNotify(detectorKey, TRACKED_NEW plObjRefMsg(obj->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); |
|
return true; |
|
}
|
|
|