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.
309 lines
9.3 KiB
309 lines
9.3 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 "plPhysicalProps.h" |
|
#include "../plPhysical/plSimDefs.h" |
|
// For plBoundsType |
|
#include "../pnSceneObject/plSimulationInterface.h" |
|
|
|
#include "plMaxNode.h" |
|
#include "../MaxExport/plErrorMsg.h" |
|
|
|
/** These enums are used to indicate which parameters are ignorable and can |
|
be overridden. |
|
We can't use the "PhysFlags," below, for this, because those only cover boolean properties. |
|
*** We should use the same enum for both and just not worry that some of the enums aren't |
|
usable as "ignore" flags, -- the readability & simplification gain would be worth it. */ |
|
enum CanIgnore |
|
{ |
|
kMemberGroup = 0x1, |
|
kBounceGroup = 0x2, |
|
kReportGroup = 0x4, |
|
kMass = 0x8, |
|
kFriction = 0x10, |
|
kRestitution = 0x20, |
|
kBoundsType = 0x40, |
|
kProxyNode = 0x80, |
|
kPinned = 0x100, |
|
kAlignToOwner = 0x200, |
|
kCameraAvoid = 0x400, |
|
kPhysAnim = 0x800, |
|
kCanIgnoreLOSBlockCamera = 0x1000, |
|
kCanIgnoreLOSBlockUI = 0x2000, |
|
kCanIgnoreLOSUIItem = 0x4000, |
|
kCanIgnoreLOSBlockCustom = 0x8000, |
|
kCanIgnoreLOSShootable = 0x10000, |
|
kCanIgnoreLOSAvatarWalkable = 0x20000, |
|
kCanIgnoreLOSSwimRegion = 0x40000, |
|
|
|
kAll = 0xffffffff |
|
}; |
|
|
|
enum PhysFlags |
|
{ |
|
kFlagPinned = 0x1, |
|
kFlagAlignToOwner = 0x2, |
|
kFlagCameraAvoid = 0x4, |
|
kFlagPhysAnim = 0x8, |
|
kFlagStartInactive = 0x10, |
|
kFlagNoSynchronize = 0x20, |
|
kFlagLOSBlockCamera = 0x40, |
|
kFlagLOSBlockUI = 0x80, |
|
kFlagLOSUIItem = 0x100, |
|
kFlagLOSBlockCustom = 0x200, |
|
kFlagLOSShootable = 0x400, |
|
kFlagLOSAvatarWalkable = 0x800, |
|
kFlagLOSSwimRegion = 0x1000, |
|
}; |
|
|
|
plPhysicalProps::plPhysicalProps() : |
|
fUsed(false), |
|
fCanIgnore(kAll), |
|
fGroup(0), |
|
fReportGroup(0), |
|
fMass(0), |
|
fFriction(0), |
|
fRestitution(0), |
|
fBoundsType(plSimDefs::kHullBounds), |
|
fProxyNode(nil), |
|
fFlags(0), |
|
fSubworld(nil), |
|
fNoSynchronize(0), |
|
fStartInactive(0), |
|
fAvAnimPushable(0) |
|
{ |
|
} |
|
|
|
bool plPhysicalProps::SetGroup(UInt32 group, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetParam(fGroup, group, kMemberGroup, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetReportGroup(UInt32 notifyGroup, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetParam(fReportGroup, notifyGroup, kReportGroup, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetMass(float mass, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
if(mass != 0.0f) |
|
{ |
|
if (!GetPinned()) |
|
node->SetMovable(true); |
|
node->SetForceLocal(true); |
|
} |
|
return ISetParam(fMass, mass, kMass, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetFriction(float friction, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetParam(fFriction, friction, kFriction, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetRestitution(float restitution, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetParam(fRestitution, restitution, kRestitution, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetBoundsType(int boundsType, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
hsAssert(boundsType >= 1 && boundsType < plSimDefs::kNumBounds, "Bad bounds type"); |
|
return ISetParam(fBoundsType, boundsType, kBoundsType, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetProxyNode(plMaxNode *proxyNode, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
if( proxyNode ) |
|
proxyNode->SetDrawable(false); |
|
|
|
return ISetParam(fProxyNode, proxyNode, kProxyNode, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::IGetFlagParam(int flagType) |
|
{ |
|
return ((fFlags & flagType) != 0); |
|
} |
|
|
|
bool plPhysicalProps::ISetFlagParam(bool val, int flagType, int type, bool canIgnore, plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
bool ourVal = IGetFlagParam(flagType); |
|
if (ISetParam(ourVal, val, type, canIgnore, node, errMsg)) |
|
{ |
|
if (ourVal) |
|
fFlags |= flagType; |
|
else |
|
fFlags &= ~flagType; |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool plPhysicalProps::SetPinned(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagPinned, kPinned, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSBlockCamera(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSBlockCamera, kCanIgnoreLOSBlockCamera, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSBlockCamera() |
|
{ |
|
return IGetFlagParam(kFlagLOSBlockCamera); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSBlockUI(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSBlockUI, kCanIgnoreLOSBlockUI, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSBlockUI() |
|
{ |
|
return IGetFlagParam(kFlagLOSBlockUI); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSUIItem(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSUIItem, kCanIgnoreLOSUIItem, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSUIItem() |
|
{ |
|
return IGetFlagParam(kFlagLOSUIItem); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSBlockCustom(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSBlockCustom, kCanIgnoreLOSBlockCustom, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSBlockCustom() |
|
{ |
|
return IGetFlagParam(kFlagLOSBlockCustom); |
|
} |
|
|
|
bool plPhysicalProps::SetCameraAvoidFlag(bool allowLOS, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(allowLOS, kFlagCameraAvoid, kCameraAvoid, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSShootable(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSShootable, kCanIgnoreLOSShootable, canIgnore, node, errMsg); |
|
} |
|
bool plPhysicalProps::GetLOSShootable() |
|
{ |
|
return IGetFlagParam(kFlagLOSShootable); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSAvatarWalkable(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSAvatarWalkable, kCanIgnoreLOSAvatarWalkable, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSAvatarWalkable() |
|
{ |
|
return IGetFlagParam(kFlagLOSAvatarWalkable); |
|
} |
|
|
|
bool plPhysicalProps::SetLOSSwimRegion(bool status, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(status, kFlagLOSSwimRegion, kCanIgnoreLOSSwimRegion, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetLOSSwimRegion() |
|
{ |
|
return IGetFlagParam(kFlagLOSSwimRegion); |
|
} |
|
|
|
//bool plPhysicalProps::SetUILOSFlag(bool allowLOS, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
//{ |
|
// return ISetFlagParam(allowLOS, kFlagUILOS, kUILOS, canIgnore, node, errMsg); |
|
//} |
|
|
|
bool plPhysicalProps::SetAlignToOwner(bool alignToOwner, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(alignToOwner, kFlagAlignToOwner, kAlignToOwner, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::SetSubworld(plMaxNode* subworld) |
|
{ |
|
// Note that we do *not* set fUsed, because we don't (necessarily) want a physical for this node. |
|
// We just want to remember that it is a subworld. |
|
fSubworld = subworld; |
|
return true; |
|
} |
|
|
|
bool plPhysicalProps::SetPhysAnim(bool anim, plMaxNode *node, plErrorMsg *errMsg, bool canIgnore) |
|
{ |
|
return ISetFlagParam(anim, kFlagPhysAnim, kPhysAnim, canIgnore, node, errMsg); |
|
} |
|
|
|
bool plPhysicalProps::GetPinned() |
|
{ |
|
return IGetFlagParam(kFlagPinned); |
|
} |
|
|
|
bool plPhysicalProps::GetCameraAvoid() |
|
{ |
|
return IGetFlagParam(kFlagCameraAvoid); |
|
} |
|
|
|
bool plPhysicalProps::GetAlignToOwner() |
|
{ |
|
return IGetFlagParam(kFlagAlignToOwner); |
|
} |
|
|
|
bool plPhysicalProps::GetPhysAnim() |
|
{ |
|
return IGetFlagParam(kFlagPhysAnim); |
|
} |
|
|
|
void plPhysicalProps::SetCanIgnore(UInt32 type, bool canIgnore) |
|
{ |
|
if (canIgnore) |
|
fCanIgnore |= type; |
|
else |
|
fCanIgnore &= ~type; |
|
} |
|
|
|
bool plPhysicalProps::CanIgnore(UInt32 type) |
|
{ |
|
return ((fCanIgnore & type) != 0); |
|
} |
|
|
|
void plPhysicalProps::IDisplayErrorMsg(plMaxNode *node, plErrorMsg *errMsg) |
|
{ |
|
if (!errMsg->IsBogus()) |
|
{ |
|
errMsg->Set(true, |
|
"Physics Conflict", |
|
"The node \"%s\" has a conflict in its physical settings.\nMake sure the physical components on it are compatible.", |
|
node->GetName()).Show(); |
|
} |
|
}
|
|
|