Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

442 lines
12 KiB
C++

//===========================================================================//
// File: CvTool.cpp
// Project: MechWarrior 4
// Contents: Plugin to add Collision Volumes to mech
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 06/10/99 jkyle Initial coding,
//---------------------------------------------------------------------------//
// Copyright (C) 1999, Fasa Interactive, Inc.
// All Rights reserved worldwide
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL
//===========================================================================//
#include "stdafx.h"
#ifdef STRICT // Already defined by stdafx,
#undef STRICT // so we avoid warning linking msg
#endif
#ifdef _MBCS // The same as above
#undef _MBCS
#endif
#include "CvTool.hpp"
#include "cvobject.h"
#include "mw4.hpp"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
//////////////////////////////////////////////////////////////////////
// Global Variables
CvToolPanel g_cvToolPanel;
//////////////////////////////////////////////////////////////////////
// ProtoTypes
////////////////////////////////////////////////////////////////////////////////
// CvToolPanel Dialog Procedure to handle User and System Interactions
static BOOL CALLBACK CvToolPanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
switch (msg)
{
case WM_INITDIALOG: //Panel's extra initialization
g_cvToolPanel.Init(hWnd);
break;
case WM_DESTROY: //Panel's extra destruction
g_cvToolPanel.Destroy(hWnd);
break;
case WM_COMMAND :
{ //Handle Panel's controls
HWND hwndCtrl = (HWND)lParam;
switch (LOWORD(wParam))
{
case IDC_EXECUTE:
{
//g_cvToolPanel.CvToolExecute();
theHold.SuperBegin();
g_cvToolPanel.BuildCollisionVolume(g_cvToolPanel.m_ip->GetRootNode());
theHold.SuperAccept("CollisionTool");
g_cvToolPanel.m_ip->RedrawViews(g_cvToolPanel.m_ip->GetTime(),REDRAW_BEGIN);
g_cvToolPanel.m_ip->RedrawViews(g_cvToolPanel.m_ip->GetTime(),REDRAW_NORMAL);
g_cvToolPanel.m_ip->RedrawViews(g_cvToolPanel.m_ip->GetTime(),REDRAW_END);
}
}
break;
}
////////////////////////////////////////////////////////////////////////
//The following lines are not necessary for MAX2 Plugins
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
g_cvToolPanel.m_ip->RollupMouseMessage(hWnd, msg, wParam, lParam);
break;
////////////////////////////////////////////////////////////////////////
default:
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// Display the Plugin's Panel
void CvToolPanel::BeginEditParams(Interface* ip, IUtil* iu)
{
m_ip = ip; //Get the Plugin's Interface
m_iu = iu; //Get the Utility Plugin's Interface
//Display the plugin's Rollup Dialog
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HINSTANCE loc_hInstance = AfxGetResourceHandle ();
m_hPanel = ip->AddRollupPage(loc_hInstance, MAKEINTRESOURCE(IDD_CVTOOL_PANEL),
CvToolPanelProc, GetString(IDS_CVOBJECT_NAME),0);
}
////////////////////////////////////////////////////////////////////////////////
// Free the Plugins' Panel
void CvToolPanel::EndEditParams(Interface *ip, IUtil *iu)
{
m_iu = NULL;
m_ip = NULL;
//Remove the Rollup Dialog
ip->DeleteRollupPage(m_hPanel);
m_hPanel = NULL;
}
////////////////////////////////////////////////////////////////////////////////
// Panel Initialization callback
void CvToolPanel::Init(HWND hWnd)
{
}
////////////////////////////////////////////////////////////////////////////////
// Panel Destruction callback
void CvToolPanel::Destroy(HWND hWnd)
{
}
#if 0
void CvToolPanel::CvToolExecute()
{
INode *pRoot = ip->GetINodeByName("joint_WORLD");
if (pRoot)
{
// We are creating a mech Collision Volume
//AddCvNode(pRoot,true);
AddCv(pRoot);
}
else
{
// We are creating a building Collision Volume
pRoot = ip->GetRootNode();
AddCv(pRoot,false);
}
// Redraw the views
ip->RedrawViews(ip->GetTime());
}
void CvToolPanel::AddCv(INode *pNode,BOOL bCheckName)
{
BOOL bValid = false;
BOOL bIsJoint = false;
if (bCheckName)
{
CString strName = pNode->GetName();
if (0==strnicmp(strName,"joint_",6))
{
bIsJoint = true;
}
BOOL bHasGeometry = false;
for (int x=0;(x<pNode->NumberOfChildren())&&(!bHasGeometry);x++)
{
CString strChildName = pNode->GetChildNode(x)->GetName();
if (0!=strnicmp(strChildName,"joint_",6))
//if (0!=strnicmp(strChildName,"handle_",7))
bHasGeometry = true;
}
if (bIsJoint && bHasGeometry)
bValid = true;
}
else
{
CString strName = pNode->GetName();
if (0!=strnicmp(strName,"cv_",3))
{
bValid = bIsJoint = true;
}
}
if (bIsJoint)
AddCvNode(pNode,bValid);
for (int x=0;x<pNode->NumberOfChildren();x++)
{
AddCv(pNode->GetChildNode(x),bCheckName);
}
}
void CvToolPanel::AddCvNode(INode *pNode,BOOL bValid)
{
if (!bValid)
return;
/* *******************************
Code from the Max SDK solution #1981
**********************************/
// Create a new object through the CreateInstance() API
Object *obj = (Object*)ip->CreateInstance(
HELPER_CLASS_ID,
CVOBJECT_CLASS_ID);
assert(obj);
// Get a hold of the parameter block
IParamArray *iParams = obj->GetParamBlock();
assert(iParams);
// Set the parameters
// Set to a default material
iParams->SetValue(CV_MATERIAL,TimeValue(0),bValid?MechWarrior4::SteelMaterial:MechWarrior4::MaterialCount);
// Set the initial size to the size of the node's bounding box
Box3 box;
if (bValid)
{
Object *pObj = pNode->GetObjectRef();
if (pObj)
{
pObj->GetLocalBoundBox(TimeValue(0),pNode,ip->GetActiveViewport(),box);
box = Box3(Point3(0.0,0.0,0.0),box.Width());
for (int x=0;x<pNode->NumberOfChildren();x++)
{
Box3 newbox;
INode *pChild = pNode->GetChildNode(x);
if (0!=strnicmp(pChild->GetName(),"site_",5))
{
pChild->GetObjectRef()->GetLocalBoundBox(TimeValue(0),pChild,ip->GetActiveViewport(),newbox);
box += Box3(Point3(0.0,0.0,0.0),newbox.Width());
}
}
if (box.IsEmpty())
box = Box3(Point3(1,1,1),Point3(1,1,1));
}
}
else
box = Box3(Point3(0,0,0),Point3(0,0,0));
// Swap the y and z for some reason
Point3 pt = box.Width();
iParams->SetValue(CV_SIZE,TimeValue(0),Point3(pt.x,pt.z,pt.y));
// Create a node in the scene that references the object
INode *node = ip->CreateObjectNode(obj);
// Name the node and make the name unique.
CString strName = pNode->GetName();
if (strnicmp(strName,"joint_",6)==0)
{
strName = strName.Right(strName.GetLength()-6);
}
CString rcName;
rcName.LoadString(IDS_DB_CVOBJECT);
strName = rcName+strName;
TSTR name(_T(strName));
ip->MakeNameUnique(name);
node->SetName(name);
// Add node to the heiarchy and move it to the parent's position
pNode->AttachChild(node,0);
// Eval the node's object (exclude WSMs)
Object *oldObj = node->GetObjectRef();
ObjectState os = oldObj->Eval(ip->GetTime());
// Set the result to be the node's new object (make a clone)
Object *newobj = (Object*)os.obj->Clone();
newobj->SetSubSelState(0);
// Reset the selection level to object level
oldObj->SetAFlag(A_LOCK_TARGET);
node->SetObjectRef(newobj);
node->NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
oldObj->ClearAFlag(A_LOCK_TARGET);
oldObj->MaybeAutoDelete();
}
#endif
void CvToolPanel::BuildCollisionVolume(INode *inode)
{
if (inode == NULL)
return;
CString nodename = inode->GetName();
nodename.MakeLower();
if (nodename.Find("cv_")>=0 || nodename.Find("light")>=0)
return;
// depth first so I don't see my new child of the collision box
for (int c = 0; c < inode->NumberOfChildren(); c++)
{
BuildCollisionVolume(inode->GetChildNode(c));
}
// add a collision volume for myself
// if I am a joint and have a child with geometry...
SClass_ID SCID;
Class_ID CID;
ObjectState os;
os = inode->EvalWorldState(0);
if (os.obj)
{
SCID = os.obj->SuperClassID();
CID = os.obj->ClassID();
if (SCID == GEOMOBJECT_CLASS_ID)
{
theHold.Begin();
Object *obj = (Object*)m_ip->CreateInstance(HELPER_CLASS_ID, CVOBJECT_CLASS_ID);
Check_Pointer(obj);
// Get a hold of the parameter block
IParamArray *iParams = obj->GetParamBlock();
Check_Pointer(iParams);
// Set the parameters
// Set to a default material
iParams->SetValue(CV_MATERIAL,TimeValue(0),Adept::SteelMaterial);
// Create the cv node
INode *new_node = m_ip->CreateObjectNode(obj);
// Figure out the cv name
{
CString nodename = inode->GetName();
int index = nodename.Find("_",0);
if (index >=0)
nodename.Delete(0,index+1);
CString name = "cv_";
name += nodename;
new_node->SetName(name.GetBuffer(50));
}
TriObject *meshData;
Verify(os.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)));
meshData = (TriObject *) os.obj->ConvertToType(0,Class_ID(TRIOBJ_CLASS_ID, 0));
meshData->mesh.buildBoundingBox();
Box3 box;
box = meshData->mesh.getBoundingBox();
Point3 pt = box.Width();
iParams->SetValue(CV_SIZE,TimeValue(0),pt);
// figure out the correct offset
Point3 offset;
offset.x = box.pmin.x - (pt.x*-0.5f);
offset.y = box.pmin.y - (pt.y*-0.5f);
offset.z = box.pmin.z - (pt.z*-0.5f);
Point3 offset_trans = inode->GetObjOffsetPos();
Quat offset_rot = inode->GetObjOffsetRot();
//SPEW(("jerryeds", "obj-'%s'", inode->GetName()));
//SPEW(("jerryeds", "qpvt - %f %f %f %f", offset_rot.x, offset_rot.y, offset_rot.z, offset_rot.w));
//SPEW(("jerryeds", "pvt - %f %f %f", offset_trans.x, offset_trans.y, offset_trans.z));
//SPEW(("jerryeds", "pmin - %f %f %f", box.pmin.x, box.pmin.y, box.pmin.z));
//SPEW(("jerryeds", "pmax - %f %f %f", box.pmax.x, box.pmax.y, box.pmax.z));
//SPEW(("jerryeds", "pt - %f %f %f", pt.x, pt.y, pt.z));
//SPEW(("jerryeds", "ofst - %f %f %f", offset.x, offset.y, offset.z));
offset.x += offset_trans.x;
offset.y += offset_trans.y;
offset.z += offset_trans.z;
// Set transformation for the cv node
Matrix3 node_tm;
node_tm.IdentityMatrix();
offset_rot.MakeMatrix(node_tm);
node_tm.SetTrans(offset);
new_node->SetNodeTM(0,node_tm);
//find nearest joint_ parent node..
INode *closest_parent = FindParentJoint(inode);
if (closest_parent) {
Check_Pointer(closest_parent);
closest_parent->AttachChild(new_node,0);
//SPEW(("jerryeds", "par-'%s'", closest_parent->GetName()));
}
theHold.Accept(0);
}
}
}
INode *CvToolPanel::FindParentJoint(INode *inode)
{
if (inode == NULL)
return NULL;
if (!strnicmp("joint_", inode->GetName(), 6))
{
//SPEW(("jerryeds", "FOUND - '%s'", inode->GetName()));
return inode;
}
else
{
//SPEW(("jerryeds", "DEEPER - '%s'", inode->GetName()));
return FindParentJoint(inode->GetParentNode());
}
//SPEW(("jerryeds", "END OF CHAIN - '%s'", inode->GetName()));
return NULL;
}