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.
2559 lines
73 KiB
2559 lines
73 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
#include "HeadSpin.h" |
|
|
|
#include "max.h" //Max Dependencies |
|
|
|
#include "resource.h" //Resource Dependencies |
|
#include "hsResMgr.h" // Ibid |
|
|
|
#include "plComponent.h" //Component Dependencies |
|
#include "plComponentReg.h" |
|
#include "plCameraComponents.h" // Ibid |
|
#include "plAnimComponent.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 "../MaxMain/plMaxNodeData.h" // Ibid |
|
|
|
#include "../MaxConvert/plConvert.h" |
|
#include "../MaxConvert/hsConverterUtils.h" //Conversion Dependencies |
|
#include "../MaxConvert/hsControlConverter.h" // Ibid |
|
|
|
#include "../plPhysical/plSimDefs.h" |
|
|
|
#include "plgDispatch.h" //Message Dependencies |
|
#include "../pnMessage/plObjRefMsg.h" // Ibid |
|
#include "../pnMessage/plIntRefMsg.h" // Ibid |
|
#include "../pnMessage/plNodeRefMsg.h" // Ibid |
|
#include "../pnMessage/plCameraMsg.h" // Ibid |
|
#include "../MaxMain/plPlasmaRefMsgs.h" // Ibid |
|
#include "../pfAnimation/plLineFollowMod.h" |
|
#include "../plPhysical/plCollisionDetector.h" // MM |
|
|
|
#include "../pfCamera/plCameraBrain.h" |
|
#include "../pfCamera/plCameraModifier.h" |
|
#include "plMiscComponents.h" |
|
#include "../MaxMain/plPhysicalProps.h" |
|
#include "plPhysicalComponents.h" |
|
|
|
// Line Follow related |
|
#include "../plInterp/plAnimPath.h" |
|
#include "../plInterp/plController.h" |
|
#include "../pfAnimation/plLineFollowMod.h" |
|
#include "../pfAnimation/plFollowMod.h" |
|
|
|
#include <vector> |
|
#include <string> |
|
|
|
// |
|
// DummyCodeIncludeFuncPhys Function. |
|
// Necessary to keep the compiler from throwing away this file. |
|
// No functions within are inherently called otherwise.... |
|
// |
|
// |
|
|
|
void DummyCodeIncludeFuncCameras() |
|
{ |
|
} |
|
|
|
|
|
// struct for storing transition information temporarily: |
|
// used instead of camtrans because we don't have keys yet, |
|
// but need to set up at pre-convert |
|
struct PreTrans |
|
{ |
|
// used when creating default track transitions at runtime |
|
PreTrans(plSceneObject* to) |
|
{ |
|
fTransTo = to; |
|
|
|
fAccel = 60.0f; |
|
fDecel = 60.0f; |
|
fVelocity = 60.0f; |
|
fPOADecel = 60.0f; |
|
fPOAAccel = 60.0f; |
|
fPOAVelocity = 60.0f; |
|
|
|
fCutPos = false; |
|
fCutPOA = false; |
|
fIgnore = false; |
|
} |
|
plSceneObject* fTransTo; |
|
|
|
hsBool fCutPos; |
|
hsBool fCutPOA; |
|
hsBool fIgnore; |
|
hsScalar fAccel; |
|
hsScalar fDecel; |
|
hsScalar fVelocity; |
|
hsScalar fPOAAccel; |
|
hsScalar fPOADecel; |
|
hsScalar fPOAVelocity; |
|
|
|
|
|
}; |
|
|
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// limit pan component class |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plLimitPanComponent, gLimitPaneraDesc, "Allow Camera Panning", "Allow Camera Panning", COMP_TYPE_CAMERA, LIMITPAN_CID) |
|
|
|
|
|
enum |
|
{ |
|
kLimitPanX, |
|
kLimitPanZ, |
|
kPanXDeg, |
|
kPanZDeg, |
|
kMouseSensitivity, // obsolete |
|
}; |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gLimitPaneraBk |
|
( |
|
1, _T("camera"), 0, &gLimitPaneraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERAPAN, IDS_COMP_ALLOW_PAN, 0, 0, NULL, |
|
|
|
kLimitPanX, _T("Limit X"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_X_AXIS, |
|
end, |
|
|
|
kLimitPanZ, _T("Limit Z"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_Z_AXIS, |
|
end, |
|
|
|
kPanXDeg, _T("X degrees"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 180.0f, |
|
p_default, 90.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kPanZDeg, _T("Z degrees"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 180.0f, |
|
p_default, 90.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plLimitPanComponent::plLimitPanComponent() |
|
{ |
|
fClassDesc = &gLimitPaneraDesc; |
|
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 plLimitPanComponent::SetupProperties(plMaxNode* pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
hsBool plLimitPanComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plLimitPanComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// Camera Zoom component class |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
/// |
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plCameraZoomComponent, gCameraZoomeraDesc, "Allow Camera Zoom", "Allow Camera Zoom", COMP_TYPE_CAMERA, CAMERAZOOM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kZoomMaxDeg, |
|
kZoomMinDeg, |
|
kZoomRate, |
|
}; |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gCameraZoomeraBk |
|
( |
|
1, _T("camera"), 0, &gCameraZoomeraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERAZOOM, IDS_COMP_CAMERAZOOM, 0, 0, NULL, |
|
|
|
kZoomMaxDeg, _T("max degrees"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 180.0f, |
|
p_default, 120.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kZoomMinDeg, _T("min degrees"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 180.0f, |
|
p_default, 35.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kZoomRate, _T("degrees per sec"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 180.0f, |
|
p_default, 90.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY2, IDC_CAMERACMD_SPIN_OFFSETY2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plCameraZoomComponent::plCameraZoomComponent() |
|
{ |
|
fClassDesc = &gCameraZoomeraDesc; |
|
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 plCameraZoomComponent::SetupProperties(plMaxNode* pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
hsBool plCameraZoomComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plCameraZoomComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// Override transition component |
|
// |
|
// |
|
// |
|
// |
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plTransOverrideComponent, gTransOverrideeraDesc, "Override Transition", "Override Transition", COMP_TYPE_CAMERA, TRANSCAM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kTransitionTo, |
|
kCutTrans, |
|
kTrackTrans, |
|
kTransSpeed, |
|
kTransAccel, |
|
kCutPOA, |
|
kTrackPOA, |
|
kTransPOASpeed, |
|
kTransPOAAccel, |
|
kTransDecel, |
|
kTransPOADecel, |
|
kTransVelocity, |
|
kTrans, |
|
kIgnoreTrans, |
|
kTransPOAVelocity, |
|
}; |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gTransOverrideeraBk |
|
( |
|
1, _T("camera"), 0, &gTransOverrideeraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERA_TRANS, IDS_COMP_CAMERATRANS, 0, 0, NULL, |
|
|
|
kTransitionTo, _T("transitionto"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERARGN_PICKSTATE_BASE, |
|
p_sclassID, CAMERA_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
end, |
|
|
|
kCutTrans, _T("cut"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK1, |
|
end, |
|
|
|
kTrackTrans, _T("track"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK2, |
|
p_enable_ctrls, 3, kTransVelocity, kTransAccel, kTransDecel, |
|
end, |
|
|
|
kCutPOA, _T("cutPOA"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK3, |
|
end, |
|
|
|
kTrackPOA, _T("trackPOA"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK4, |
|
p_enable_ctrls, 3, kTransPOASpeed, kTransPOAAccel, kTransPOADecel, |
|
end, |
|
|
|
kTransVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL, IDC_CAMERA_VEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kTransAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL, IDC_CAMERA_ACCEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kTransDecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL, IDC_CAMERA_DECEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kTransPOAVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL2, IDC_CAMERA_VEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kTransPOAAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL2, IDC_CAMERA_ACCEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kTransPOADecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -200.0f, 200.0f, |
|
p_default, 100.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL2, IDC_CAMERA_DECEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kIgnoreTrans, _T("ignore"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK_IGNORE, |
|
end, |
|
end |
|
); |
|
|
|
plTransOverrideComponent::plTransOverrideComponent() |
|
{ |
|
fClassDesc = &gTransOverrideeraDesc; |
|
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 plTransOverrideComponent::SetupProperties(plMaxNode* pNode, plErrorMsg *pErrMsg) |
|
{ |
|
fTransKeys.clear(); |
|
return true; |
|
} |
|
|
|
|
|
hsBool plTransOverrideComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
// see if there is a camera specified |
|
INode* pCamNode = fCompPB->GetINode(kTransitionTo); |
|
|
|
PreTrans* pTrans = nil; |
|
if (pCamNode) |
|
pTrans = TRACKED_NEW PreTrans(((plMaxNode*)pCamNode)->GetSceneObject()); |
|
else |
|
pTrans = TRACKED_NEW PreTrans(nil); |
|
|
|
if (fCompPB->GetInt(kIgnoreTrans)) |
|
{ |
|
pTrans->fIgnore = true; |
|
} |
|
else |
|
if (fCompPB->GetInt(kTrackTrans)) |
|
{ |
|
pTrans->fCutPos = false; |
|
pTrans->fAccel = fCompPB->GetFloat(kTransAccel); |
|
pTrans->fDecel = fCompPB->GetFloat(kTransDecel); |
|
pTrans->fVelocity = fCompPB->GetFloat(kTransVelocity); |
|
} |
|
else |
|
{ |
|
pTrans->fCutPos = true; |
|
} |
|
if (fCompPB->GetInt(kTrackPOA)) |
|
{ |
|
pTrans->fCutPOA = false; |
|
pTrans->fPOAAccel = fCompPB->GetFloat(kTransPOAAccel); |
|
pTrans->fPOADecel = fCompPB->GetFloat(kTransPOADecel); |
|
pTrans->fPOAVelocity = fCompPB->GetFloat(kTransPOAVelocity); |
|
} |
|
else |
|
{ |
|
pTrans->fCutPOA = true; |
|
} |
|
fTransKeys[pNode] = pTrans; |
|
|
|
|
|
return true; |
|
} |
|
|
|
hsBool plTransOverrideComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plTransOverrideComponent::DeInit(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
TransitionKeys::iterator i = fTransKeys.begin(); |
|
|
|
for( ; i != fTransKeys.end(); i++ ) |
|
{ |
|
delete (*i).second; |
|
} |
|
fTransKeys.clear(); |
|
|
|
return plComponent::DeInit( node, pErrMsg ); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// POA components |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// avatar POA component... |
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plPOAAvatarComponent, gPOAAvatareraDesc, "Avatar POA", "Avatar POA", COMP_TYPE_CAMERA, AVATAR_POA_CID) |
|
|
|
enum |
|
{ |
|
kAvPOAOffX, |
|
kAvPOAOffY, |
|
kAvPOAOffZ, |
|
kAvPOAWorldspace, |
|
|
|
}; |
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gPOAAvatareraBk |
|
( |
|
1, _T("camera"), 0, &gPOAAvatareraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_AVATAR_POA, IDS_AVATARPOA, 0, 0, NULL, |
|
|
|
|
|
kAvPOAOffX, _T("PX Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX5, IDC_CAMERACMD_SPIN_OFFSETX5, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAvPOAOffY, _T("PY Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY4, IDC_CAMERACMD_SPIN_OFFSETY4, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAvPOAOffZ, _T("PZ Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ2, IDC_CAMERACMD_SPIN_OFFSETZ2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAvPOAWorldspace, _T("POAworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_POA_WORLDSPACE, |
|
end, |
|
|
|
|
|
end |
|
); |
|
|
|
plPOAAvatarComponent::plPOAAvatarComponent() |
|
{ |
|
fClassDesc = &gPOAAvatareraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// Object POA component |
|
// |
|
// |
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plPOAObjectComponent, gPOAObjecteraDesc, "Object POA", "Object POA", COMP_TYPE_CAMERA, OBJECT_POA_CID) |
|
|
|
|
|
enum |
|
{ |
|
kPOAObject, |
|
kPOAObjOffsetX, |
|
kPOAObjOffsetY, |
|
kPOAObjOffsetZ, |
|
kPOAObjWorldspace, |
|
}; |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gPOAObjecteraBk |
|
( |
|
1, _T("camera"), 0, &gPOAObjecteraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_OBJECT_POA, IDS_COMP_OBJECTPOA, 0, 0, NULL, |
|
|
|
kPOAObject, _T("objectPOA"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CLICK_PROXY, |
|
p_sclassID, GEOMOBJECT_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
end, |
|
|
|
kPOAObjOffsetX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kPOAObjOffsetY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kPOAObjOffsetZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kPOAObjWorldspace, _T("POAworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_OBJECTPOA_WORLDSPACE, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plPOAObjectComponent::plPOAObjectComponent() |
|
{ |
|
fClassDesc = &gPOAObjecteraDesc; |
|
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 plPOAObjectComponent::SetupProperties(plMaxNode* pNode, plErrorMsg *pErrMsg) |
|
{ |
|
if (fCompPB->GetINode(kPOAObject)) |
|
{ |
|
plMaxNode *pPOA = ((plMaxNode*)fCompPB->GetINode(kPOAObject)); |
|
if (pPOA) |
|
{ |
|
pPOA->SetForceLocal(true); |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
hsBool plPOAObjectComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
plKey plPOAObjectComponent::GetObjectKey() |
|
{ |
|
if (fCompPB->GetINode(kPOAObject)) |
|
return ((plMaxNode*)(fCompPB->GetINode(kPOAObject)))->GetSceneObject()->GetKey(); |
|
return nil; |
|
} |
|
|
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// Make Default component... |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
//Max desc stuff necessary. |
|
CLASS_DESC(plMakeDefaultCamComponent, gMakeDefaultCameraDesc, "Make Default Camera", "Make Default Camera", COMP_TYPE_CAMERA, DEFAULTCAM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kMakeDefaultCam, |
|
}; |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gMakeDefaultCameraBk |
|
( |
|
1, _T("camera"), 0, &gMakeDefaultCameraDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
|
|
end |
|
); |
|
|
|
plMakeDefaultCamComponent::plMakeDefaultCamComponent() |
|
{ |
|
fClassDesc = &gMakeDefaultCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
|
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// base class for all camera components which make a plCameraModifier |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
hsBool plCameraBaseComponent::IsValidNodeType(plMaxNode *pNode) |
|
{ |
|
Object *obj = pNode->EvalWorldState(hsConverterUtils::Instance().GetTime(pNode->GetInterface())).obj; |
|
TimeValue Now = hsConverterUtils::Instance().GetTime(pNode->GetInterface()); |
|
if(obj->ConvertToType(Now, Class_ID(LOOKAT_CAM_CLASS_ID, 0))) |
|
return true; |
|
else |
|
return false; |
|
} |
|
|
|
hsBool plCameraBaseComponent::SetupProperties(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
fModKeys.clear(); |
|
hsBool ValidNode = IsValidNodeType(pNode); |
|
if(!ValidNode){ |
|
if(pErrMsg->Set(true, "Invalid Camera Object", "The camera %s is not a 'Max Target Camera type'. This camera will be disabled..\nKill the export?",((INode*)pNode)->GetName()).Ask()) |
|
pErrMsg->Set(true, "", ""); |
|
else |
|
pErrMsg->Set(false); // Don't want to abort |
|
|
|
return false; |
|
} |
|
plMaxNode* node = ((plMaxNode*)pNode->GetTarget()); |
|
if (node) |
|
{ |
|
node->SetDrawable(false); |
|
node->SetMovable(true); |
|
node->SetForceLocal(true); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
hsBool plCameraBaseComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plCameraBaseComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
// check for overriden transitions and special animation commands |
|
int count = node->NumAttachedComponents(); |
|
for (UInt32 x = 0; x < count; x++) |
|
{ |
|
plComponentBase *comp = node->GetAttachedComponent(x); |
|
if (comp->ClassID() == TRANSCAM_CID) |
|
{ |
|
plTransOverrideComponent* pTrans = (plTransOverrideComponent*)comp; |
|
int idx = 0; |
|
plTransOverrideComponent::TransitionKeys::const_iterator it; |
|
for (it = pTrans->fTransKeys.begin(); it != pTrans->fTransKeys.end(); it++) |
|
{ |
|
if (it->first != node) |
|
continue; |
|
PreTrans *trans = it->second; |
|
// convert the pre transition to a camera transition (get the camera modifier key that we are going to) |
|
plSceneObject* pObj = trans->fTransTo; |
|
const plCameraModifier1* pCamMod = nil; |
|
if (pObj) |
|
{ |
|
for (int i = 0; i < pObj->GetNumModifiers(); i++) |
|
{ |
|
pCamMod = plCameraModifier1::ConvertNoRef(pObj->GetModifier(i)); |
|
if (pCamMod) |
|
break; |
|
} |
|
} |
|
CamTrans* camTrans = nil; |
|
if (!pCamMod) |
|
camTrans = TRACKED_NEW CamTrans(nil); |
|
else |
|
camTrans = TRACKED_NEW CamTrans(pCamMod->GetKey()); |
|
|
|
camTrans->fAccel = trans->fAccel; |
|
camTrans->fDecel = trans->fDecel; |
|
camTrans->fVelocity = trans->fVelocity; |
|
camTrans->fPOAAccel = trans->fPOAAccel; |
|
camTrans->fPOADecel = trans->fPOADecel; |
|
camTrans->fPOAVelocity = trans->fPOAVelocity; |
|
camTrans->fCutPOA = trans->fCutPOA; |
|
camTrans->fCutPos = trans->fCutPos; |
|
camTrans->fIgnore = trans->fIgnore; |
|
|
|
fModKeys[node]->AddTrans(camTrans); |
|
idx++; |
|
} |
|
|
|
} |
|
} |
|
return true; |
|
} |
|
|
|
plCameraModifier1* plCameraBaseComponent::ICreateCameraModifier(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
|
|
GenCamera* theCam = nil; |
|
Object* obj = pNode->EvalWorldState(hsConverterUtils::Instance().GetTime(pNode->GetInterface())).obj; |
|
TimeValue Now = hsConverterUtils::Instance().GetTime(pNode->GetInterface()); |
|
|
|
if (obj->ConvertToType(Now, Class_ID(LOOKAT_CAM_CLASS_ID, 0))) |
|
theCam = (GenCamera *) obj->ConvertToType(Now, Class_ID(LOOKAT_CAM_CLASS_ID, 0)); |
|
else |
|
{ |
|
return nil; |
|
} |
|
|
|
pNode->SetDrawable(false); |
|
pNode->SetForceLocal(true); |
|
pNode->SetItinerant(true); |
|
|
|
// create run-time objects |
|
|
|
plCameraModifier1* pMod = TRACKED_NEW plCameraModifier1; |
|
|
|
plKey modifierKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pMod, pNode->GetLocation()); |
|
hsgResMgr::ResMgr()->AddViaNotify(modifierKey, TRACKED_NEW plObjRefMsg(pNode->GetSceneObject()->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); |
|
|
|
|
|
obj = pNode->EvalWorldState(hsConverterUtils::Instance().GetTime(pNode->GetInterface())).obj; |
|
|
|
hsVector3 pt; |
|
|
|
float FOVvalue= 0.0; //Currently in Radians |
|
// radians |
|
FOVvalue = theCam->GetFOV(Now); |
|
// convert |
|
FOVvalue = FOVvalue*(180/3.141592); |
|
int FOVType = theCam->GetFOVType(); |
|
hsScalar wDeg, hDeg; |
|
switch(FOVType) |
|
{ |
|
case 0: // FOV_W |
|
{ |
|
wDeg = FOVvalue; |
|
hDeg = (wDeg*3)/4; |
|
} |
|
break; |
|
case 1: // FOV_H |
|
{ |
|
hDeg = FOVvalue; |
|
wDeg = (hDeg*4)/3; |
|
} |
|
break; |
|
} |
|
pMod->SetFOVw(wDeg); |
|
pMod->SetFOVh(hDeg); |
|
|
|
pNode->AddModifier(pMod, IGetUniqueName(pNode)); |
|
return pMod; |
|
} |
|
|
|
|
|
void plCameraBaseComponent::ISetLimitPan(plMaxNode* pNode, plCameraBrain1* pBrain) |
|
{ |
|
plComponentBase* LimitPanComp = 0; |
|
|
|
for (UInt32 x = 0; x < pNode->NumAttachedComponents(); x++) |
|
{ |
|
plComponentBase *comp = pNode->GetAttachedComponent(x); |
|
if (comp->ClassID() == LIMITPAN_CID) |
|
LimitPanComp = comp; |
|
} |
|
if (LimitPanComp) |
|
{ |
|
// set this camera to limit panning x degrees |
|
IParamBlock2* pBlk = LimitPanComp->GetParamBlock(plComponentBase::kRefComp); |
|
if ( pBlk && pBlk->GetInt(kLimitPanX) ) |
|
{ |
|
hsScalar deg = pBlk->GetFloat(kPanZDeg); |
|
hsScalar rad = hsScalarDegToRad(deg); |
|
pBrain->SetXPanLimit( rad * 0.5f ); |
|
} |
|
if ( pBlk && pBlk->GetInt(kLimitPanZ) ) |
|
{ |
|
hsScalar deg = pBlk->GetFloat(kPanXDeg); |
|
hsScalar rad = hsScalarDegToRad(deg); |
|
pBrain->SetZPanLimit( rad * 0.5f ); |
|
} |
|
} |
|
} |
|
|
|
void plCameraBaseComponent::ISetLimitZoom(plMaxNode* pNode, plCameraBrain1* pBrain) |
|
{ |
|
plComponentBase* LimitZoomComp = 0; |
|
|
|
for (UInt32 x = 0; x < pNode->NumAttachedComponents(); x++) |
|
{ |
|
plComponentBase *comp = pNode->GetAttachedComponent(x); |
|
if (comp->ClassID() == CAMERAZOOM_CID) |
|
LimitZoomComp = comp; |
|
} |
|
if (LimitZoomComp) |
|
{ |
|
// set this camera to limit panning x degrees |
|
IParamBlock2* pBlk = LimitZoomComp->GetParamBlock(plComponentBase::kRefComp); |
|
hsScalar max = pBlk->GetFloat(kZoomMaxDeg); |
|
hsScalar min = pBlk->GetFloat(kZoomMinDeg); |
|
hsScalar rate = pBlk->GetFloat(kZoomRate); |
|
pBrain->SetZoomParams(max / 1.33333333, min / 1.33333333, rate); |
|
} |
|
} |
|
|
|
void plCameraBaseComponent::ISetIgnoreSubworld(plMaxNode* pNode, plCameraBrain1* pBrain) |
|
{ |
|
plComponentBase* subComp = 0; |
|
|
|
for (UInt32 x = 0; x < pNode->NumAttachedComponents(); x++) |
|
{ |
|
plComponentBase *comp = pNode->GetAttachedComponent(x); |
|
if (comp->ClassID() == CAM_IGNORE_SUB_CID) |
|
subComp = comp; |
|
} |
|
if (subComp) |
|
{ |
|
// set this camera to ignore subworld movement |
|
pBrain->SetFlags(plCameraBrain1::kIgnoreSubworldMovement); |
|
} |
|
} |
|
|
|
|
|
|
|
plCameraModifier1* plCameraBaseComponent::ICreateFocalPointObject(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
plMaxNode* node = ((plMaxNode*)pNode->GetTarget()); |
|
|
|
plCameraModifier1* pPOAMod = TRACKED_NEW plCameraModifier1; |
|
|
|
plKey poaModifierKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pPOAMod, node->GetLocation()); |
|
hsgResMgr::ResMgr()->AddViaNotify(poaModifierKey, TRACKED_NEW plObjRefMsg(node->GetKey(), plRefMsg::kOnCreate, -1, plObjRefMsg::kModifier), plRefFlags::kActiveRef); |
|
|
|
|
|
plCameraBrain1* pPOABrain = TRACKED_NEW plCameraBrain1(pPOAMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pPOABrain, pNode->GetLocation()); |
|
|
|
plGenRefMsg* pGRMsg = TRACKED_NEW plGenRefMsg(pPOAMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pGRMsg->SetRef( (hsKeyedObject*)pPOABrain ); |
|
plConvert::Instance().AddMessageToQueue(pGRMsg); |
|
|
|
return (pPOAMod); |
|
} |
|
|
|
|
|
hsBool plCameraBaseComponent::ISetPOA(plMaxNode* pNode, plCameraBrain1* pBrain, plErrorMsg* pErrMsg) |
|
{ |
|
// do we want a special POA for this brain |
|
hsBool bResult = false; |
|
hsBool bAvPOA = false; |
|
plComponentBase* POAComp = 0; |
|
hsBool bPOAObject = false; |
|
plComponentBase* objPOAComp = 0; |
|
|
|
for (UInt32 x = 0; x < pNode->NumAttachedComponents(); x++) |
|
{ |
|
plComponentBase *comp = pNode->GetAttachedComponent(x); |
|
if (comp->ClassID() == OBJECT_POA_CID) |
|
{ |
|
if (objPOAComp != 0 || POAComp != 0) |
|
{ |
|
pErrMsg->Set(true, "Export Error - Cameras", |
|
"Object %s : Cameras must have one and only one POA component!\n", |
|
pNode->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
objPOAComp = comp; |
|
bPOAObject = true; |
|
} |
|
if (comp->ClassID() == AVATAR_POA_CID) |
|
{ |
|
if (objPOAComp != 0 || POAComp != 0) |
|
{ |
|
pErrMsg->Set(true, "Export Error - Cameras", |
|
"Object %s : Cameras must have one and only one POA component!\n", |
|
pNode->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
bAvPOA = true; |
|
POAComp = comp; |
|
} |
|
} |
|
if (bPOAObject) |
|
{ |
|
IParamBlock2* pBlk = objPOAComp->GetParamBlock(plComponentBase::kRefComp); |
|
if (!pBlk) |
|
return false; |
|
|
|
plKey fCamKey = ((plPOAObjectComponent*)objPOAComp)->GetObjectKey(); |
|
if (fCamKey) |
|
{ |
|
pBrain->SetSubject(plSceneObject::ConvertNoRef(fCamKey->GetObjectPtr())); |
|
if (!plCameraBrain1_Avatar::ConvertNoRef(pBrain)) |
|
{ |
|
pBrain->SetFlags(plCameraBrain1::kCutPOA); |
|
pBrain->SetFlags(plCameraBrain1::kCutPos); |
|
} |
|
hsVector3 pt; |
|
pt.fX = pBlk->GetFloat(kPOAObjOffsetX); |
|
pt.fY = pBlk->GetFloat(kPOAObjOffsetY); |
|
pt.fZ = pBlk->GetFloat(kPOAObjOffsetZ); |
|
pBrain->SetPOAOffset(pt); |
|
if (pBlk->GetInt(kPOAObjWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePOA); |
|
bResult = true; |
|
} |
|
else |
|
{ |
|
pErrMsg->Set(true, "Export Error - Cameras", |
|
"Object POA component of camera %s has no object specified!\n", |
|
pNode->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
} |
|
if (bAvPOA) |
|
{ |
|
pBrain->SetFlags(plCameraBrain1::kFollowLocalAvatar); |
|
|
|
IParamBlock2* pBlk = POAComp->GetParamBlock(plComponentBase::kRefComp); |
|
if (!pBlk) |
|
return false; |
|
|
|
hsVector3 pt; |
|
pt.fX = pBlk->GetFloat(kAvPOAOffX); |
|
pt.fY = pBlk->GetFloat(kAvPOAOffY); |
|
pt.fZ = pBlk->GetFloat(kAvPOAOffZ); |
|
if (pBlk->GetInt(kAvPOAWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePOA); |
|
pBrain->SetPOAOffset(pt); |
|
bResult = true; |
|
} |
|
return bResult; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// Camera1Component |
|
// |
|
// the fixed camera component for the new camera code.. |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plCamera1Component, gCamera1Desc, "FixedCamera", "Fixed Camera", COMP_TYPE_CAMERA, FIXEDCAM_CID) |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gCamera1Bk |
|
( |
|
1, _T("camera"), 0, &gCamera1Desc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
end |
|
); |
|
|
|
|
|
plCamera1Component::plCamera1Component() |
|
{ |
|
fClassDesc = &gCamera1Desc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plCamera1Component::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
//this is a fixed camera using the built-in target |
|
plCameraBrain1_Fixed* pBrain = TRACKED_NEW plCameraBrain1_Fixed(pMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
|
|
plGenRefMsg* pMsg = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg); |
|
|
|
pBrain->SetFlags(plCameraBrain1::kCutPOA); |
|
pBrain->SetFlags(plCameraBrain1::kCutPos); |
|
|
|
if (!ISetPOA(pNode, pBrain, pErrMsg)) |
|
pBrain->SetTargetPoint(ICreateFocalPointObject(pNode, pErrMsg)); |
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
fModKeys[pNode] = pMod; |
|
return true; |
|
} |
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// IgnoreSubworldComponent |
|
// |
|
// tells the camera to ignore all subworld matrix movement |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plCameraIgnoreSub, gCameraIgnoreSubDesc, "IgnoreSubworldMovement", "Ignore Subworld Movement", COMP_TYPE_CAMERA, CAM_IGNORE_SUB_CID) |
|
|
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gCameraIgnoreSubBk |
|
( |
|
1, _T("camera"), 0, &gCameraIgnoreSubDesc, P_AUTO_CONSTRUCT, plComponent::kRefComp, |
|
|
|
end |
|
); |
|
|
|
|
|
plCameraIgnoreSub::plCameraIgnoreSub() |
|
{ |
|
fClassDesc = &gCameraIgnoreSubDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// AutoCamComponent |
|
// |
|
// the 3rd person camera component for the new camera code.. |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plAutoCamComponent, gAutoCameraDesc, "AutoCamera", "Auto Camera", COMP_TYPE_CAMERA, AUTOCAM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kAutoCamOffX, |
|
kAutoCamOffY, |
|
kAutoCamOffZ, |
|
kAutoCamWorldspace, |
|
kAutoCamLOS, |
|
kAutoCamSpeed, |
|
kAutoCamAccel, |
|
kAutoPOAOffX, |
|
kAutoPOAOffY, |
|
kAutoPOAOffZ, |
|
kAutoCamCut, |
|
kAutoCamPOAWorldspace, |
|
kAutoCamPosWorldspace, |
|
kAutoCamDecel, |
|
kAutoCamPOAAccel, |
|
kAutoCamPOADecel, |
|
kAutoCamPOASpeed, |
|
kAutoCamCutPOA, |
|
kAutoCamVelocity, |
|
kAutoCamVerticalInFall, |
|
kAutoCamFastRun, |
|
}; |
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gAutoCameraBk |
|
( |
|
1, _T("camera"), 0, &gAutoCameraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_AUTOCAM, IDS_COMP_AUTOCAM, 0, 0, NULL, |
|
|
|
kAutoCamOffX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamOffY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 10.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamOffZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoPOAOffX, _T("PX Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX5, IDC_CAMERACMD_SPIN_OFFSETX5, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoPOAOffY, _T("PY Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY4, IDC_CAMERACMD_SPIN_OFFSETY4, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoPOAOffZ, _T("PZ Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ2, IDC_CAMERACMD_SPIN_OFFSETZ2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamLOS, _T("maintainLOS"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS, |
|
end, |
|
|
|
kAutoCamCut, _T("cutPos"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS2, |
|
end, |
|
|
|
kAutoCamCutPOA, _T("cutPOA"), TYPE_BOOL, 0, 0, |
|
p_default, 1, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS3, |
|
end, |
|
|
|
kAutoCamPosWorldspace, _T("PosWorldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_POS_WORLDSPACE, |
|
end, |
|
|
|
kAutoCamPOAWorldspace, _T("POAworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_POA_WORLDSPACE, |
|
end, |
|
|
|
kAutoCamVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL, IDC_CAMERA_VEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL, IDC_CAMERA_ACCEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamDecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL, IDC_CAMERA_DECEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamPOASpeed, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL2, IDC_CAMERA_VEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamPOAAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL2, IDC_CAMERA_ACCEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamPOADecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL2, IDC_CAMERA_DECEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kAutoCamVerticalInFall, _T("vertical"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_VERTICAL, |
|
end, |
|
|
|
kAutoCamFastRun, _T("runspeedup"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_RUN, |
|
end, |
|
end |
|
); |
|
|
|
plAutoCamComponent::plAutoCamComponent() |
|
{ |
|
fClassDesc = &gAutoCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plAutoCamComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
|
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
plCameraBrain1_Avatar* pBrain = TRACKED_NEW plCameraBrain1_Avatar(pMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
|
|
plGenRefMsg* pMsg = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg); |
|
hsVector3 pt; |
|
pt.Set(fCompPB->GetFloat(kAutoCamOffX),fCompPB->GetFloat(kAutoCamOffY),fCompPB->GetFloat(kAutoCamOffZ)); |
|
pBrain->SetOffset(pt); |
|
pt.Set(fCompPB->GetFloat(kAutoPOAOffX),fCompPB->GetFloat(kAutoPOAOffY),fCompPB->GetFloat(kAutoPOAOffZ)); |
|
pBrain->SetPOAOffset(pt); |
|
if (fCompPB->GetInt(kAutoCamPosWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePos); |
|
|
|
if (fCompPB->GetInt(kAutoCamPOAWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePOA); |
|
|
|
if (fCompPB->GetInt(kAutoCamLOS)) |
|
pBrain->SetFlags(plCameraBrain1::kMaintainLOS); |
|
|
|
if (fCompPB->GetInt(kAutoCamCut)) |
|
pBrain->SetFlags(plCameraBrain1::kCutPos); |
|
|
|
if (fCompPB->GetInt(kAutoCamCutPOA)) |
|
pBrain->SetFlags(plCameraBrain1::kCutPOA); |
|
|
|
if (fCompPB->GetInt(kAutoCamVerticalInFall)) |
|
pBrain->SetFlags(plCameraBrain1::kVerticalWhenFalling); |
|
|
|
if (fCompPB->GetInt(kAutoCamFastRun)) |
|
pBrain->SetFlags(plCameraBrain1::kSpeedUpWhenRunning); |
|
|
|
// We want a local Avatar POA for this brain |
|
pBrain->SetFlags(plCameraBrain1::kFollowLocalAvatar); |
|
|
|
fModKeys[pNode] = pMod; |
|
|
|
// set brain parameters |
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
pBrain->SetAccel(fCompPB->GetFloat(kAutoCamAccel)); |
|
pBrain->SetDecel(fCompPB->GetFloat(kAutoCamDecel)); |
|
pBrain->SetVelocity(fCompPB->GetFloat(kAutoCamVelocity)); |
|
|
|
pBrain->SetPOAAccel(fCompPB->GetFloat(kAutoCamPOAAccel)); |
|
pBrain->SetPOADecel(fCompPB->GetFloat(kAutoCamPOADecel)); |
|
pBrain->SetPOAVelocity(fCompPB->GetFloat(kAutoCamPOASpeed)); |
|
|
|
return true; |
|
} |
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// FPCamComponent |
|
// |
|
// the first-person camera component for the new camera code.. |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plFPCamComponent, gFPCameraDesc, "First Person Camera", "First Person Camera", COMP_TYPE_CAMERA, FPCAM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kFPCamOffX, |
|
kFPCamOffY, |
|
kFPCamOffZ, |
|
kFPCamPOAOffX, |
|
kFPCamPOAOffY, |
|
kFPCamPOAOffZ, |
|
kFpCamPOAWorldspace, |
|
kFpCamPosWorldspace, |
|
}; |
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gFPCameraBk |
|
( |
|
1, _T("camera"), 0, &gFPCameraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_FIRSTPERSON_CAM, IDS_COMP_FIRST_PERSONCAM, 0, 0, NULL, |
|
|
|
kFPCamOffX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFPCamOffY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 1.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFPCamOffZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 6.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFPCamPOAOffX, _T("PX Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX5, IDC_CAMERACMD_SPIN_OFFSETX5, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFPCamPOAOffY, _T("PY Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY4, IDC_CAMERACMD_SPIN_OFFSETY4, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFPCamPOAOffZ, _T("PZ Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 6.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ2, IDC_CAMERACMD_SPIN_OFFSETZ2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFpCamPOAWorldspace, _T("POAworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_POA_WORLDSPACE, |
|
end, |
|
|
|
kFpCamPosWorldspace, _T("Posworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_POS_WORLDSPACE, |
|
end, |
|
end |
|
); |
|
|
|
plFPCamComponent::plFPCamComponent() |
|
{ |
|
fClassDesc = &gFPCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
|
|
hsBool plFPCamComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
|
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
plCameraBrain1_FirstPerson* pBrain = TRACKED_NEW plCameraBrain1_FirstPerson(pMod); |
|
|
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
plGenRefMsg* pMsg2 = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg2->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg2); |
|
|
|
hsVector3 pt; |
|
pt.Set(fCompPB->GetFloat(kFPCamOffX),fCompPB->GetFloat(kFPCamOffY),fCompPB->GetFloat(kFPCamOffZ)); |
|
pBrain->SetOffset(pt); |
|
pt.Set(fCompPB->GetFloat(kFPCamPOAOffX),fCompPB->GetFloat(kFPCamPOAOffY),fCompPB->GetFloat(kFPCamPOAOffZ)); |
|
pBrain->SetPOAOffset(pt); |
|
|
|
// We want a local Avatar POA for this brain |
|
pBrain->SetFlags(plCameraBrain1::kFollowLocalAvatar); |
|
// and we don't want any lag at all. |
|
pBrain->SetFlags(plCameraBrain1::kCutPos); |
|
pBrain->SetFlags(plCameraBrain1::kCutPOA); |
|
fModKeys[pNode] = pMod; |
|
|
|
if (fCompPB->GetInt(kFpCamPOAWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePOA); |
|
|
|
if (fCompPB->GetInt(kFpCamPosWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePos); |
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
return true; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// RailCameraComponent |
|
// |
|
// the fixed camera component for the new camera code.. |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
enum |
|
{ |
|
kRailCamObj, |
|
kRailFarthest, |
|
kRailSpeed, |
|
kRailAccel, |
|
kRailDecel, |
|
kRailPOASpeed, |
|
kRailPOAAccel, |
|
kRailPOADecel, |
|
kRailVelocity, |
|
}; |
|
|
|
|
|
CLASS_DESC(plRailCameraComponent, gRailCameraDesc, "Rail Camera", "Rail Camera", COMP_TYPE_CAMERA, RAIL_CAM_CID) |
|
|
|
|
|
ParamBlockDesc2 gRailCameraBk |
|
( |
|
plComponent::kBlkComp, _T("RailCamera"), 0, &gRailCameraDesc, P_AUTO_CONSTRUCT+P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERA_RAIL, IDS_COMP_RAILCAMERA, 0, 0, 0, |
|
|
|
kRailCamObj, _T("PathObjectChoice"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_LINE_CHOOSE_PATH, |
|
end, |
|
|
|
kRailFarthest, _T("farthest"), TYPE_BOOL, 0, 0, |
|
p_default, FALSE, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK1, |
|
end, |
|
|
|
kRailVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 5.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL, IDC_CAMERA_VEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kRailAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 5.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL, IDC_CAMERA_ACCEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kRailDecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 5.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL, IDC_CAMERA_DECEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kRailPOASpeed, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL2, IDC_CAMERA_VEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kRailPOAAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL2, IDC_CAMERA_ACCEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kRailPOADecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL2, IDC_CAMERA_DECEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
end |
|
|
|
); |
|
|
|
plRailCameraComponent::plRailCameraComponent() |
|
: fValid(false), |
|
fLineMod(nil) |
|
{ |
|
fClassDesc = &gRailCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plRailCameraComponent::IMakeLineMod(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
|
|
plRailCameraMod* lineMod = TRACKED_NEW plRailCameraMod; |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), lineMod, pNode->GetLocation()); |
|
|
|
lineMod->SetFollowMode(plLineFollowMod::kFollowLocalAvatar); |
|
|
|
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kRailCamObj); |
|
if(!pathNode) |
|
{ |
|
pErrMsg->Set(true, "Path Node Failure", "Path Node %s was set to be Ignored or empty. Path Component ignored.", ((INode*)pathNode)->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
//hsAssert(pathNode, "If valid is true, this must be set"); |
|
|
|
Control* maxTm = pathNode->GetTMController(); |
|
|
|
plCompoundController* tmc = plCompoundController::ConvertNoRef(hsControlConverter::Instance().MakeTransformController(maxTm, pathNode)); |
|
|
|
if( !(tmc && tmc->GetPosController() && !plCompoundController::ConvertNoRef(tmc->GetPosController())) ) |
|
{ |
|
delete tmc; |
|
|
|
pErrMsg->Set(true, pNode->GetName(), "Rail Camera Path Node %s has no suitable animation. Rail Camera ignored", pathNode->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
|
|
Matrix3 w2p(true); |
|
Matrix3 l2w = pathNode->GetNodeTM(TimeValue(0)); |
|
if( !pathNode->GetParentNode()->IsRootNode() ) |
|
w2p = Inverse(pathNode->GetParentNode()->GetNodeTM(TimeValue(0))); |
|
hsMatrix44 loc2Par = pathNode->Matrix3ToMatrix44(l2w * w2p); |
|
|
|
gemAffineParts ap; |
|
decomp_affine(loc2Par.fMap, &ap); |
|
hsAffineParts initParts; |
|
AP_SET(initParts, ap); |
|
|
|
plAnimPath* animPath = TRACKED_NEW plAnimPath; |
|
animPath->SetController(tmc); |
|
animPath->InitParts(initParts); |
|
animPath->SetFarthest(fCompPB->GetInt(kRailFarthest)); |
|
|
|
lineMod->SetPath(animPath); |
|
|
|
if( !pathNode->GetParentNode()->IsRootNode() ) |
|
{ |
|
plMaxNode* parNode = (plMaxNode*)pathNode->GetParentNode(); |
|
plSceneObject* parObj = parNode->GetSceneObject(); |
|
if( parObj ) |
|
{ |
|
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(lineMod->GetKey(), plRefMsg::kOnCreate, 0, plLineFollowMod::kRefParent); |
|
hsgResMgr::ResMgr()->AddViaNotify(parObj->GetKey(), refMsg, plRefFlags::kPassiveRef); |
|
} |
|
} |
|
|
|
plLeafController *controller = plLeafController::ConvertNoRef(tmc->GetPosController()); |
|
|
|
hsPoint3 start, end; |
|
controller->Interp(0, &start); |
|
controller->Interp(controller->GetLength(), &end); |
|
|
|
animPath->SetWrap(start == end); |
|
|
|
lineMod->SetForceToLine(true); |
|
|
|
fLineMod = lineMod; |
|
|
|
return true; |
|
} |
|
|
|
hsBool plRailCameraComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
if (!plCameraBaseComponent::SetupProperties(pNode, pErrMsg)) |
|
return false; |
|
|
|
fValid = false; |
|
fLineMod = nil; |
|
|
|
if( !fCompPB->GetINode(kRailCamObj) ) |
|
{ |
|
return true; |
|
} |
|
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kRailCamObj); |
|
if( !pathNode ) |
|
{ |
|
return true; |
|
} |
|
if( !pathNode->IsTMAnimated() ) |
|
{ |
|
return true; |
|
} |
|
pathNode->SetCanConvert(false); |
|
|
|
fValid = true; |
|
pNode->SetForceLocal(true); |
|
pNode->SetMovable(true); |
|
|
|
return true; |
|
} |
|
|
|
hsBool plRailCameraComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
//this is a fixed camera using the built-in target |
|
plCameraBrain1_Fixed* pBrain = TRACKED_NEW plCameraBrain1_Fixed(pMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
|
|
// make the rail cam have pretty slow acceleration |
|
pBrain->SetAccel(5.0f); |
|
pBrain->SetDecel(5.0f); |
|
|
|
plGenRefMsg* pMsg = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg); |
|
|
|
pBrain->SetVelocity(fCompPB->GetFloat(kRailVelocity)); |
|
pBrain->SetAccel(fCompPB->GetFloat(kRailAccel)); |
|
pBrain->SetDecel(fCompPB->GetFloat(kRailDecel)); |
|
|
|
// need to cap these in legacy datasets |
|
if (pBrain->GetAccel() > 10.0f) |
|
pBrain->SetAccel(10.0f); |
|
|
|
if (pBrain->GetDecel() > 10.0f) |
|
pBrain->SetDecel(10.0f); |
|
|
|
if (pBrain->GetVelocity() > 10.0f) |
|
pBrain->SetVelocity(10.0f); |
|
|
|
pBrain->SetPOAVelocity(fCompPB->GetFloat(kRailPOASpeed)); |
|
pBrain->SetPOAAccel(fCompPB->GetFloat(kRailPOAAccel)); |
|
pBrain->SetPOADecel(fCompPB->GetFloat(kRailPOADecel)); |
|
|
|
if (!ISetPOA(pNode, pBrain, pErrMsg)) |
|
pBrain->SetTargetPoint(ICreateFocalPointObject(pNode, pErrMsg)); |
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
fModKeys[pNode] = pMod; |
|
|
|
// rail camera part |
|
plMaxNode* pathNode = (plMaxNode*)fCompPB->GetINode(kRailCamObj); |
|
if( !pathNode ) |
|
{ |
|
pErrMsg->Set(true, "Invald Rail Camera", "Rail Camera component on %s. has no path object selected. This component will not be exported.\n", ((INode*)pNode)->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
|
|
if( !fLineMod ) |
|
{ |
|
if( !IMakeLineMod(pNode, pErrMsg) ) |
|
{ |
|
fValid = false; |
|
return true; |
|
} |
|
} |
|
pNode->AddModifier(fLineMod, IGetUniqueName(pNode)); |
|
pBrain->SetRail(fLineMod); |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// Circle camera Component |
|
// |
|
// a circle camera component for the new camera code.. |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
enum |
|
{ |
|
kCircleFarthest, |
|
kCircleSpeed, |
|
kCirclePOASpeed, |
|
kCirclePOAAccel, |
|
kCirclePOADecel, |
|
kCirclePOAVelocity, |
|
}; |
|
|
|
|
|
CLASS_DESC(plCircleCameraComponent, gCircleCameraDesc, "Circle Camera", "Circle Camera", COMP_TYPE_CAMERA, CIRCLE_CAM_CID) |
|
|
|
|
|
ParamBlockDesc2 gCircleCameraBk |
|
( |
|
plComponent::kBlkComp, _T("CircleCamera"), 0, &gCircleCameraDesc, P_AUTO_CONSTRUCT+P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERA_CIRCLE, IDS_COMP_CIRCLECAMERA, 0, 0, 0, |
|
|
|
kCircleFarthest, _T("farthest"), TYPE_BOOL, 0, 0, |
|
p_default, FALSE, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK1, |
|
end, |
|
|
|
kCircleSpeed, _T("Lag Scale"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.1f, 1.0f, |
|
p_default, 0.1f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX3, IDC_CAMERACMD_SPIN_OFFSETX3, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kCirclePOAVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL, IDC_CAMERA_VEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kCirclePOAAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL, IDC_CAMERA_ACCEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kCirclePOADecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL, IDC_CAMERA_DECEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
|
|
end |
|
|
|
); |
|
|
|
plCircleCameraComponent::plCircleCameraComponent() |
|
: fValid(false) |
|
{ |
|
fClassDesc = &gCircleCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plCircleCameraComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
//this is a circle camera using the built-in target |
|
plCameraBrain1_Circle* pBrain = TRACKED_NEW plCameraBrain1_Circle(pMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
|
|
// make the circle cam have pretty slow acceleration |
|
pBrain->SetAccel(10.0f); |
|
pBrain->SetDecel(10.0f); |
|
pBrain->SetVelocity(15.0f); |
|
// Stay away from / close to the local avatar |
|
pBrain->SetFlags(plCameraBrain1::kFollowLocalAvatar); |
|
|
|
if (fCompPB->GetInt(kCircleFarthest)) |
|
pBrain->SetFarCircleCam(true); |
|
|
|
plGenRefMsg* pMsg = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg); |
|
|
|
pBrain->SetPOAVelocity(fCompPB->GetFloat(kCirclePOAVelocity)); |
|
pBrain->SetPOAAccel(fCompPB->GetFloat(kCirclePOAAccel)); |
|
pBrain->SetPOADecel(fCompPB->GetFloat(kCirclePOADecel)); |
|
|
|
if (fCompPB->GetFloat(kCircleSpeed)) |
|
pBrain->SetCircumferencePerSec(fCompPB->GetFloat(kCircleSpeed)); |
|
|
|
if (!ISetPOA(pNode, pBrain, pErrMsg)) |
|
pBrain->SetTargetPoint(ICreateFocalPointObject(pNode, pErrMsg)); |
|
else |
|
pBrain->SetCircleFlags(plCameraBrain1_Circle::kCircleLocalAvatar); |
|
|
|
// set radius and center point |
|
hsPoint3 point, point2; |
|
TimeValue Now = hsConverterUtils::Instance().GetTime(pNode->GetInterface()); |
|
Matrix3 ReturnMatrix = pNode->GetTarget()->GetNodeTM(Now); |
|
Point3 ReturnVal = ReturnMatrix.GetRow(3); |
|
|
|
point.fX = ReturnVal.x; |
|
point.fY = ReturnVal.y; |
|
point.fZ = ReturnVal.z; |
|
|
|
ReturnMatrix = pNode->GetLocalToWorld(Now); |
|
ReturnVal = ReturnMatrix.GetRow(3); |
|
|
|
point2.fX = ReturnVal.x; |
|
point2.fY = ReturnVal.y; |
|
point2.fZ = ReturnVal.z; |
|
|
|
hsVector3 vec(point - point2); |
|
pBrain->SetRadius(vec.Magnitude()); |
|
pBrain->SetCenter(&point); |
|
|
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
fModKeys[pNode] = pMod; |
|
|
|
return true; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// the detector for triggering camera changes |
|
/////////////////////////////////////////////////////// |
|
|
|
class plCameraDetectorComponent : public plPhysicCoreComponent |
|
{ |
|
public: |
|
|
|
|
|
|
|
plCameraDetectorComponent(); |
|
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(plCameraDetectorComponent, gCameraDetectorDesc, "Camera Region", "CameraRegion", COMP_TYPE_CAMERA, CAM_REGION_CID) |
|
|
|
enum |
|
{ |
|
kCameraTarget, |
|
}; |
|
|
|
ParamBlockDesc2 gCameraRegionBlock |
|
( |
|
plComponent::kBlkComp, _T("cameraRegion"), 0, &gCameraDetectorDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERARGN, IDS_CAMERARGN, 0, 0, NULL, |
|
|
|
|
|
kCameraTarget, _T("CameraTarget"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERARGN_PICKSTATE_BASE, |
|
p_sclassID, CAMERA_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
end, |
|
|
|
|
|
|
|
end |
|
); |
|
|
|
|
|
plCameraDetectorComponent::plCameraDetectorComponent() |
|
{ |
|
fClassDesc = &gCameraDetectorDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
|
|
hsBool plCameraDetectorComponent::SetupProperties(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
pNode->SetForceLocal(true); |
|
pNode->SetDrawable(false); |
|
|
|
plPhysicalProps *physProps = pNode->GetPhysicalProps(); |
|
|
|
physProps->SetPinned(true, pNode, pErrMsg); |
|
// only if movable will it have mass (then it will keep track of movements in PhysX) |
|
if ( pNode->IsMovable() || pNode->IsTMAnimatedRecur() ) |
|
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); |
|
/// physProps->SetAllowLOS(true, pNode, pErrMsg); |
|
|
|
return true; |
|
} |
|
|
|
|
|
hsBool plCameraDetectorComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
hsBool plCameraDetectorComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
plSceneObject *obj = node->GetSceneObject(); |
|
plLocation loc = node->GetLocation(); |
|
|
|
plCameraRegionDetector *detector = TRACKED_NEW plCameraRegionDetector; |
|
|
|
// 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); |
|
|
|
|
|
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg; |
|
pMsg->SetBCastFlag(plMessage::kBCastByType); |
|
|
|
// need to get the key for the camera here... |
|
plMaxNode* pCamNode = (plMaxNode*)fCompPB->GetINode(kCameraTarget); |
|
if (pCamNode) |
|
{ |
|
if(pCamNode->CanConvert()) |
|
{ |
|
pMsg->SetCmd(plCameraMsg::kRegionPushCamera); |
|
pMsg->SetNewCam(((plMaxNode*)pCamNode)->GetSceneObject()->GetKey()); |
|
|
|
int count = ((plMaxNode*)pCamNode)->NumAttachedComponents(); |
|
for (UInt32 x = 0; x < count; x++) |
|
{ |
|
plComponentBase *comp = ((plMaxNode*)pCamNode)->GetAttachedComponent(x); |
|
if (comp->ClassID() == DEFAULTCAM_CID) |
|
{ |
|
pMsg->SetCmd(plCameraMsg::kSetAsPrimary); |
|
break; |
|
} |
|
} |
|
|
|
} |
|
else |
|
{ |
|
pErrMsg->Set(true, "Improper Cam Region Selection", "Cam Choice %s was set to be Ignored. No Camera selected.", ((INode*)pCamNode)->GetName()); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
|
|
} |
|
else |
|
{ |
|
pErrMsg->Set(true, "Camera Region", "Camera Region %s has no camera assigned to it.", ((INode*)node)->GetName()).Show(); |
|
pErrMsg->Set(false); |
|
return false; |
|
} |
|
|
|
|
|
detector->AddMessage(pMsg); |
|
|
|
|
|
return true; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// Object Follow cam Component |
|
// |
|
// the 3rd person camera component for objects other than the avatar |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
//Max desc stuff necessary. |
|
CLASS_DESC(plFollowCamComponent, gFollowCameraDesc, "FollowCamera", "Object Follow Camera", COMP_TYPE_CAMERA, FOLLOWCAM_CID) |
|
|
|
|
|
enum |
|
{ |
|
kFollowCamOffX, |
|
kFollowCamOffY, |
|
kFollowCamOffZ, |
|
kFollowCamWorldspace, |
|
kFollowCamLOS, |
|
kFollowCamSpeed, |
|
kFollowCamAccel, |
|
kFollowPOAOffX, |
|
kFollowPOAOffY, |
|
kFollowPOAOffZ, |
|
kFollowCamCut, |
|
kFollowCamPOAWorldspace, |
|
kFollowCamPosWorldspace, |
|
kFollowCamDecel, |
|
kFollowCamPOAAccel, |
|
kFollowCamPOADecel, |
|
kFollowCamPOASpeed, |
|
kFollowCamCutPOA, |
|
kFollowCamVelocity, |
|
}; |
|
//Max paramblock2 stuff below. |
|
ParamBlockDesc2 gFollowCameraBk |
|
( |
|
1, _T("camera"), 0, &gFollowCameraDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_OBJECT_FOLLOWCAM, IDS_COMP_OBJECT_FOLLOWCAM, 0, 0, NULL, |
|
|
|
kFollowCamOffX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamOffY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 10.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamOffZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowPOAOffX, _T("PX Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX5, IDC_CAMERACMD_SPIN_OFFSETX5, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowPOAOffY, _T("PY Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY4, IDC_CAMERACMD_SPIN_OFFSETY4, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowPOAOffZ, _T("PZ Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -50.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ2, IDC_CAMERACMD_SPIN_OFFSETZ2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamLOS, _T("maintainLOS"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS, |
|
end, |
|
|
|
kFollowCamCut, _T("cutPos"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS2, |
|
end, |
|
|
|
kFollowCamCutPOA, _T("cutPOA"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_LOS3, |
|
end, |
|
|
|
kFollowCamPosWorldspace, _T("PosWorldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_POS_WORLDSPACE, |
|
end, |
|
|
|
kFollowCamPOAWorldspace, _T("POAworldspace"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_AUTOCAM_POA_WORLDSPACE, |
|
end, |
|
|
|
kFollowCamVelocity, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL, IDC_CAMERA_VEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL, IDC_CAMERA_ACCEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamDecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL, IDC_CAMERA_DECEL_SPIN, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamPOASpeed, _T("Velocity"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_VEL2, IDC_CAMERA_VEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamPOAAccel, _T("Accel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_ACCEL2, IDC_CAMERA_ACCEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kFollowCamPOADecel, _T("Decel"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, -100.0f, 100.0f, |
|
p_default, 60.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERA_DECEL2, IDC_CAMERA_DECEL_SPIN2, SPIN_AUTOSCALE, |
|
end, |
|
|
|
end |
|
); |
|
|
|
plFollowCamComponent::plFollowCamComponent() |
|
{ |
|
fClassDesc = &gFollowCameraDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
hsBool plFollowCamComponent::PreConvert(plMaxNode *pNode, plErrorMsg *pErrMsg) |
|
{ |
|
|
|
plCameraModifier1* pMod = ICreateCameraModifier(pNode, pErrMsg); |
|
if (!pMod) |
|
return false; |
|
|
|
plCameraBrain1_Avatar* pBrain = TRACKED_NEW plCameraBrain1_Avatar(pMod); |
|
// Give the brain a key |
|
hsgResMgr::ResMgr()->NewKey(IGetUniqueName(pNode), pBrain, pNode->GetLocation()); |
|
|
|
plGenRefMsg* pMsg = TRACKED_NEW plGenRefMsg(pMod->GetKey(), plRefMsg::kOnCreate, -1, 0); |
|
pMsg->SetRef( (hsKeyedObject*)pBrain ); |
|
plConvert::Instance().AddMessageToQueue(pMsg); |
|
hsVector3 pt; |
|
pt.Set(fCompPB->GetFloat(kFollowCamOffX),fCompPB->GetFloat(kFollowCamOffY),fCompPB->GetFloat(kFollowCamOffZ)); |
|
pBrain->SetOffset(pt); |
|
pt.Set(fCompPB->GetFloat(kFollowPOAOffX),fCompPB->GetFloat(kFollowPOAOffY),fCompPB->GetFloat(kFollowPOAOffZ)); |
|
pBrain->SetPOAOffset(pt); |
|
if (fCompPB->GetInt(kFollowCamPosWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePos); |
|
|
|
if (fCompPB->GetInt(kFollowCamPOAWorldspace)) |
|
pBrain->SetFlags(plCameraBrain1::kWorldspacePOA); |
|
|
|
if (fCompPB->GetInt(kFollowCamLOS)) |
|
pBrain->SetFlags(plCameraBrain1::kMaintainLOS); |
|
|
|
if (fCompPB->GetInt(kFollowCamCut)) |
|
pBrain->SetFlags(plCameraBrain1::kCutPos); |
|
|
|
if (fCompPB->GetInt(kFollowCamCutPOA)) |
|
pBrain->SetFlags(plCameraBrain1::kCutPOA); |
|
|
|
fModKeys[pNode] = pMod; |
|
|
|
if (!ISetPOA(pNode, pBrain, pErrMsg)) |
|
{ |
|
if(pErrMsg->Set(true, "Invalid Object Follow Camera", "The camera %s does NOT have an Object POA to go with its Object Follow Cam Component. This camera will be disabled..\nKill the export?",((INode*)pNode)->GetName()).Ask()) |
|
pErrMsg->Set(true, "", ""); |
|
else |
|
pErrMsg->Set(false); // Don't want to abort |
|
} |
|
|
|
// set brain parameters |
|
|
|
ISetLimitPan(pNode, pBrain); |
|
ISetLimitZoom(pNode, pBrain); |
|
ISetIgnoreSubworld(pNode, pBrain); |
|
|
|
pBrain->SetAccel(fCompPB->GetFloat(kFollowCamAccel)); |
|
pBrain->SetDecel(fCompPB->GetFloat(kFollowCamDecel)); |
|
pBrain->SetVelocity(fCompPB->GetFloat(kFollowCamVelocity)); |
|
|
|
pBrain->SetPOAAccel(fCompPB->GetFloat(kFollowCamPOAAccel)); |
|
pBrain->SetPOADecel(fCompPB->GetFloat(kFollowCamPOADecel)); |
|
pBrain->SetPOAVelocity(fCompPB->GetFloat(kFollowCamPOASpeed)); |
|
|
|
return true; |
|
} |
|
|
|
/////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////// |
|
// |
|
// |
|
// animated camera command component - |
|
// does nothing if you haven't put an animation component on the camera this is on |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
// |
|
|
|
|
|
CLASS_DESC(plCameraAnimCmdComponent, gAnimcamCmdDesc, "Animated Camera Commands", "AnimatedCameraCmd", COMP_TYPE_CAMERA, ANIMCAM_CMD_CID) |
|
|
|
enum |
|
{ |
|
kAnimateOnPush, |
|
kStopOnPop, |
|
kResetOnPop, |
|
kIgnoreFOV |
|
}; |
|
|
|
ParamBlockDesc2 gAnimcamCmdBlock |
|
( |
|
plComponent::kBlkComp, _T("animCamCmd"), 0, &gAnimcamCmdDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_ANIMCAM_COMMANDS, IDS_COMP_ANIM_CAM_CMD, 0, 0, NULL, |
|
|
|
kAnimateOnPush, _T("animOnPush"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_BEGINONPUSH, |
|
end, |
|
|
|
kStopOnPop, _T("stopOnPop"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_STOPONPOP, |
|
end, |
|
|
|
kResetOnPop, _T("resetOnPop"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_RESETONPOP, |
|
end, |
|
|
|
kIgnoreFOV, _T("ignoreFOV"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_IGNOREFOV, |
|
end, |
|
end |
|
); |
|
|
|
|
|
plCameraAnimCmdComponent::plCameraAnimCmdComponent() |
|
{ |
|
fClassDesc = &gAnimcamCmdDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
fIgnoreFOV = false; |
|
} |
|
|
|
plCameraAnimCmdComponent::PreConvert(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
fIgnoreFOV = fCompPB->GetInt(kIgnoreFOV); |
|
return true; |
|
} |
|
plCameraAnimCmdComponent::Convert(plMaxNode* pNode, plErrorMsg* pErrMsg) |
|
{ |
|
plSceneObject* pObj = pNode->GetSceneObject(); |
|
const plCameraModifier1* pCamMod = nil; |
|
if (pObj) |
|
{ |
|
for (int i = 0; i < pObj->GetNumModifiers(); i++) |
|
{ |
|
pCamMod = plCameraModifier1::ConvertNoRef(pObj->GetModifier(i)); |
|
if (pCamMod) |
|
break; |
|
} |
|
if (!pCamMod) |
|
return false; |
|
// forgive me oh const-ness gods. it is only the exporter, after all... |
|
const_cast<plCameraModifier1*>(pCamMod)->SetAnimCommands( fCompPB->GetInt(kAnimateOnPush), fCompPB->GetInt(kStopOnPop), fCompPB->GetInt(kResetOnPop) ); |
|
} |
|
return true; |
|
} |
|
|
|
// obsolete camera components: |
|
#define CAMERACMD_CID Class_ID(0x6edb72d1, 0xd8a1f43) |
|
class plCameraCmdComponent : public plComponent |
|
{ |
|
public: |
|
protected: |
|
|
|
public: |
|
plCameraCmdComponent(); |
|
|
|
// 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 *node, plErrorMsg *pErrMsg); |
|
|
|
hsBool PreConvert(plMaxNode *node, plErrorMsg* pErrMsg); |
|
hsBool Convert(plMaxNode *node, plErrorMsg *pErrMsg); |
|
|
|
}; |
|
OBSOLETE_CLASS_DESC(plCameraCmdComponent, gCameraCmdDesc, "(ex)Camera Command Region", "CameraCmdRegion", COMP_TYPE_MISC, CAMERACMD_CID) |
|
|
|
enum |
|
{ |
|
kCommand, |
|
kOffsetX, |
|
kOffsetY, |
|
kOffsetZ, |
|
kCustomBoundListStuff, |
|
kSmooth, |
|
}; |
|
|
|
class plCameraCmdComponentProc; |
|
extern plCameraCmdComponentProc gCameraCmdComponentProc; |
|
|
|
enum |
|
{ |
|
kCommandSetOffset, |
|
kCommandSetFP, |
|
kCommandSetFixedCam, |
|
}; |
|
|
|
ParamBlockDesc2 gCameraCmdBlock |
|
( |
|
plComponent::kBlkComp, _T("cameraComp"), 0, &gCameraCmdDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp, |
|
|
|
IDD_COMP_CAMERACMD, IDS_COMP_CAMERACMD, 0, 0, &gCameraCmdComponentProc, |
|
|
|
kCommand, _T("Command"), TYPE_INT, 0, 0, |
|
p_default, kCommandSetFixedCam, |
|
end, |
|
|
|
kOffsetX, _T("X Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 50.0f, |
|
p_default, 0.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETX, IDC_CAMERACMD_SPIN_OFFSETX, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kOffsetY, _T("Y Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 50.0f, |
|
p_default, 10.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETY, IDC_CAMERACMD_SPIN_OFFSETY, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kOffsetZ, _T("Z Offset"), TYPE_FLOAT, P_ANIMATABLE, 0, |
|
p_range, 0.0f, 50.0f, |
|
p_default, 3.0f, |
|
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, |
|
IDC_CAMERACMD_OFFSETZ, IDC_CAMERACMD_SPIN_OFFSETZ, SPIN_AUTOSCALE, |
|
end, |
|
|
|
kCustomBoundListStuff, _T("FixedCamera"), TYPE_INODE, 0, 0, |
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERACMD_PICKSTATE_BASE, |
|
p_sclassID, CAMERA_CLASS_ID, |
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, |
|
end, |
|
|
|
kSmooth, _T("useCut"), TYPE_BOOL, 0, 0, |
|
p_ui, TYPE_SINGLECHEKBOX, IDC_COMP_CAMERACMD_CUT, |
|
end, |
|
|
|
|
|
|
|
end |
|
); |
|
|
|
plCameraCmdComponent::plCameraCmdComponent() |
|
{ |
|
fClassDesc = &gCameraCmdDesc; |
|
fClassDesc->MakeAutoParamBlocks(this); |
|
} |
|
|
|
// Internal setup and write-only set properties on the MaxNode. No reading |
|
// of properties on the MaxNode, as it's still indeterminant. |
|
hsBool plCameraCmdComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plCameraCmdComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
hsBool plCameraCmdComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg) |
|
{ |
|
return true; |
|
} |
|
|
|
class plCameraCmdComponentProc : public ParamMap2UserDlgProc |
|
{ |
|
public: |
|
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
return false; |
|
} |
|
|
|
void DeleteThis() {} |
|
|
|
protected: |
|
void IEnableControls(IParamMap2 *map, int type) |
|
{ |
|
} |
|
|
|
void IAddComboItem(HWND hCombo, const char *name, int id) |
|
{ |
|
} |
|
void ISetComboSel(HWND hCombo, int type) |
|
{ |
|
} |
|
}; |
|
static plCameraCmdComponentProc gCameraCmdComponentProc; |
|
|
|
|
|
|
|
|