| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts 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/>.
- */
- // BoneMgrDialog.cpp : implementation file
- //
- #include "StdAfx.H"
- #include "W3DView.H"
- #include "BoneMgrDialog.H"
- #include "HTree.H"
- #include "AssetMgr.H"
- #include "Utils.H"
- #include "MainFrm.H"
- #include "W3DViewDoc.H"
- #include "DataTreeView.H"
- //#include "HModel.H"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- ///////////////////////////////////////////////////////////////
- //
- // BoneMgrDialogClass
- //
- BoneMgrDialogClass::BoneMgrDialogClass
- (
- RenderObjClass *prender_obj,
- CWnd *pparent
- )
- : m_pBaseModel (prender_obj),
- m_pBackupModel (NULL),
- m_bAttach (true),
- CDialog (BoneMgrDialogClass::IDD, pparent)
- {
- //{{AFX_DATA_INIT(BoneMgrDialogClass)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- return ;
- }
- ///////////////////////////////////////////////////////////////
- //
- // DoDataExchange
- //
- void
- BoneMgrDialogClass::DoDataExchange (CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(BoneMgrDialogClass)
- DDX_Control(pDX, IDC_OBJECT_COMBO, m_ObjectCombo);
- DDX_Control(pDX, IDC_BONE_TREE, m_BoneTree);
- //}}AFX_DATA_MAP
- return ;
- }
- BEGIN_MESSAGE_MAP(BoneMgrDialogClass, CDialog)
- //{{AFX_MSG_MAP(BoneMgrDialogClass)
- ON_NOTIFY(TVN_SELCHANGED, IDC_BONE_TREE, OnSelchangedBoneTree)
- ON_CBN_SELCHANGE(IDC_OBJECT_COMBO, OnSelchangeObjectCombo)
- ON_WM_DESTROY()
- ON_BN_CLICKED(IDC_ATTACH_BUTTON, OnAttachButton)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- ///////////////////////////////////////////////////////////////
- //
- // OnInitDialog
- //
- BOOL
- BoneMgrDialogClass::OnInitDialog (void)
- {
- // Allow the base class to process this message
- CDialog::OnInitDialog ();
- // Make a backup of this hierarchy in case we need to restore it.
- m_pBackupModel = m_pBaseModel->Clone ();
- // Create an icon imagelist for the tree control
- CImageList *pimagelist = new CImageList;
- pimagelist->Create (16, 16, ILC_COLOR | ILC_MASK, 2, 2);
- // Load this icon and add it to our imagelist
- pimagelist->Add ((HICON)::LoadImage (::AfxGetResourceHandle (),
- MAKEINTRESOURCE (IDI_FOLDER),
- IMAGE_ICON,
- 16,
- 16,
- LR_SHARED));
- pimagelist->Add ((HICON)::LoadImage (::AfxGetResourceHandle (),
- MAKEINTRESOURCE (IDI_OBJECT),
- IMAGE_ICON,
- 16,
- 16,
- LR_SHARED));
- m_BoneTree.SetImageList (pimagelist, TVSIL_NORMAL);
- // Get the hierarchy tree for this model so we can enumerate bone's
- // and subobjects.
- HTREEITEM hfirst_item = NULL;
- // Loop through all the bones in this model
- int bone_count = m_pBaseModel->Get_Num_Bones ();
- for (int index = 0; index < bone_count; index ++) {
- const char *pbone_name = m_pBaseModel->Get_Bone_Name (index);
- // Add this bone to the tree control
- HTREEITEM hbone_item = m_BoneTree.InsertItem (pbone_name, 0, 0);
- Fill_Bone_Item (hbone_item, index);
- // Is this the first item we've added to the tree?
- if (hfirst_item == NULL) {
- hfirst_item = hbone_item;
- }
- }
- //
- // Sort the tree control
- //
- m_BoneTree.SortChildren (TVI_ROOT);
- // Build a list of all the render objects currently loaded
- CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
- CDataTreeView *pdata_tree = pdoc->GetDataTreeView ();
- DynamicVectorClass <CString> asset_list;
- pdata_tree->Build_Render_Object_List (asset_list);
- // Add this render object list to the combobox
- for (index = 0; index < asset_list.Count (); index ++) {
- m_ObjectCombo.AddString (asset_list[index]);
- }
- // Select the first entry in the combobox
- m_ObjectCombo.SetCurSel (0);
- OnSelchangeObjectCombo ();
- // Select the first item in the tree
- m_BoneTree.SelectItem (hfirst_item);
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////
- //
- // Fill_Bone_Item
- //
- void
- BoneMgrDialogClass::Fill_Bone_Item
- (
- HTREEITEM hbone_item,
- int bone_index
- )
- {
- // Create a new instance of the hmodel which we can use
- // to compare with the supplied hmodel and determine
- // which 'bones-models' are new.
- const char *orig_model_name = m_pBaseModel->Get_Base_Model_Name ();
- orig_model_name = (orig_model_name == NULL) ? m_pBaseModel->Get_Name () : orig_model_name;
- RenderObjClass *porig_model = WW3DAssetManager::Get_Instance()->Create_Render_Obj (orig_model_name);
- // Build a list of nodes that are contained in the vanilla model
- DynamicVectorClass <RenderObjClass *> orig_node_list;
- for (int index = 0;
- index < porig_model->Get_Num_Sub_Objects_On_Bone (bone_index);
- index ++) {
- RenderObjClass *psubobj = porig_model->Get_Sub_Object_On_Bone (index, bone_index);
- if (psubobj != NULL) {
- orig_node_list.Add (psubobj);
- }
- }
- // Build a list of nodes that are contained in this bone
- DynamicVectorClass <RenderObjClass *> node_list;
- for (index = 0;
- index < m_pBaseModel->Get_Num_Sub_Objects_On_Bone (bone_index);
- index ++) {
- RenderObjClass *psubobj = m_pBaseModel->Get_Sub_Object_On_Bone (index, bone_index);
- if (psubobj != NULL) {
- node_list.Add (psubobj);
- }
- }
- if (node_list.Count () > 0) {
-
- // Add the subobjects to the tree control
- for (int node_index = 0; node_index < node_list.Count (); node_index ++) {
- RenderObjClass *psubobject = node_list[node_index];
- ASSERT (psubobject != NULL);
-
- // Is this subobject new? (i.e. not in a 'vanilla' instance?)
- if (psubobject != NULL &&
- (Is_Object_In_List (psubobject->Get_Name (), orig_node_list) == false)) {
- m_BoneTree.InsertItem (psubobject->Get_Name (), 1, 1, hbone_item);
- }
- }
- }
- // Free our hold on the render objs in the original node list
- for (index = 0; index < orig_node_list.Count (); index ++) {
- MEMBER_RELEASE (orig_node_list[index]);
- }
- // Free our hold on the render objs in the node list
- for (index = 0; index < node_list.Count (); index ++) {
- MEMBER_RELEASE (node_list[index]);
- }
-
- MEMBER_RELEASE (porig_model);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // Is_Object_In_List
- //
- bool
- BoneMgrDialogClass::Is_Object_In_List
- (
- const char *passet_name,
- DynamicVectorClass <RenderObjClass *> &node_list
- )
- {
- // Assume failure
- bool retval = false;
- // Loop through the nodes in the list until we've found the one
- // were are looking for.
- for (int node_index = 0; (node_index < node_list.Count ()) && (retval == false); node_index ++) {
- RenderObjClass *prender_obj = node_list[node_index];
-
- // Is this the render object we were looking for?
- if (prender_obj != NULL &&
- ::lstrcmpi (prender_obj->Get_Name (), passet_name) == 0) {
- retval = true;
- }
- }
- // Return the true/false result code
- return retval;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnSelchangedBoneTree
- //
- void
- BoneMgrDialogClass::OnSelchangedBoneTree
- (
- NMHDR *pNMHDR,
- LRESULT *pResult
- )
- {
- // Make the dialog controls reflect the new selection
- NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;
- Update_Controls (pNMTreeView->itemNew.hItem);
- (*pResult) = 0;
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnSelchangeObjectCombo
- //
- void
- BoneMgrDialogClass::OnSelchangeObjectCombo (void)
- {
- // Get the name of the currently selected render object
- CString name;
- int index = m_ObjectCombo.GetCurSel ();
- m_ObjectCombo.GetLBText (index, name);
- // Change the text of the 'Attach' button based on whether or not
- // this render object is already attached to the current bone.
- if (Is_Render_Obj_Already_Attached (name)) {
- SetDlgItemText (IDC_ATTACH_BUTTON, "&Remove");
- m_bAttach = false;
- } else {
- SetDlgItemText (IDC_ATTACH_BUTTON, "&Attach");
- m_bAttach = true;
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // Is_Render_Obj_Already_Attached
- //
- bool
- BoneMgrDialogClass::Is_Render_Obj_Already_Attached (const CString &name)
- {
- // Assume not already attached
- bool retval = false;
- HTREEITEM htree_item = m_BoneTree.GetSelectedItem ();
- HTREEITEM hparent_item = m_BoneTree.GetParentItem (htree_item);
- htree_item = (hparent_item != NULL) ? hparent_item : htree_item;
- if (htree_item != NULL) {
-
- // Loop through all the children of this bone
- for (HTREEITEM hchild_item = m_BoneTree.GetChildItem (htree_item);
- (hchild_item != NULL) && (retval == false);
- hchild_item = m_BoneTree.GetNextSiblingItem (hchild_item)) {
-
- // Is this the render object we were looking for?
- CString child_name = m_BoneTree.GetItemText (hchild_item);
- if (name.CompareNoCase (child_name) == 0) {
- retval = true;
- }
- }
- }
- // Return the true/false result code
- return retval;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // Update_Controls
- //
- void
- BoneMgrDialogClass::Update_Controls (HTREEITEM selected_item)
- {
- // Get the name of the currently selected item
- CString name = m_BoneTree.GetItemText (selected_item);
- bool bis_bone = (m_BoneTree.GetParentItem (selected_item) == NULL);
- // Did the user select a bone name?
- if (bis_bone) {
- m_BoneName = name;
- } else {
- // Select this render object in the combobox
- int index = m_ObjectCombo.FindStringExact (-1, name);
- m_ObjectCombo.SetCurSel ((index != CB_ERR) ? index : 0);
- // The bone name is the name of the parent item of the selected item.
- m_BoneName = m_BoneTree.GetItemText (m_BoneTree.GetParentItem (selected_item));
- }
- OnSelchangeObjectCombo ();
- // Change the text of the group box to reflect the bone name
- CString text;
- text.Format ("Bone: %s", m_BoneName);
- SetDlgItemText (IDC_BONE_GROUPBOX, text);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnDestroy
- //
- void
- BoneMgrDialogClass::OnDestroy (void)
- {
- // Free the state image list we associated with the control
- CImageList *pimagelist = m_BoneTree.GetImageList (TVSIL_NORMAL);
- m_BoneTree.SetImageList (NULL, TVSIL_NORMAL);
- SAFE_DELETE (pimagelist);
-
- // Allow the base class to process this message
- CDialog::OnDestroy ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnOK
- //
- void
- BoneMgrDialogClass::OnOK (void)
- {
- // Simply forget about the backup we made
- MEMBER_RELEASE (m_pBackupModel);
-
- // Update the hierarchy's cached information to reflect the new settings
- CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
- pdoc->Update_Aggregate_Prototype (*m_pBaseModel);
- // Allow the base class to process this message
- CDialog::OnOK ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnCancel
- //
- void
- BoneMgrDialogClass::OnCancel (void)
- {
- CWaitCursor wait_cursor;
- // Display the backup hierarchy
- CW3DViewDoc *pdoc = (CW3DViewDoc *)((CMainFrame *)::AfxGetMainWnd())->GetActiveDocument ();
- pdoc->DisplayObject (m_pBackupModel, false, false);
- // Allow the base class to process this message
- CDialog::OnCancel ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // OnAttachButton
- //
- void
- BoneMgrDialogClass::OnAttachButton (void)
- {
- // Get the name of the currently selected render object
- CString name;
- int index = m_ObjectCombo.GetCurSel ();
- m_ObjectCombo.GetLBText (index, name);
- // Lookup the currently selected bone item
- HTREEITEM hbone_item = Get_Current_Bone_Item ();
- // Should we attach or remove the render object?
- if (m_bAttach) {
-
- // Create an instance of the render object and attach it to the bone
- RenderObjClass *prender_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj (name);
- if (prender_obj != NULL) {
- m_pBaseModel->Add_Sub_Object_To_Bone (prender_obj, m_BoneName);
- m_BoneTree.InsertItem (name, 1, 1, hbone_item);
- MEMBER_RELEASE (prender_obj);
- }
- } else {
- // Loop through all the subobjects on the bone
- bool found = false;
- int bone_index = m_pBaseModel->Get_Bone_Index (m_BoneName);
- int count = m_pBaseModel->Get_Num_Sub_Objects_On_Bone (bone_index);
- for (int index = 0; (index < count) && !found; index ++) {
-
- // Is this the subobject we were looking for?
- RenderObjClass *psub_obj = m_pBaseModel->Get_Sub_Object_On_Bone (index, bone_index);
- if ((psub_obj != NULL) &&
- (::lstrcmpi (psub_obj->Get_Name (), name) == 0)) {
-
- // Remove this subobject from the bone
- m_pBaseModel->Remove_Sub_Object (psub_obj);
- found = true;
- }
- // Release our hold on this pointer
- MEMBER_RELEASE (psub_obj);
- }
-
- // Remove the object from our UI
- Remove_Object_From_Bone (hbone_item, name);
- }
- // Refresh the UI state
- m_BoneTree.InvalidateRect (NULL, TRUE);
- m_BoneTree.UpdateWindow ();
- Update_Controls (hbone_item);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Current_Bone_Item
- //
- HTREEITEM
- BoneMgrDialogClass::Get_Current_Bone_Item (void)
- {
- // Get the currently selected item and its parent
- HTREEITEM htree_item = m_BoneTree.GetSelectedItem ();
- HTREEITEM hparent_item = m_BoneTree.GetParentItem (htree_item);
-
- // Return the bone item
- return (hparent_item != NULL) ? hparent_item : htree_item;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //
- // Remove_Object_From_Bone
- //
- void
- BoneMgrDialogClass::Remove_Object_From_Bone
- (
- HTREEITEM bone_item,
- const CString &name
- )
- {
- // Loop through all the children of this bone
- for (HTREEITEM hchild_item = m_BoneTree.GetChildItem (bone_item);
- (hchild_item != NULL);
- hchild_item = m_BoneTree.GetNextSiblingItem (hchild_item)) {
-
- // Is this the render object we were looking for?
- CString child_name = m_BoneTree.GetItemText (hchild_item);
- if (name.CompareNoCase (child_name) == 0) {
- m_BoneTree.DeleteItem (hchild_item);
- break ;
- }
- }
-
- return ;
- }
|