/*==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 3 ds 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 , 3 ds 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 "hsWindows.h"
# include "plComponent.h"
# include "plComponentReg.h"
# pragma hdrstop
void DummyCodeIncludeFuncPhysConst ( )
{
}
# define PHYS_CONST_HINGE_CID Class_ID(0x790b1637, 0x32c94144)
# define PHYS_CONST_WHEEL_CID Class_ID(0x6e2958dc, 0x62e86e87)
# define PHYS_CONST_SS_CID Class_ID(0x14843886, 0x62a24e94)
# define PHYS_CONST_BRIDGE_CID Class_ID(0x5f99392f, 0x3e5a5807)
OBSOLETE_CLASS ( plPhysHingeConstraintComponent , gPhysHingeConstDesc , " (ex)Hinge Constraint " , " (ex)Hinge Constraint " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_HINGE_CID )
OBSOLETE_CLASS ( plPhysBridgeComponent , gPhysBridgeConstDesc , " (ex)Bridge " , " Bridge " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_BRIDGE_CID )
OBSOLETE_CLASS ( plStrongSpringConstraintComponent , gPhysStrongSpringConstDesc , " (ex)StrongSpring Constraint " , " (ex)StrongSpring Constraint " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_SS_CID )
#if 0
# include <hkdynamics/defs.h>
# include <hkdynamics/entity/rigidcollection.h>
# include <hkdynamics/util/units.h>
//#include "plHavok1/plHKConstraintSolver.h" //Got Havok Messiness... Must go before all plasma directories...
//#include "plHavok1/plHavokConstraintTools.h"
# include "plPhysicalComponents.h"
# include "plComponentProcBase.h"
# include "plPhysical/plPhysicsGroups.h"
# include "MaxMain/plPhysicalProps.h"
//#include "max.h" //Max Dependencies, reffed in plEventGroupDefs
# include "resource.h" //Resource Dependencies
# include "hsResMgr.h" // Ibid
# include "plComponent.h" //Component Dependencies
# include "plComponentReg.h" // Ibid
# include "pnSceneObject/plSceneObject.h" // Ibid
# include "pnSceneObject/plCoordinateInterface.h"
# include "plScene/plSceneNode.h" // Ibid
# include "pnKeyedObject/plKey.h" // Ibid
# include "MaxMain/plMaxNode.h" // Ibid
# include "MaxConvert/hsConverterUtils.h" //Conversion Dependencies
# include "MaxConvert/hsControlConverter.h" // Ibid
# include "plHavok1/plHKPhysical.h" //Havok Dependencies
# include "MaxMain/plPhysicalProps.h"
# include "plgDispatch.h" //Message Dependencies
# include "pnMessage/plObjRefMsg.h" // Ibid
# include "pnMessage/plIntRefMsg.h" // Ibid
# include "pnMessage/plNodeRefMsg.h" // Ibid
# include "MaxMain/plPlasmaRefMsgs.h" // Ibid
# include "plModifier/plAliasModifier.h"
//
// DummyCodeIncludeFuncPhys Function.
// Necessary to keep the compiler from throwing away this file.
// No functions within are inherently called otherwise....
//
//
class plPhysConstraintAccessor : public PBAccessor
{
public :
//! Public Accessor Class, used in ParamBlock2 processing.
/*!
Workhorse for this Accessor Class ( derived from Max ' s PBAccessor ) .
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 .
*/
void Set ( PB2Value & v , ReferenceMaker * owner , ParamID id , int tabIndex , TimeValue t )
{
plComponentBase * comp = ( plComponentBase * ) owner ;
comp - > NotifyDependents ( FOREVER , PART_ALL , REFMSG_USER_COMP_REF_CHANGED ) ;
}
} ;
//! Global variable.
plPhysConstraintAccessor gPhysConstraintAccessor ;
//! Physical Hinge Constraint Component Class
/*!
This Class offers the very limited functionality , specifically wheel constraint
Physical properties . It relies on the Core ' s Convert functionality .
The function GetParamVals is processed uniquely , to offer transparency into the Core
internal states found in its PhysicalStats member function , fUserInput .
member functions :
GetParamVals ( plMaxNode * pNode , plErrorMsg * pErrMsg )
PreConvert ( plMaxNode * node , plErrorMsg * pErrMsg ) ;
\ sa plPhysDetectorComponent ( ) , DeleteThis ( ) , GetParamVals ( ) , PreConvert ( ) , Convert ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
class plPhysHingeConstraintComponent : plComponent
{
public :
enum
{
kPositionPtr ,
kParent ,
kParentPinnedBool ,
kFriction ,
kUpperAngle ,
kLowerAngle ,
kRebound ,
kStrength ,
kUseParentBool ,
kChildPinnedBool ,
} ;
enum
{
kYAxis ,
kXAxis ,
kZAxis ,
} ;
//! Constructor function for class
/*!
Herein the ClassDesc2 object that is used extensively by the ParamBlock2
has gained accessibiltiy . Auto - Creation of the UI is done here as well .
\ sa DeleteThis ( ) , GetParamVals ( ) , PreConvert ( ) , Convert ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
plPhysHingeConstraintComponent ( ) ;
//! Detector GetParamVals function for class, with 1 input.
/*!
Partial Transparency . The following Internal states are accessible :
- Bounce
- Friction
- Collision Reporting
- Bounding Surface State
- Disabling LOS
- Disable Ghost
\ param pNode a plMaxNode ptr , is the only formal parameter .
\ sa DeleteThis ( ) , plPhysicalCoreComponent ( ) , Convert ( ) , PreConvert ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
bool GetParamVals ( plMaxNode * pNode , plErrorMsg * pErrMsg ) ;
//! Detector PreConvert, takes in two variables and return a bool.
/*!
Calls the function MaybeMakeLocal ( ) and Sets Drawable to false .
Takes in two variables , being :
\ param node a plMaxNode ptr .
\ param pErrMsg a pErrMsg ptr .
\ return A bool expressing the success of the operation .
\ sa DeleteThis ( ) , plPhysicalCoreComponent ( ) , Convert ( ) , GetParamVals ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
bool SetupProperties ( plMaxNode * node , plErrorMsg * pErrMsg ) ;
bool PreConvert ( plMaxNode * node , plErrorMsg * plErrorMsg ) { return true ; }
bool Convert ( plMaxNode * node , plErrorMsg * pErrMsg ) ;
} ;
//
// plPhysHingeConstraint Component MacroConstructor
//
CLASS_DESC ( plPhysHingeConstraintComponent , gPhysHingeConstDesc , " (ex)Hinge Constraint " , " (ex)Hinge Constraint " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_HINGE_CID )
enum { HackVal = 1 } ;
ParamBlockDesc2 gPhysHingeConstraintBk
(
plComponent : : kBlkComp , _T ( " Hinge Constraint " ) , 0 , & gPhysHingeConstDesc , P_AUTO_CONSTRUCT + P_AUTO_UI , plComponent : : kRefComp ,
//Roll out
IDD_COMP_PHYS_HINGE_CONSTRAINT , IDS_COMP_PHYS_HINGE_CONSTRAINTS , 0 , 0 , NULL , //&gPhysCoreComponentProc,
// params
plPhysHingeConstraintComponent : : kPositionPtr , _T ( " Rotation Axis Conditions " ) , TYPE_INT , 0 , 0 ,
p_ui , TYPE_RADIO , 3 , IDC_COMP_PHYS_HINGE_AXIS_RADIO , IDC_COMP_PHYS_HINGE_AXIS_RADIO2 , IDC_COMP_PHYS_HINGE_AXIS_RADIO3 ,
p_vals , plPhysHingeConstraintComponent : : kXAxis , plPhysHingeConstraintComponent : : kYAxis , plPhysHingeConstraintComponent : : kZAxis ,
p_default , plPhysHingeConstraintComponent : : kZAxis ,
end ,
plPhysHingeConstraintComponent : : kUseParentBool , _T ( " UseParentChkBx " ) , TYPE_BOOL , P_ANIMATABLE , 0 ,
p_ui , TYPE_SINGLECHEKBOX , IDC_COMP_PHYS_USE_PARENT_BOOL ,
p_default , TRUE ,
p_enable_ctrls , 2 , plPhysHingeConstraintComponent : : kParent , plPhysHingeConstraintComponent : : kParentPinnedBool ,
end ,
plPhysHingeConstraintComponent : : kParent , _T ( " Parent " ) , TYPE_INODE , 0 , 0 ,
p_ui , TYPE_PICKNODEBUTTON , IDC_COMP_PHYS_PARENT ,
p_sclassID , GEOMOBJECT_CLASS_ID ,
p_prompt , IDS_COMP_PHYS_CHOSEN_BASE ,
p_accessor , & gPhysConstraintAccessor ,
end ,
plPhysHingeConstraintComponent : : kParentPinnedBool , _T ( " ParentPinnedChkBx " ) , TYPE_BOOL , P_ANIMATABLE , 0 ,
p_default , FALSE ,
p_ui , TYPE_SINGLECHEKBOX , IDC_COMP_PHYS_PINNED_STATE_BOOL ,
end ,
plPhysHingeConstraintComponent : : kFriction , _T ( " Friction " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 1.0 ,
p_range , 0.0 , 50000.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHYS_FRICTION_SLIDER , IDC_COMP_PHYS_FRICTION_SPIN1 , 1.0 ,
end ,
plPhysHingeConstraintComponent : : kUpperAngle , _T ( " UpperLimit " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.0 ,
p_range , - 360.0 , 360.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_COMP_PHYS_OPENANGLE_EDIT , IDC_COMP_PHYS_OPENANGLE_SPIN , 1.0 ,
end ,
plPhysHingeConstraintComponent : : kLowerAngle , _T ( " LowerLimit " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 360.0 ,
p_range , - 360.0 , 360.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_COMP_PHYS_CLOSEANGLE_EDIT , IDC_COMP_PHYS_CLOSEANGLE_SPIN , 1.0 ,
end ,
plPhysHingeConstraintComponent : : kRebound , _T ( " Rebound " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.1 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHYS_TAU_SLIDER , IDC_COMP_PHYS_TAU_SPIN , .01f ,
end ,
plPhysHingeConstraintComponent : : kStrength , _T ( " Strength " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.5 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHYS_STRENGTH_SLIDER , IDC_COMP_PHYS_STRENGTH_SPIN , .01f ,
end ,
plPhysHingeConstraintComponent : : kChildPinnedBool , _T ( " ChildPinnedChkBx " ) , TYPE_BOOL , P_ANIMATABLE , 0 ,
p_default , FALSE ,
p_ui , TYPE_SINGLECHEKBOX , IDC_COMP_PHYS_PINNED_STATE_BOOL2 ,
end ,
end
) ;
//
// PhysHingeConstraint Component Constructor
//
//
plPhysHingeConstraintComponent : : plPhysHingeConstraintComponent ( )
{
fClassDesc = & gPhysHingeConstDesc ;
fClassDesc - > MakeAutoParamBlocks ( this ) ;
}
//
// plPhysHingeConstraintComponent GetParamVals Function
//
//
bool plPhysHingeConstraintComponent : : GetParamVals ( plMaxNode * node , plErrorMsg * pErrMsg )
{
return true ;
}
//
// Physical Wheel Constraint Component PreConvert Function
//
//
bool plPhysHingeConstraintComponent : : SetupProperties ( plMaxNode * pNode , plErrorMsg * pErrMsg )
{
/*
plMaxNodeData * pMD = pNode - > GetMaxNodeData ( ) ;
pMD - > SetMovable ( true ) ;
pMD - > SetForceLocal ( true ) ;
plMaxNode * ParentNode = ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ;
plMaxNodeData * pMD2 = ParentNode - > GetMaxNodeData ( ) ;
pMD2 - > SetMovable ( true ) ;
pMD2 - > SetForceLocal ( true ) ;
*/
/*
bool HasPhysFlag = false ;
for ( int i = 0 ; i < pNode - > NumAttachedComponents ( ) ; i + + )
{
plComponentBase * thisComp = pNode - > GetAttachedComponent ( i ) ;
if ( thisComp - > ClassID ( ) = = PHYSICS_DEBUG_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( thisComp - > ClassID ( ) = = PHYSICS_TERRAIN_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( thisComp - > ClassID ( ) = = PHYSICS_DETECTOR_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( thisComp - > ClassID ( ) = = PHYSICS_INVISIBLE_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( thisComp - > ClassID ( ) = = PHYSICS_PLAYER_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( thisComp - > ClassID ( ) = = PHYSICS_SIMPLE_CID & & ! HasPhysFlag ) HasPhysFlag = true ;
if ( HasPhysFlag ) break ;
} */
GetParamVals ( pNode , pErrMsg ) ;
if ( fCompPB - > GetINode ( kParent ) & & fCompPB - > GetInt ( kUseParentBool ) )
if ( ! ( ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ) - > CanConvert ( ) )
{
pErrMsg - > Set ( true , " Ignored Parent Value " , " Parent %s was set to be Ignored. No Constraint was used. " , ( fCompPB - > GetINode ( kParent ) - > GetName ( ) ) ) . Show ( ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
return true ;
}
extern PlasmaToHavokQuat ( Havok : : Quaternion & a , hsQuat & b ) ;
bool plPhysHingeConstraintComponent : : Convert ( plMaxNode * node , plErrorMsg * pErrMsg )
{
plHingeConstraintMod * HMod = new plHingeConstraintMod ;
plMaxNode * ParentNode = ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ;
if ( ParentNode )
{
if ( ! ParentNode - > GetPhysicalProps ( ) - > IsUsed ( ) )
{
pErrMsg - > Set ( true , " Need a Physical Component " , " Object %s has a Physical Constraint but no Physical Component. No Constraint was used. " , ( node - > GetName ( ) ) ) . Show ( ) ;
pErrMsg - > Set ( false ) ;
}
}
if ( ! node - > GetPhysicalProps ( ) - > IsUsed ( ) )
{
pErrMsg - > Set ( true , " Need a Physical Component " , " Object %s has a Physical Constraint but no Physical Component. No Constraint was used. " , ( node - > GetName ( ) ) ) . Show ( ) ;
pErrMsg - > Set ( false ) ;
}
// Using the MotorTorque field, just to keep from creating yet another field in our bloated base class.
if ( fCompPB - > GetInt ( kParentPinnedBool ) )
HMod - > SetParentPin ( true ) ;
if ( fCompPB - > GetInt ( kChildPinnedBool ) )
HMod - > SetChildPin ( true ) ;
if ( fCompPB - > GetFloat ( kFriction ) )
HMod - > SetHCFriction ( 0 , fCompPB - > GetFloat ( kFriction ) ) ;
//Grab the pivot point from the child translate
hsPoint3 PP = node - > GetLocalToWorld44 ( ) . GetTranslate ( ) ;
hsVector3 PPVector ;
PPVector . Set ( PP . fX , PP . fY , PP . fZ ) ;
HMod - > SetPP ( PPVector ) ;
plKey ParentKey = nil ;
if ( fCompPB - > GetINode ( kParent ) & & fCompPB - > GetInt ( kUseParentBool ) )
if ( ( ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ) - > CanConvert ( ) )
{
plMaxNode * ParentNode = ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ;
ParentKey = ParentNode - > GetKey ( ) ;
}
else
{
pErrMsg - > Set ( true , " Ignored Position Value " , " Position %s was set to be Ignored. No Physical Proxy selected. " , ( fCompPB - > GetINode ( kPositionPtr ) - > GetName ( ) ) ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
hsVector3 HingeVector ;
if ( fCompPB - > GetInt ( kPositionPtr ) = = kZAxis )
{
HingeVector = node - > GetLocalToWorld44 ( ) . GetAxis ( hsMatrix44 : : kUp ) ;
HMod - > SetHCLimits ( kZAxis , 1 , fCompPB - > GetFloat ( kUpperAngle ) ) ;
HMod - > SetHCLimits ( kZAxis , 0 , fCompPB - > GetFloat ( kLowerAngle ) ) ;
}
else if ( fCompPB - > GetInt ( kPositionPtr ) = = kYAxis )
{
HingeVector = node - > GetLocalToWorld44 ( ) . GetAxis ( hsMatrix44 : : kView ) ;
HMod - > SetHCLimits ( kYAxis , 0 , - 1 * fCompPB - > GetFloat ( kUpperAngle ) ) ;
HMod - > SetHCLimits ( kYAxis , 1 , - 1 * fCompPB - > GetFloat ( kLowerAngle ) ) ;
}
else
{
HingeVector = node - > GetLocalToWorld44 ( ) . GetAxis ( hsMatrix44 : : kRight ) ;
HMod - > SetHCLimits ( kXAxis , 0 , - 1 * fCompPB - > GetFloat ( kUpperAngle ) ) ;
HMod - > SetHCLimits ( kXAxis , 1 , - 1 * fCompPB - > GetFloat ( kLowerAngle ) ) ;
}
HMod - > SetRotationAxis ( - 1 * HingeVector ) ;
HMod - > SetRR ( fCompPB - > GetFloat ( kRebound ) ) ;
HMod - > SetDamp ( fCompPB - > GetFloat ( kStrength ) ) ;
node - > AddModifier ( HMod , IGetUniqueName ( node ) ) ;
if ( ParentKey )
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( ParentKey , new plGenRefMsg ( HMod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kParentIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( node - > GetKey ( ) , new plGenRefMsg ( HMod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kChildIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
return true ;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class plPhysBridgeComponent : public plComponent
{
protected :
// Only used during convert
bool fIsValidated ;
public :
enum
{
kSections ,
kUpperAngle ,
kLowerAngle ,
kStiffness ,
kStrength ,
} ;
plPhysBridgeComponent ( ) ;
void SetDefaultTau ( ) ;
void ValidateSections ( ) ;
bool SetupProperties ( plMaxNode * node , plErrorMsg * errMsg ) ;
bool PreConvert ( plMaxNode * node , plErrorMsg * errMsg ) ;
bool Convert ( plMaxNode * node , plErrorMsg * errMsg ) ;
} ;
class plBridgeProc : public ParamMap2UserDlgProc
{
protected :
void ILoadList ( IParamBlock2 * pb , HWND hDlg ) ;
void IMoveListSel ( bool up , IParamBlock2 * pb , HWND hDlg ) ;
public :
BOOL DlgProc ( TimeValue t , IParamMap2 * pm , HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam ) ;
void DeleteThis ( ) { }
} ;
static plBridgeProc gBridgeComponentProc ;
CLASS_DESC ( plPhysBridgeComponent , gPhysBridgeConstDesc , " (ex)Bridge " , " Bridge " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_BRIDGE_CID )
ParamBlockDesc2 gPhysBridgeConstraintBk
(
plComponent : : kBlkComp , _T ( " Bridge " ) , 0 , & gPhysBridgeConstDesc , P_AUTO_CONSTRUCT + P_AUTO_UI , plComponent : : kRefComp ,
IDD_COMP_PHYS_BRIDGE , IDS_COMP_PHYS_BRIDGE , 0 , 0 , & gBridgeComponentProc ,
plPhysBridgeComponent : : kSections , _T ( " Sections " ) , TYPE_INODE_TAB , 0 , 0 , 0 ,
end ,
plPhysBridgeComponent : : kUpperAngle , _T ( " UpperLimit " ) , TYPE_FLOAT , 0 , 0 ,
p_default , 15.0 ,
p_range , 0.0 , 360.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_COMP_PHYS_OPENANGLE_EDIT , IDC_COMP_PHYS_OPENANGLE_SPIN , 1.0 ,
end ,
plPhysBridgeComponent : : kLowerAngle , _T ( " LowerLimit " ) , TYPE_FLOAT , 0 , 0 ,
p_default , - 15.0 ,
p_range , - 360.0 , 0.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_COMP_PHYS_CLOSEANGLE_EDIT , IDC_COMP_PHYS_CLOSEANGLE_SPIN , 1.0 ,
end ,
plPhysBridgeComponent : : kStiffness , _T ( " Stiffness " ) , TYPE_FLOAT , 0 , 0 ,
p_default , 1.0 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_STIFFNESS_EDIT , IDC_STIFFNESS_SPIN , 0.01 ,
end ,
plPhysBridgeComponent : : kStrength , _T ( " Strength " ) , TYPE_FLOAT , 0 , 0 ,
p_default , 0.4 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_FLOAT ,
IDC_STRENGTH_EDIT , IDC_STRENGTH_SPIN , 0.01 ,
end ,
end
) ;
plPhysBridgeComponent : : plPhysBridgeComponent ( ) : fIsValidated ( false )
{
fClassDesc = & gPhysBridgeConstDesc ;
fClassDesc - > MakeAutoParamBlocks ( this ) ;
}
void plPhysBridgeComponent : : SetDefaultTau ( )
{
int count = fCompPB - > Count ( kSections ) ;
float tau = 1.f / sqrt ( float ( count ) ) ;
fCompPB - > SetValue ( kStrength , 0 , tau ) ;
}
void plPhysBridgeComponent : : ValidateSections ( )
{
int i ;
// Make sure everything we're attached to is in our list of sections
for ( i = 0 ; i < NumTargets ( ) ; i + + )
{
INode * node = ( INode * ) GetTarget ( i ) ;
bool found = false ;
int count = fCompPB - > Count ( kSections ) ;
for ( int j = 0 ; j < count ; j + + )
{
if ( node = = fCompPB - > GetINode ( kSections , 0 , j ) )
{
found = true ;
break ;
}
}
if ( ! found )
fCompPB - > Append ( kSections , 1 , & node ) ;
}
// Make sure we're still attached to everything in our list of sections
for ( i = fCompPB - > Count ( kSections ) - 1 ; i > = 0 ; i - - )
{
plMaxNodeBase * node = ( plMaxNodeBase * ) fCompPB - > GetINode ( kSections , 0 , i ) ;
if ( ! IsTarget ( node ) )
fCompPB - > Delete ( kSections , i , 1 ) ;
}
}
bool plPhysBridgeComponent : : SetupProperties ( plMaxNode * node , plErrorMsg * errMsg )
{
if ( ! fIsValidated )
{
ValidateSections ( ) ;
fIsValidated = true ;
}
plPhysicalProps * physProps = node - > GetPhysicalProps ( ) ;
physProps - > SetMass ( 100.f , node , errMsg ) ;
physProps - > SetBoundsType ( plSimDefs : : kHullBounds , node , errMsg ) ;
// If the parent is the start or end anchor for the bridge, pin it
int numSections = fCompPB - > Count ( kSections ) ;
if ( node = = fCompPB - > GetINode ( kSections , 0 , 0 ) | |
( numSections > 0 & & node = = fCompPB - > GetINode ( kSections , 0 , numSections - 1 ) ) )
{
physProps - > SetPinned ( true , node , errMsg ) ;
physProps - > SetMemberGroup ( plHKPhysicsGroups : : kStaticSimulated , node , errMsg ) ;
}
else
{
physProps - > SetMemberGroup ( plHKPhysicsGroups : : kDynamicSimulated , node , errMsg ) ;
}
return true ;
}
bool plPhysBridgeComponent : : PreConvert ( plMaxNode * node , plErrorMsg * errMsg )
{
fIsValidated = false ;
return true ;
}
bool plPhysBridgeComponent : : Convert ( plMaxNode * node , plErrorMsg * errMsg )
{
plMaxNode * parent = nil ;
// Find the parent for this section
int count = fCompPB - > Count ( kSections ) ;
for ( int i = 0 ; i < count ; i + + )
{
plMaxNode * curNode = ( plMaxNode * ) fCompPB - > GetINode ( kSections , 0 , i ) ;
if ( curNode = = node )
{
if ( i < count - 1 )
parent = ( plMaxNode * ) fCompPB - > GetINode ( kSections , 0 , i + 1 ) ;
break ;
}
}
// No parent, must be the end anchor for the bridge
if ( ! parent )
return false ;
plHingeConstraintMod * mod = new plHingeConstraintMod ;
// mod->SetHCFriction(0, 1.f);
mod - > SetRR ( fCompPB - > GetFloat ( kStrength ) ) ; //1.f / sqrt(float(count)));
mod - > SetDamp ( fCompPB - > GetFloat ( kStiffness ) ) ;
// Grab the pivot point from the child translate
hsPoint3 pivot = node - > GetLocalToWorld44 ( ) . GetTranslate ( ) ;
hsVector3 pivotVec ;
pivotVec . Set ( pivot . fX , pivot . fY , pivot . fZ ) ;
mod - > SetPP ( pivotVec ) ;
// Cut'n'Paste
enum
{
kYAxis ,
kXAxis ,
kZAxis ,
} ;
hsVector3 hingeVector ;
hingeVector = node - > GetLocalToWorld44 ( ) . GetAxis ( hsMatrix44 : : kRight ) ;
// mod->SetHCLimits(kXAxis, 0, -1*fCompPB->GetFloat(kUpperAngle));
// mod->SetHCLimits(kXAxis, 1, -1*fCompPB->GetFloat(kLowerAngle));
mod - > SetRotationAxis ( - 1 * hingeVector ) ;
node - > AddModifier ( mod , IGetUniqueName ( node ) ) ;
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( parent - > GetKey ( ) , new plGenRefMsg ( mod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kParentIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( node - > GetKey ( ) , new plGenRefMsg ( mod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kChildIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
return true ;
}
///
void plBridgeProc : : ILoadList ( IParamBlock2 * pb , HWND hDlg )
{
HWND hList = GetDlgItem ( hDlg , IDC_SECT_LIST ) ;
for ( int i = 0 ; i < pb - > Count ( plPhysBridgeComponent : : kSections ) ; i + + )
{
INode * node = pb - > GetINode ( plPhysBridgeComponent : : kSections , 0 , i ) ;
ListBox_AddString ( hList , node - > GetName ( ) ) ;
}
}
void plBridgeProc : : IMoveListSel ( bool up , IParamBlock2 * pb , HWND hDlg )
{
HWND hList = GetDlgItem ( hDlg , IDC_SECT_LIST ) ;
int idx = ListBox_GetCurSel ( hList ) ;
int count = ListBox_GetCount ( hList ) ;
int newIdx = 0 ;
if ( up & & idx > 0 )
newIdx = idx - 1 ;
else if ( ! up & & idx < count - 1 )
newIdx = idx + 1 ;
else
return ;
INode * node = pb - > GetINode ( plPhysBridgeComponent : : kSections , 0 , idx ) ;
INode * swapNode = pb - > GetINode ( plPhysBridgeComponent : : kSections , 0 , newIdx ) ;
pb - > SetValue ( plPhysBridgeComponent : : kSections , 0 , node , newIdx ) ;
pb - > SetValue ( plPhysBridgeComponent : : kSections , 0 , swapNode , idx ) ;
ListBox_ResetContent ( hList ) ;
ILoadList ( pb , hDlg ) ;
ListBox_SetCurSel ( hList , newIdx ) ;
}
BOOL plBridgeProc : : DlgProc ( TimeValue t , IParamMap2 * pm , HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam )
{
switch ( msg )
{
case WM_INITDIALOG :
{
plPhysBridgeComponent * comp = ( plPhysBridgeComponent * ) pm - > GetParamBlock ( ) - > GetOwner ( ) ;
comp - > ValidateSections ( ) ;
ILoadList ( pm - > GetParamBlock ( ) , hWnd ) ;
}
return TRUE ;
case WM_COMMAND :
switch ( HIWORD ( wParam ) )
{
case BN_CLICKED :
if ( LOWORD ( wParam ) = = IDC_UP_BUTTON | | LOWORD ( wParam ) = = IDC_DN_BUTTON )
{
IMoveListSel ( ( LOWORD ( wParam ) = = IDC_UP_BUTTON ) , pm - > GetParamBlock ( ) , hWnd ) ;
return TRUE ;
}
else if ( LOWORD ( wParam ) = = IDC_DEF_STR_BUTTON )
{
plPhysBridgeComponent * comp = ( plPhysBridgeComponent * ) pm - > GetParamBlock ( ) - > GetOwner ( ) ;
comp - > SetDefaultTau ( ) ;
pm - > Invalidate ( plPhysBridgeComponent : : kStrength ) ;
return TRUE ;
}
break ;
case LBN_SELCHANGE :
{
bool hasSelection = ( ListBox_GetCurSel ( HWND ( lParam ) ) ! = LB_ERR ) ;
EnableWindow ( GetDlgItem ( hWnd , IDC_UP_BUTTON ) , hasSelection ) ;
EnableWindow ( GetDlgItem ( hWnd , IDC_DN_BUTTON ) , hasSelection ) ;
}
break ;
}
break ;
}
return FALSE ;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class plStrongSpringConstraintComponent : plComponent
{
public :
enum
{
kLength = 0 ,
kRebound ,
kStrength ,
kParent ,
kParentPinnedBool ,
} ;
//! Constructor function for class
/*!
Herein the ClassDesc2 object that is used extensively by the ParamBlock2
has gained accessibiltiy . Auto - Creation of the UI is done here as well .
\ sa DeleteThis ( ) , GetParamVals ( ) , PreConvert ( ) , Convert ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
plStrongSpringConstraintComponent ( ) ;
//! Detector GetParamVals function for class, with 1 input.
/*!
Partial Transparency . The following Internal states are accessible :
- Bounce
- Friction
- Collision Reporting
- Bounding Surface State
- Disabling LOS
- Disable Ghost
\ param pNode a plMaxNode ptr , is the only formal parameter .
\ sa DeleteThis ( ) , plPhysicalCoreComponent ( ) , Convert ( ) , PreConvert ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
bool GetParamVals ( plMaxNode * pNode , plErrorMsg * pErrMsg ) ;
//! Detector PreConvert, takes in two variables and return a bool.
/*!
Calls the function MaybeMakeLocal ( ) and Sets Drawable to false .
Takes in two variables , being :
\ param node a plMaxNode ptr .
\ param pErrMsg a pErrMsg ptr .
\ return A bool expressing the success of the operation .
\ sa DeleteThis ( ) , plPhysicalCoreComponent ( ) , Convert ( ) , GetParamVals ( ) , MaybeMakeLocal ( ) and FixUpPhysical ( )
*/
bool SetupProperties ( plMaxNode * node , plErrorMsg * pErrMsg ) ;
bool PreConvert ( plMaxNode * node , plErrorMsg * plErrorMsg ) { return true ; }
bool Convert ( plMaxNode * node , plErrorMsg * pErrMsg ) ;
} ;
//
// Hack! Hack! Don't talk back!
//
//
// Detector Component MacroConstructor
//
CLASS_DESC ( plStrongSpringConstraintComponent , gPhysStrongSpringConstDesc , " (ex)StrongSpring Constraint " , " (ex)StrongSpring Constraint " , COMP_TYPE_PHYS_CONSTRAINTS , PHYS_CONST_SS_CID )
//
// Wheel Constraint ParamBlock2
//
//
ParamBlockDesc2 gPhysSSConstraintBk
(
plComponent : : kBlkComp , _T ( " Strong Spring Constraint " ) , 0 , & gPhysStrongSpringConstDesc , P_AUTO_CONSTRUCT + P_AUTO_UI , plComponent : : kRefComp ,
//Roll out
IDD_COMP_PHYS_SS_CONSTRAINT , IDS_COMP_PHYS_SS_CONSTRAINTS , 0 , 0 , NULL , //&gPhysCoreComponentProc,
// params
plStrongSpringConstraintComponent : : kLength , _T ( " Length " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.0 ,
p_range , 0.0 , 500.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHY_SS_LENGTH_EDIT , IDC_COMP_PHY_SS_LENGTH_SPIN , 1.0 ,
end ,
plStrongSpringConstraintComponent : : kRebound , _T ( " Rebound " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.0 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHYS_SS_REBOUND_EDIT , IDC_COMP_PHYS_SS_REBOUND_SPIN , 0.1 ,
end ,
plStrongSpringConstraintComponent : : kStrength , _T ( " Strength " ) , TYPE_FLOAT , P_ANIMATABLE , 0 ,
p_default , 0.5 ,
p_range , 0.0 , 1.0 ,
p_ui , TYPE_SPINNER , EDITTYPE_POS_FLOAT ,
IDC_COMP_PHYS_SS_STRENGTH_EDIT , IDC_COMP_PHYS_SS_STRENGTH_SPIN , 0.1 ,
end ,
plStrongSpringConstraintComponent : : kParent , _T ( " Parent " ) , TYPE_INODE , 0 , 0 ,
p_ui , TYPE_PICKNODEBUTTON , IDC_COMP_PHYS_PARENT ,
//p_sclassID, GEOMOBJECT_CLASS_ID,
p_prompt , IDS_COMP_PHYS_CHOSEN_BASE ,
p_accessor , & gPhysConstraintAccessor ,
end ,
plStrongSpringConstraintComponent : : kParentPinnedBool , _T ( " PinnedChkBx " ) , TYPE_BOOL , 0 , 0 ,
p_default , FALSE ,
p_ui , TYPE_SINGLECHEKBOX , IDC_COMP_PHYS_USE_PARENT_BOOL ,
end ,
end
) ;
//
// Detector Component Constructor
//
//
plStrongSpringConstraintComponent : : plStrongSpringConstraintComponent ( )
{
fClassDesc = & gPhysStrongSpringConstDesc ;
fClassDesc - > MakeAutoParamBlocks ( this ) ;
}
//
// Detector Component GetParamVals Function
//
//
extern PlasmaToHavokQuat ( Havok : : Quaternion & a , hsQuat & b ) ;
bool plStrongSpringConstraintComponent : : GetParamVals ( plMaxNode * node , plErrorMsg * pErrMsg )
{
return true ;
}
//
// Physical Wheel Constraint Component PreConvert Function
//
//
bool plStrongSpringConstraintComponent : : SetupProperties ( plMaxNode * pNode , plErrorMsg * pErrMsg )
{
GetParamVals ( pNode , pErrMsg ) ;
if ( fCompPB - > GetINode ( kParent ) )
if ( ! ( ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ) - > CanConvert ( ) )
{
pErrMsg - > Set ( true , " Ignored Parent Value " , " Parent %s was set to be Ignored. No Constraint was used. " , ( fCompPB - > GetINode ( kParent ) - > GetName ( ) ) ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
else
{
pErrMsg - > Set ( true , " Bad Parent Value " , " Parent %s wasn't selected, all are currently necessary. " , ( fCompPB - > GetINode ( kParent ) - > GetName ( ) ) ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
if ( 500 > = fCompPB - > GetFloat ( kLength ) & & fCompPB - > GetFloat ( kLength ) > = 0 )
{
}
else
{
pErrMsg - > Set ( true , " Bad Spring Length Value " , " Strong Spring Constraint was out of range. Bailing out!. " ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
if ( fCompPB - > GetFloat ( kRebound ) > = 0 & & fCompPB - > GetFloat ( kRebound ) < = 1 )
{
}
else
{
pErrMsg - > Set ( true , " Bad Spring Rebound Value " , " Strong Spring Constraint was lost. Bailing out!. " ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
if ( fCompPB - > GetFloat ( kStrength ) > = 0 & & fCompPB - > GetFloat ( kStrength ) < = 1 )
{
}
else
{
pErrMsg - > Set ( true , " Bad Spring Strength Value " , " Strong Spring Constraint was lost. Bailing out!. " ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
return true ;
}
bool plStrongSpringConstraintComponent : : Convert ( plMaxNode * node , plErrorMsg * pErrMsg )
{
plStrongSpringConstraintMod * HMod = new plStrongSpringConstraintMod ;
HMod - > SetDamp ( fCompPB - > GetFloat ( kStrength ) ) ;
HMod - > SetRR ( fCompPB - > GetFloat ( kRebound ) ) ;
//No MaximumTorque here, might as well use that field for the Pinned state for the Parent...
HMod - > SetParentPin ( fCompPB - > GetInt ( kParentPinnedBool ) ) ;
Object * obj = fCompPB - > GetINode ( kParent ) - > EvalWorldState ( 0 /*hsConverterUtils::Instance().GetTime(GetInterface())*/ ) . obj ;
plKey ParentKey = nil ;
if ( fCompPB - > GetINode ( kParent ) )
if ( ( ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ) - > CanConvert ( ) & & ( obj - > ClassID ( ) = = Class_ID ( DUMMY_CLASS_ID , 0 ) | | obj - > SuperClassID ( ) = = GEOMOBJECT_CLASS_ID ) )
{
plMaxNode * ParentNode = ( plMaxNode * ) fCompPB - > GetINode ( kParent ) ;
ParentKey = ParentNode - > GetKey ( ) ;
}
else
{
pErrMsg - > Set ( true , " Ignored Parent Node " , " Parent Node %s was set to be Ignored. Bad! Bad!. " , ( fCompPB - > GetINode ( kParent ) - > GetName ( ) ) ) ;
pErrMsg - > Set ( false ) ;
return false ;
}
else
{
// pErrMsg->Set(true, "Bad Parent Node", " Parent Node %s wasn't selected. Strong Spring Constraint failed.", (fCompPB->GetINode(kParent)->GetName()));
// pErrMsg->Set(false);
// return false;
}
//No motor Angle here, might as well use the field for Length Storage...
HMod - > SetFixedLength ( fCompPB - > GetFloat ( kLength ) ) ;
node - > AddModifier ( HMod , IGetUniqueName ( node ) ) ;
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( ParentKey , new plGenRefMsg ( HMod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kParentIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
hsgResMgr : : ResMgr ( ) - > AddViaNotify ( node - > GetKey ( ) , new plGenRefMsg ( HMod - > GetKey ( ) , plRefMsg : : kOnCreate , plHavokConstraintsMod : : kChildIdx , 0 ) , plRefFlags : : kPassiveRef ) ;
return true ;
}
# endif