AnimReportPage.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // AnimReportPage.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "w3dview.h"
  22. #include "W3DViewDoc.h"
  23. #include "AdvancedAnimSheet.h"
  24. #include "AnimReportPage.h"
  25. #include "HAnim.h"
  26. #include "HTree.h"
  27. #include "Utils.h"
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CAnimReportPage property page
  35. IMPLEMENT_DYNCREATE(CAnimReportPage, CPropertyPage)
  36. CAnimReportPage::CAnimReportPage(CAdvancedAnimSheet *sheet)
  37. : CPropertyPage(CAnimReportPage::IDD),
  38. m_Sheet(sheet)
  39. {
  40. //{{AFX_DATA_INIT(CAnimReportPage)
  41. // NOTE: the ClassWizard will add member initialization here
  42. //}}AFX_DATA_INIT
  43. }
  44. CAnimReportPage::~CAnimReportPage()
  45. {
  46. }
  47. void CAnimReportPage::DoDataExchange(CDataExchange* pDX)
  48. {
  49. CPropertyPage::DoDataExchange(pDX);
  50. //{{AFX_DATA_MAP(CAnimReportPage)
  51. DDX_Control(pDX, IDC_ANIM_REPORT, m_AnimReport);
  52. //}}AFX_DATA_MAP
  53. }
  54. BEGIN_MESSAGE_MAP(CAnimReportPage, CPropertyPage)
  55. //{{AFX_MSG_MAP(CAnimReportPage)
  56. //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58. /////////////////////////////////////////////////////////////////////////////
  59. // CAnimReportPage message handlers
  60. BOOL CAnimReportPage::OnInitDialog()
  61. {
  62. CPropertyPage::OnInitDialog();
  63. return TRUE; // return TRUE unless you set the focus to a control
  64. // EXCEPTION: OCX Property Pages should return FALSE
  65. }
  66. void CAnimReportPage::FillListControl()
  67. {
  68. // Add the first column to the animation report. All bone names will
  69. // go in this column.
  70. m_AnimReport.InsertColumn(0, "Bone Name");
  71. // Get the current render object and it's HTree. If it doesn't have
  72. // an HTree, then it's not animating and we're not interested.
  73. RenderObjClass *robj = ::GetCurrentDocument()->GetDisplayedObject();
  74. if (robj == NULL)
  75. return;
  76. const HTreeClass *htree = robj->Get_HTree();
  77. if (htree == NULL)
  78. return;
  79. // Get a sorted array of animations that affect the currently active object.
  80. HAnimClass **anim = m_Sheet->GetAnims();
  81. int anim_count = m_Sheet->GetAnimCount();
  82. /*
  83. ** Create a column in the report view for each animation.
  84. */
  85. int column_count; // number of columns in the report view (EXCLUDING the bone column)
  86. bool indirect; // true if we have one column per animation selected in the mixing page
  87. if (m_Sheet->m_SelectedAnims.Count() > 0)
  88. {
  89. column_count = m_Sheet->m_SelectedAnims.Count();
  90. indirect = true;
  91. }
  92. else
  93. {
  94. column_count = anim_count;
  95. indirect = false;
  96. }
  97. int i, j;
  98. int anim_idx; // column index, essentially (anim_idx + 1 == column for that anim)
  99. for (i = 0; i < column_count; i++)
  100. {
  101. // Add a new column with the name of this animation as the title.
  102. anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
  103. if (m_AnimReport.InsertColumn(anim_idx+1, anim[anim_idx]->Get_Name(), LVCFMT_CENTER) == -1)
  104. {
  105. // Failed to add a new column to the list control.
  106. ASSERT(false);
  107. }
  108. }
  109. /*
  110. ** Add a row to the report for each bone in the object affected by
  111. ** an animation. It's entry (row/col) will contain the animation
  112. ** channels with valid animation data.
  113. */
  114. for (i = 0; i < column_count; i++)
  115. {
  116. // Grab the anim pointer directly.
  117. anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
  118. HAnimClass *pAnim = anim[anim_idx];
  119. // Which bones does it affect, and how?
  120. int num_bones = robj->Get_Num_Bones();
  121. for (j = 1; j < num_bones; j++) // skip bone 0, which is always the root bone
  122. {
  123. // Add each bone to the report (regardless of animation status)
  124. // if it isn't already there.
  125. int idx = FindItem(htree->Get_Bone_Name(j));
  126. if (idx == -1)
  127. {
  128. // Wasn't present, add a new item for this bone.
  129. idx = m_AnimReport.InsertItem(m_AnimReport.GetItemCount(),
  130. htree->Get_Bone_Name(j));
  131. }
  132. if (pAnim->Is_Node_Motion_Present(j))
  133. {
  134. // Add motion channel info to the appropriate column.
  135. char channels[6]; // strlen("XYZQV")+1
  136. ZeroMemory(channels, sizeof(channels));
  137. MakeChannelStr(j, pAnim, channels);
  138. m_AnimReport.SetItem(idx, i+1, LVIF_TEXT, channels, 0,0,0,0);
  139. }
  140. }
  141. }
  142. // Make the columns sized nicely.
  143. m_AnimReport.SetColumnWidth(0, LVSCW_AUTOSIZE);
  144. for (i = 0; i < column_count; i++)
  145. m_AnimReport.SetColumnWidth(i+1, LVSCW_AUTOSIZE_USEHEADER);
  146. // All done, the report view is set up.
  147. }
  148. int CAnimReportPage::FindItem (const char *item_name)
  149. {
  150. LVFINDINFO lvfi;
  151. lvfi.flags = LVFI_STRING;
  152. lvfi.psz = item_name;
  153. return m_AnimReport.FindItem(&lvfi);
  154. }
  155. void CAnimReportPage::MakeChannelStr (int bone_idx, HAnimClass *hanim, char *channels)
  156. {
  157. if (hanim->Has_X_Translation(bone_idx))
  158. strcat(channels, "X");
  159. if (hanim->Has_Y_Translation(bone_idx))
  160. strcat(channels, "Y");
  161. if (hanim->Has_Z_Translation(bone_idx))
  162. strcat(channels, "Z");
  163. if (hanim->Has_Rotation(bone_idx))
  164. strcat(channels, "Q");
  165. if (hanim->Has_Visibility(bone_idx))
  166. strcat(channels, "V");
  167. }
  168. BOOL CAnimReportPage::OnSetActive()
  169. {
  170. // Delete all info in the report view.
  171. m_AnimReport.DeleteAllItems();
  172. while (m_AnimReport.DeleteColumn(0));
  173. // Fill the list control each time we're set active so that
  174. // a change in selection on the mixing page will have an
  175. // effect on this page.
  176. FillListControl();
  177. return CPropertyPage::OnSetActive();
  178. }