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

1523 lines
36 KiB
C++

// JointEditDialog.cpp : implementation file
//
#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 "JointEditDialog.h"
//#ifdef _DEBUG
//#define new DEBUG_NEW
//#undef THIS_FILE
//static char THIS_FILE[] = __FILE__;
//#endif
/////////////////////////////////////////////////////////////////////////////
// JointEditDialog dialog
JointEditDialog::JointEditDialog(INode *root_node, Interface *ip, CWnd* pParent /*=NULL*/)
: CDialog(JointEditDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(JointEditDialog)
m_rotOptCheck = FALSE;
m_tranOptCheck = FALSE;
m_rotRangeCheck = FALSE;
m_tranRangeCheck = FALSE;
m_encodeVelocityCheck = FALSE;
m_rotThresholdEdit = 0.0f;
m_tranThresholdEdit = 0.0f;
m_rotMaxRange = 0;
m_rotMinRange = 0;
m_tranMaxRange = 0;
m_tranMinRange = 0;
m_rotConvertCheck = FALSE;
m_tranConvertCheck = FALSE;
//}}AFX_DATA_INIT
m_max_interface = ip;
m_rootNode = root_node;
m_forceExclude = false;
m_forceConvertRotation = false;
m_forceConvertTranslation = false;
}
void JointEditDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
if (m_firstDataSave)
{
//{{AFX_DATA_MAP(JointEditDialog)
DDX_Control(pDX, IDC_COMBO_TRAN_CONVERT, m_tranConvertCombo);
DDX_Control(pDX, IDC_COMBO_ROT_CONVERT, m_rotConvertCombo);
DDX_Control(pDX, IDC_COMBO_INCLUDE, m_includeCombo);
DDX_Check(pDX, IDC_CHECK_ROT_OPT, m_rotOptCheck);
DDX_Check(pDX, IDC_CHECK_TRAN_OPT, m_tranOptCheck);
DDX_Check(pDX, IDC_CHECK_ROT_RANGE, m_rotRangeCheck);
DDX_Check(pDX, IDC_CHECK_TRAN_RANGE, m_tranRangeCheck);
DDX_Check(pDX, IDC_CHECK_ENCODE_VELOCITY, m_encodeVelocityCheck);
DDX_Text(pDX, IDC_EDIT_ROT_THRESH, m_rotThresholdEdit);
DDX_Text(pDX, IDC_EDIT_TRAN_THRESH, m_tranThresholdEdit);
DDX_Text(pDX, IDC_ROT_MAX_RANGE, m_rotMaxRange);
DDX_Text(pDX, IDC_ROT_MIN_RANGE, m_rotMinRange);
DDX_Text(pDX, IDC_TRAN_MAX_RANGE, m_tranMaxRange);
DDX_Text(pDX, IDC_TRAN_MIN_RANGE, m_tranMinRange);
DDX_Check(pDX, IDC_CONVERT_ROT_CHECK, m_rotConvertCheck);
DDX_Check(pDX, IDC_CONVERT_TRAN_CHECK, m_tranConvertCheck);
//}}AFX_DATA_MAP
m_firstDataSave = false;
}
GetDlgItem(IDC_COMBO_INCLUDE)->EnableWindow(true);
GetDlgItem(IDC_CONVERT_ROT_CHECK)->EnableWindow(true);
GetDlgItem(IDC_CONVERT_TRAN_CHECK)->EnableWindow(true);
{
DDX_Control(pDX, IDC_COMBO_INCLUDE, m_includeCombo);
if (m_forceExclude)
{
GetDlgItem(IDC_COMBO_INCLUDE)->EnableWindow(false);
}
else
{
GetDlgItem(IDC_COMBO_INCLUDE)->EnableWindow(true);
}
DDX_Check(pDX, IDC_CHECK_ENCODE_VELOCITY, m_encodeVelocityCheck);
//-----------------------------------------------------------
// Do the rotation
DDX_Check(pDX, IDC_CONVERT_ROT_CHECK, m_rotConvertCheck);
if (m_rotConvertCheck)
{
DDX_Control(pDX, IDC_COMBO_ROT_CONVERT, m_rotConvertCombo);
GetDlgItem(IDC_COMBO_ROT_CONVERT)->EnableWindow(true);
if (m_forceConvertRotation)
{
GetDlgItem(IDC_CONVERT_ROT_CHECK)->EnableWindow(false);
}
else
{
GetDlgItem(IDC_CONVERT_ROT_CHECK)->EnableWindow(true);
}
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_COMBO_ROT_CONVERT)->EnableWindow(false);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_ROT_CONVERT);
box->SetCurSel( -1 );
}
}
DDX_Check(pDX, IDC_CHECK_ROT_OPT, m_rotOptCheck);
if (m_rotOptCheck)
{
DDX_Text(pDX, IDC_EDIT_ROT_THRESH, m_rotThresholdEdit);
DDX_Check(pDX, IDC_CHECK_ROT_RANGE, m_rotRangeCheck);
GetDlgItem(IDC_EDIT_ROT_THRESH)->EnableWindow(true);
GetDlgItem(IDC_CHECK_ROT_RANGE)->EnableWindow(true);
if (m_rotRangeCheck)
{
DDX_Text(pDX, IDC_ROT_MAX_RANGE, m_rotMaxRange);
DDX_Text(pDX, IDC_ROT_MIN_RANGE, m_rotMinRange);
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(true);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(true);
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText("");
}
}
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_EDIT_ROT_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_ROT_RANGE)->EnableWindow(false);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_ROT_THRESH);
edit->SetWindowText("");
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(false);
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText("");
}
}
//-----------------------------------------------------------
// Do the translation
DDX_Check(pDX, IDC_CONVERT_TRAN_CHECK, m_tranConvertCheck);
if (m_tranConvertCheck)
{
DDX_Control(pDX, IDC_COMBO_TRAN_CONVERT, m_tranConvertCombo);
GetDlgItem(IDC_COMBO_TRAN_CONVERT)->EnableWindow(true);
if (m_forceConvertTranslation)
{
GetDlgItem(IDC_CONVERT_TRAN_CHECK)->EnableWindow(false);
}
else
{
GetDlgItem(IDC_CONVERT_TRAN_CHECK)->EnableWindow(true);
}
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_COMBO_TRAN_CONVERT)->EnableWindow(false);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_TRAN_CONVERT);
box->SetCurSel( -1 );
}
}
DDX_Check(pDX, IDC_CHECK_TRAN_OPT, m_tranOptCheck);
if (m_tranOptCheck)
{
DDX_Text(pDX, IDC_EDIT_TRAN_THRESH, m_tranThresholdEdit);
DDX_Check(pDX, IDC_CHECK_TRAN_RANGE, m_tranRangeCheck);
GetDlgItem(IDC_EDIT_TRAN_THRESH)->EnableWindow(true);
GetDlgItem(IDC_CHECK_TRAN_RANGE)->EnableWindow(true);
if (m_tranRangeCheck)
{
DDX_Text(pDX, IDC_TRAN_MAX_RANGE, m_tranMaxRange);
DDX_Text(pDX, IDC_TRAN_MIN_RANGE, m_tranMinRange);
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(true);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(true);
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText("");
}
}
}
else
{
// if we are loading then disable the controls
if (!pDX->m_bSaveAndValidate)
{
GetDlgItem(IDC_EDIT_TRAN_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_TRAN_RANGE)->EnableWindow(false);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_TRAN_THRESH);
edit->SetWindowText("");
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(false);
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText("");
}
}
}
}
BEGIN_MESSAGE_MAP(JointEditDialog, CDialog)
//{{AFX_MSG_MAP(JointEditDialog)
ON_BN_CLICKED(ID_REVERT_JOINT, OnRevertJoint)
ON_NOTIFY(TVN_SELCHANGED, IDC_NODE_TREE, OnSelchangedNodeTree)
ON_BN_CLICKED(IDC_CHECK_ROT_OPT, OnCheckRotOpt)
ON_BN_CLICKED(IDC_CONVERT_ROT_CHECK, OnConvertRotCheck)
ON_BN_CLICKED(IDC_CHECK_ROT_RANGE, OnCheckRotRange)
ON_BN_CLICKED(IDC_CONVERT_TRAN_CHECK, OnConvertTranCheck)
ON_BN_CLICKED(IDC_CHECK_TRAN_OPT, OnCheckTranOpt)
ON_BN_CLICKED(IDC_CHECK_TRAN_RANGE, OnCheckTranRange)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// JointEditDialog message handlers
BOOL JointEditDialog::OnInitDialog()
{
// prime the pump...
AddJointPreference(m_rootNode);
m_firstDataSave = true;
CDialog::OnInitDialog();
// set up the combos...
m_tranConvertCombo.InsertString(-1, "Linear");
m_tranConvertCombo.InsertString(-1, "EulerXYZ");
m_tranConvertCombo.InsertString(-1, "PositionXYZ");
m_rotConvertCombo.InsertString(-1, "Linear");
m_rotConvertCombo.InsertString(-1, "EulerXYZ");
m_rotConvertCombo.InsertString(-1, "PositionXYZ");
m_includeCombo.InsertString(-1, "Exclude");
m_includeCombo.InsertString(-1, "Include");
m_includeCombo.InsertString(-1, "Auto");
// init the tree...
CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(IDC_NODE_TREE);
HTREEITEM top_item = AddToTree(tree, m_rootNode, TVI_ROOT);
tree->EnsureVisible(top_item);
tree->SelectItem(top_item);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////////////////////
HTREEITEM JointEditDialog::AddToTree(CTreeCtrl *tree, INode *node, HTREEITEM parent)
{
HTREEITEM new_entry = tree->InsertItem( node->GetName(), parent, TVI_LAST );
tree->SetItemData(new_entry, (DWORD)node);
for (int c = 0; c < node->NumberOfChildren(); c++)
{
AddToTree(tree, node->GetChildNode(c), new_entry);
}
tree->Expand(new_entry, TVE_EXPAND );
return new_entry;
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::OnOK()
{
// save the current node...
CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(IDC_NODE_TREE);
INode *node = (INode*)tree->GetItemData(tree->GetSelectedItem());
if (!node->IsRootNode())
{
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
JointPreference *j_pref = (JointPreference *)ad->data;
SaveControls(j_pref);
}
AcceptTempData(m_max_interface->GetRootNode());
CDialog::OnOK();
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::OnCancel()
{
CancelTempData(m_max_interface->GetRootNode());
CDialog::OnCancel();
}
/////////////////////////////////////////////////////////////////////////////
JointPreference * JointEditDialog::GetJointPrefrence(INode* node)
{
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID
);
if (ad != NULL)
{
return (JointPreference *)ad->data;
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::CopyJointPrefrence(INode* source_node, INode* target_node)
{
AppDataChunk *ad =
source_node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID
);
if (ad != NULL)
{
size_t size = ad->length;
BYTE *data = new BYTE[size];
Mem_Copy(data, ad->data, ad->length, size);
target_node->AddAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID,
size, data);
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::AcceptTempData(INode *node)
{
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
if (ad)
{
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID);
size_t size = ad->length;
BYTE *data = new BYTE[size];
Mem_Copy(data, ad->data, ad->length, size);
node->AddAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID,
size, data);
// now kill the temp data
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID);
SetSaveRequiredFlag(TRUE);
}
for (int c = 0; c < node->NumberOfChildren(); c++)
{
AcceptTempData(node->GetChildNode(c));
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::CancelTempData(INode *node)
{
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID);
for (int c = 0; c < node->NumberOfChildren(); c++)
{
CancelTempData(node->GetChildNode(c));
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::DeleteAllJointPrefrence(INode* node)
{
if (!node->IsRootNode())
{
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID);
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID);
}
for (int c = 0; c < node->NumberOfChildren(); c++)
{
DeleteAllJointPrefrence(node->GetChildNode(c));
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::OnRevertJoint()
{
// reinitialize this joints temporary data with it's perminate data.
// remove temp data
// copy perm data into temp data
CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(IDC_NODE_TREE);
INode *node = (INode*)tree->GetItemData(tree->GetSelectedItem());
AppDataChunk *ad_perm =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID
);
Verify(ad_perm != NULL);
size_t size = ad_perm->length;
BYTE *data = new BYTE[size];
Mem_Copy(data, ad_perm->data, ad_perm->length, size);
// remove it if it exists...
node->RemoveAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID);
node->AddAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID,
size, data);
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
Verify(ad != NULL);
// we just added it!
ClearControls();
JointPreference *j_pref = (JointPreference *)ad->data;
InitControls(j_pref);
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::OnSelchangedNodeTree(NMHDR* pNMHDR, LRESULT* pResult)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(IDC_NODE_TREE);
// Save old node data...
if (pNMTreeView->itemOld.hItem != NULL)
{
// copy the interface into the tempdata
// get pointer to data
INode *node = (INode*)tree->GetItemData(pNMTreeView->itemOld.hItem);
if (!node->IsRootNode())
{
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
JointPreference *j_pref = (JointPreference *)ad->data;
SaveControls(j_pref);
}
}
// Load this data segment
INode *node = (INode*)tree->GetItemData(pNMTreeView->itemNew.hItem);
if (node->IsRootNode())
{
ClearControls();
return;
}
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
if (!ad)
{
// Not found!
// copy from the other perm data segment...
AppDataChunk *ad_perm =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID
);
Verify(ad_perm != NULL);
size_t size = ad_perm->length;
BYTE *data = new BYTE[size];
Mem_Copy(data, ad_perm->data, ad_perm->length, size);
node->AddAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID,
size, data);
ad = node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
TEMP_DATA_ID
);
}
// copy ad into the interface
ClearControls();
JointPreference *j_pref = (JointPreference *)ad->data;
InitControls(j_pref);
*pResult = 0;
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::ClearControls()
{
// Clear the combos
m_tranConvertCombo.SetCurSel( -1 );
m_rotConvertCombo.SetCurSel( -1 );
m_includeCombo.SetCurSel( -1 );
m_rotOptCheck = false;
m_tranOptCheck = false;
m_rotRangeCheck = false;
m_tranRangeCheck = false;
m_rotConvertCheck = false;
m_tranConvertCheck = false;
m_encodeVelocityCheck = false;
m_rotThresholdEdit = 0.0f;
m_tranThresholdEdit = 0.0f;
m_rotMaxRange = 0;
m_rotMinRange = 0;
m_tranMaxRange = 0;
m_tranMinRange = 0;
UpdateData(false);
// clear out the edits
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_EDIT_ROT_THRESH);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_EDIT_TRAN_THRESH);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText("");
GetDlgItem(IDC_COMBO_TRAN_CONVERT)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(false);
GetDlgItem(IDC_EDIT_TRAN_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_TRAN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_COMBO_ROT_CONVERT)->EnableWindow(false);
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(false);
GetDlgItem(IDC_EDIT_ROT_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_ROT_RANGE)->EnableWindow(false);
CButton *button;
button = (CButton *)GetDlgItem(IDC_CHECK_TRAN_RANGE);
button->SetCheck(0);
button = (CButton *)GetDlgItem(IDC_CHECK_ROT_RANGE);
button->SetCheck(0);
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::SaveControls(JointPreference *j_pref)
{
UpdateData(true);
j_pref->m_forceExclude = m_forceExclude;
j_pref->m_forceConvertRotation = m_forceConvertRotation;
j_pref->m_forceConvertTranslation = m_forceConvertTranslation;
j_pref->m_excludeJoint = m_includeCombo.GetCurSel();
j_pref->m_decodeWithVelocity = (m_encodeVelocityCheck)?true:false;
Verify(j_pref->m_decodeWithVelocity == true || j_pref->m_decodeWithVelocity == false);
//SPEW((0, "SAVE : %d : %d", j_pref->m_decodeWithVelocity, encodeVelocityCheck ));
j_pref->m_convertRotationJoint = (m_rotConvertCheck)?true:false;;
if (m_rotConvertCheck)
{
j_pref->m_rotationConvertType = m_rotConvertCombo.GetCurSel();
}
j_pref->m_convertTranslationJoint = (m_tranConvertCheck)?true:false;;
if (m_tranConvertCheck)
{
j_pref->m_translationConvertType = m_tranConvertCombo.GetCurSel();
}
j_pref->m_optimizeRotation = (m_rotOptCheck)?true:false;;
if (m_rotOptCheck)
{
j_pref->m_rotationThreshold = m_rotThresholdEdit;
j_pref->m_rotationRange = (m_rotRangeCheck)?true:false;;
if (m_rotRangeCheck)
{
j_pref->m_rotationSampleStartFrame = m_rotMinRange;
j_pref->m_rotationSampleEndFrame = m_rotMaxRange;
}
}
j_pref->m_optimizeTranslation = (m_tranOptCheck)?true:false;;
if (m_tranOptCheck)
{
j_pref->m_translationThreshold = m_tranThresholdEdit;
j_pref->m_translationRange = (m_tranRangeCheck)?true:false;;
if (m_tranRangeCheck)
{
j_pref->m_translationSampleStartFrame = m_tranMinRange;
j_pref->m_translationSampleEndFrame = m_tranMaxRange;
}
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::InitControls(JointPreference *j_pref)
{
m_forceExclude = j_pref->m_forceExclude;
m_forceConvertRotation = j_pref->m_forceConvertRotation;
m_forceConvertTranslation = j_pref->m_forceConvertTranslation;
m_includeCombo.SetCurSel(j_pref->m_excludeJoint);
m_encodeVelocityCheck = j_pref->m_decodeWithVelocity;
Verify(j_pref->m_decodeWithVelocity == true || j_pref->m_decodeWithVelocity == false);
//SPEW((0, "INIT : %d : %d", j_pref->m_decodeWithVelocity, encodeVelocityCheck ));
m_rotConvertCheck = j_pref->m_convertRotationJoint;
if (m_rotConvertCheck)
{
m_rotConvertCombo.SetCurSel(j_pref->m_rotationConvertType);
}
m_tranConvertCheck = j_pref->m_convertTranslationJoint;
if (m_tranConvertCheck)
{
m_tranConvertCombo.SetCurSel(j_pref->m_translationConvertType);
}
m_rotOptCheck = j_pref->m_optimizeRotation;
if (m_rotOptCheck)
{
m_rotThresholdEdit = j_pref->m_rotationThreshold;
m_rotRangeCheck = j_pref->m_rotationRange;
if (m_rotRangeCheck)
{
m_rotMinRange = j_pref->m_rotationSampleStartFrame;
m_rotMaxRange = j_pref->m_rotationSampleEndFrame;
}
}
m_tranOptCheck = j_pref->m_optimizeTranslation;
if (m_tranOptCheck)
{
m_tranThresholdEdit = j_pref->m_translationThreshold;
m_tranRangeCheck = j_pref->m_translationRange;
if (m_tranRangeCheck)
{
m_tranMinRange = j_pref->m_translationSampleStartFrame;
m_tranMaxRange = j_pref->m_translationSampleEndFrame;
}
}
UpdateData(false);
}
/////////////////////////////////////////////////////////////////////////////
#define APPDATA_TEST_CLASS_ID 0xf6277abd
void JointEditDialog::AddJointPreference(INode* node)
{
AppDataChunk *ad =
node->GetAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID
);
if (!ad)
{
// Not found!
// Create and load...
if (!node->IsRootNode())
{
JointPreference *joint_preference = (JointPreference *)malloc(sizeof(JointPreference));
LoadPrefs(node, joint_preference);
node->AddAppDataChunk(
JOINTPREFS_SAVE_CLASS_ID,
JOINT_SAVE_SUPER_CLASS_ID,
PERM_DATA_ID,
(DWORD)sizeof(JointPreference), (void *)joint_preference);
}
}
// For each child of this node, we recurse into ourselves
// and increment the counter until no more children are found.
for (int c = 0; c < node->NumberOfChildren(); c++)
{
AddJointPreference(node->GetChildNode(c));
}
}
/////////////////////////////////////////////////////////////////////////////
void JointEditDialog::CountNodes(INode* node, int& node_count)
{
node_count++;
// For each child of this node, we recurse into ourselves
// and increment the counter until no more children are found.
for (int c = 0; c < node->NumberOfChildren(); c++)
{
CountNodes(node->GetChildNode(c), node_count);
}
}
//===========================================================================//
void JointEditDialog::LoadPrefs(INode* node, JointPreference *prefs)
{
// Right now we are just going to fake it...
// these routines will be used by the prefrence plugin
// only allow for geom, helpers, bones, etc...NO CAMERAS, LIGHTS, etc...
if (!KnownNode(node))
{
prefs->m_forceExclude = true;
prefs->m_excludeJoint = JointPreference::ExcludeJoint;
prefs->m_decodeWithVelocity = false;
}
else if (!NodeAnimated(node))
{
prefs->m_forceExclude = false;
prefs->m_excludeJoint = JointPreference::AutoJoint;
prefs->m_decodeWithVelocity = false;
}
else
{
prefs->m_forceExclude = false;
prefs->m_excludeJoint = JointPreference::AutoJoint;
const char *node_name = node->GetName();
if (!_strnicmp(node_name, "joint_vel", 9))
{
prefs->m_decodeWithVelocity = true;
}
else
{
prefs->m_decodeWithVelocity = false;
}
// if one is diffrent
// then we can't be sure that it doesn't mess
// with the other so we just throw out unless we
// know both controllers!
if (HasKnownControler(node))
{
// this should check each one
prefs->m_convertRotationJoint = false;
prefs->m_convertTranslationJoint = false;
prefs->m_optimizeRotation = false;
prefs->m_optimizeTranslation = false;
prefs->m_forceConvertRotation = false;
prefs->m_forceConvertTranslation = false;
prefs->m_rotationRange = false;
prefs->m_translationRange = false;
}
else
{
prefs->m_forceConvertRotation = true;
prefs->m_forceConvertTranslation = true;
Interval total_time = m_max_interface->GetAnimRange();
int start_frame;
int end_frame;
TIME_TO_FRAME(total_time.Start(), start_frame);
TIME_TO_FRAME(total_time.End(), end_frame);
prefs->m_convertRotationJoint = true;
prefs->m_convertTranslationJoint = true;
prefs->m_rotationConvertType = JointPreference::LinearKeyframeType;
prefs->m_translationConvertType = JointPreference::LinearKeyframeType;
prefs->m_optimizeRotation = true;
prefs->m_rotationThreshold = 0.3f;
prefs->m_rotationSampleStartFrame = start_frame;
prefs->m_rotationSampleEndFrame = end_frame;
prefs->m_optimizeTranslation = true;
prefs->m_translationThreshold = 0.05f;
prefs->m_translationSampleStartFrame = start_frame;
prefs->m_translationSampleEndFrame = end_frame;
prefs->m_rotationRange = false;
prefs->m_translationRange = false;
}
// Detect if translation is there
// Detect if rotation is there
}
Verify(prefs->m_decodeWithVelocity == true || prefs->m_decodeWithVelocity == false);
}
//===========================================================================//
bool JointEditDialog::NodeIsRoot(INode* node)
{
// root node defined as being a child to theworld
if (m_max_interface->GetRootNode() == node->GetParentNode())
{
return true;
}
return false;
}
//===========================================================================//
bool JointEditDialog::KnownNode(INode* node)
{
ObjectState os;
SClass_ID SCID;
Class_ID CID;
os = node->EvalWorldState(m_max_interface->GetTime());
if (os.obj)
{
SCID = os.obj->SuperClassID();
CID = os.obj->ClassID();
switch (SCID)
{
case GEOMOBJECT_CLASS_ID:
return true;
case HELPER_CLASS_ID:
if (CID == Class_ID(DUMMY_CLASS_ID,0) || CID == Class_ID(BONE_CLASS_ID, 0)
||CID == SITEOBJECT_CLASS_ID)
{
return true;
}
break;
}
}
return false;
}
//===========================================================================//
bool
JointEditDialog::HasKnownControler(INode *node)
{
Control *c;
c = node->GetTMController();
// If known consists of .. is the top a leaf node? if so is it a PRS_CONTROL_CLASS_ID ?
// If it is a prs, are both the p & r known to me?
// we ignore scale.
// This works but...MAN...do we need Euelers now!
// Check leaf, if it is not a leaf ( leaf is the last node on a branch, imagine )
// then it must be procedural and wierd. That would mean that it has one controller
// for position, rotation and scale
if (c->IsLeaf())
{
return false;
}
// Make sure it is a Position Rotation Scale control class, since we don't support hybreeds.
if (c->ClassID().PartA() != PRS_CONTROL_CLASS_ID)
{
return false;
}
if (
IsKnownControlerType(c->GetRotationController()) &&
IsKnownControlerType(c->GetPositionController())
)
{
return true;
}
// We didn't know it so
// it is hasta la vista ( ?sp? )
return false;
}
//===========================================================================//
bool
JointEditDialog::IsKnownControlerType(Control *c)
{
if ( c == NULL )
{
return false;
}
switch(c->ClassID().PartA())
{
case LININTERP_POSITION_CLASS_ID:
case LININTERP_ROTATION_CLASS_ID:
return true;
}
return false;
}
//===========================================================================//
bool JointEditDialog::NodeAnimated(INode* node)
{
// this does not correctly get bones....
// only way to tell is to spin through them...
#if 0
ObjectState os;
SClass_ID SCID;
Class_ID CID;
os = node->EvalWorldState(0);
if (os.obj)
{
SCID = os.obj->SuperClassID();
CID = os.obj->ClassID();
if ((SCID == HELPER_CLASS_ID) && (CID == Class_ID(BONE_CLASS_ID, 0)))
{
if (node->IsAnimated())
{
return true;
}
Interval iv = m_max_interface->GetAnimRange();
TimeValue start = iv.Start();
TimeValue end = iv.End();
int delta = GetTicksPerFrame();
Matrix3 lastTM = node->GetNodeTM(start);
for (int time_of_key=start; time_of_key<=end; time_of_key+=delta)
{
Matrix3 nodeTM;
nodeTM = node->GetNodeTM(time_of_key);
for (int i = 0; i < 4; ++i)
{
Point3 m1 = nodeTM.GetRow(i);
Point3 m2 = lastTM.GetRow(i);
if (m1 != m2)
{
return true;
}
}
lastTM = nodeTM;
}
}
}
return (node->IsAnimated())?true:false;
#endif
//just evaluate the name
//cull out sites unless they are animated...
//cull out anything not joint_
const char *node_name = node->GetName();
if (!_stricmp(node_name, "joint_world"))
{
return false;
}
if (!_stricmp(node_name, "joint_lgunabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_luarmabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_rgunabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_ruarmabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_torsoabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_torsobelow"))
{
return false;
}
if (!_stricmp(node_name, "joint_hipabove"))
{
return false;
}
if (!_stricmp(node_name, "joint_hipbelow"))
{
return false;
}
if (!_strnicmp(node_name, "joint_", 6))
{
return true;
}
if (!_strnicmp(node_name, "site_", 5))
{
if (node_name)
{
ObjectState os;
os = node->EvalWorldState(0);
SClass_ID SCID;
Class_ID CID;
if (os.obj)
{
SCID = os.obj->SuperClassID();
CID = os.obj->ClassID();
if (SCID == HELPER_CLASS_ID && CID == SITEOBJECT_CLASS_ID)
{
IParamBlock *pb = (IParamBlock*)os.obj->GetParamBlock();
return (pb->IsAnimated())?true:false;
}
}
}
return false;
}
//deal with life then move on.
return false;
}
void JointEditDialog::OnConvertRotCheck()
{
CButton *button = (CButton *)GetDlgItem(IDC_CONVERT_ROT_CHECK);
if (button->GetCheck())
{
GetDlgItem(IDC_COMBO_ROT_CONVERT)->EnableWindow(true);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_ROT_CONVERT);
box->SetCurSel( 2 );
}
else
{
GetDlgItem(IDC_COMBO_ROT_CONVERT)->EnableWindow(false);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_ROT_CONVERT);
box->SetCurSel( -1 );
}
}
void JointEditDialog::OnCheckRotOpt()
{
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_ROT_OPT);
if (button->GetCheck())
{
GetDlgItem(IDC_EDIT_ROT_THRESH)->EnableWindow(true);
GetDlgItem(IDC_CHECK_ROT_RANGE)->EnableWindow(true);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_ROT_THRESH);
edit->SetWindowText("0.3");
}
else
{
GetDlgItem(IDC_EDIT_ROT_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_ROT_RANGE)->EnableWindow(false);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_ROT_THRESH);
edit->SetWindowText("");
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_ROT_RANGE);
if (button->GetCheck())
{
button->SetCheck(0);
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText("");
}
}
}
void JointEditDialog::OnCheckRotRange()
{
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_ROT_RANGE);
if (button->GetCheck())
{
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(true);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(true);
Interval total_time = m_max_interface->GetAnimRange();
int start_frame;
int end_frame;
TIME_TO_FRAME(total_time.Start(), start_frame);
TIME_TO_FRAME(total_time.End(), end_frame);
char buffer[20];
CEdit *edit;
sprintf(buffer, "%d", start_frame);
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText(buffer);
sprintf(buffer, "%d", end_frame);
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText(buffer);
}
else
{
GetDlgItem(IDC_ROT_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_ROT_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_ROT_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_ROT_MAX_RANGE);
edit->SetWindowText("");
}
}
void JointEditDialog::OnConvertTranCheck()
{
CButton *button = (CButton *)GetDlgItem(IDC_CONVERT_TRAN_CHECK);
if (button->GetCheck())
{
GetDlgItem(IDC_COMBO_TRAN_CONVERT)->EnableWindow(true);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_TRAN_CONVERT);
box->SetCurSel( 2 );
}
else
{
GetDlgItem(IDC_COMBO_TRAN_CONVERT)->EnableWindow(false);
CComboBox *box = (CComboBox *)GetDlgItem(IDC_COMBO_TRAN_CONVERT);
box->SetCurSel( -1 );
}
}
void JointEditDialog::OnCheckTranOpt()
{
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_TRAN_OPT);
if (button->GetCheck())
{
GetDlgItem(IDC_EDIT_TRAN_THRESH)->EnableWindow(true);
GetDlgItem(IDC_CHECK_TRAN_RANGE)->EnableWindow(true);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_TRAN_THRESH);
edit->SetWindowText("0.05");
}
else
{
GetDlgItem(IDC_EDIT_TRAN_THRESH)->EnableWindow(false);
GetDlgItem(IDC_CHECK_TRAN_RANGE)->EnableWindow(false);
CEdit *edit = (CEdit *)GetDlgItem(IDC_EDIT_TRAN_THRESH);
edit->SetWindowText("");
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_TRAN_RANGE);
if (button->GetCheck())
{
button->SetCheck(0);
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText("");
}
}
}
void JointEditDialog::OnCheckTranRange()
{
CButton *button = (CButton *)GetDlgItem(IDC_CHECK_TRAN_RANGE);
if (button->GetCheck())
{
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(true);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(true);
Interval total_time = m_max_interface->GetAnimRange();
int start_frame;
int end_frame;
TIME_TO_FRAME(total_time.Start(), start_frame);
TIME_TO_FRAME(total_time.End(), end_frame);
char buffer[20];
CEdit *edit;
sprintf(buffer, "%d", start_frame);
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText(buffer);
sprintf(buffer, "%d", end_frame);
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText(buffer);
}
else
{
GetDlgItem(IDC_TRAN_MIN_RANGE)->EnableWindow(false);
GetDlgItem(IDC_TRAN_MAX_RANGE)->EnableWindow(false);
CEdit *edit;
edit = (CEdit *)GetDlgItem(IDC_TRAN_MIN_RANGE);
edit->SetWindowText("");
edit = (CEdit *)GetDlgItem(IDC_TRAN_MAX_RANGE);
edit->SetWindowText("");
}
}
////////////////////////////////////////////////////////////////////////////////
int
JointEditDialog::CountChildren(
INode *node
)
{
// Me
int total_count = 1;
// and all my children
for (int i = 0; i < node->NumberOfChildren(); i++)
{
INode *child_node = node->GetChildNode(i);
assert(child_node != NULL);
total_count += CountChildren(child_node);
}
return total_count;
}