216 lines
5.9 KiB
C++
216 lines
5.9 KiB
C++
/*
|
|
** 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/>.
|
|
*/
|
|
|
|
// AnimReportPage.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "w3dview.h"
|
|
#include "W3DViewDoc.h"
|
|
#include "AdvancedAnimSheet.h"
|
|
#include "AnimReportPage.h"
|
|
|
|
|
|
#include "HAnim.h"
|
|
#include "HTree.h"
|
|
#include "Utils.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAnimReportPage property page
|
|
|
|
IMPLEMENT_DYNCREATE(CAnimReportPage, CPropertyPage)
|
|
|
|
CAnimReportPage::CAnimReportPage(CAdvancedAnimSheet *sheet)
|
|
: CPropertyPage(CAnimReportPage::IDD),
|
|
m_Sheet(sheet)
|
|
{
|
|
//{{AFX_DATA_INIT(CAnimReportPage)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
CAnimReportPage::~CAnimReportPage()
|
|
{
|
|
}
|
|
|
|
void CAnimReportPage::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CAnimReportPage)
|
|
DDX_Control(pDX, IDC_ANIM_REPORT, m_AnimReport);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CAnimReportPage, CPropertyPage)
|
|
//{{AFX_MSG_MAP(CAnimReportPage)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAnimReportPage message handlers
|
|
|
|
BOOL CAnimReportPage::OnInitDialog()
|
|
{
|
|
CPropertyPage::OnInitDialog();
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
void CAnimReportPage::FillListControl()
|
|
{
|
|
// Add the first column to the animation report. All bone names will
|
|
// go in this column.
|
|
m_AnimReport.InsertColumn(0, "Bone Name");
|
|
|
|
// Get the current render object and it's HTree. If it doesn't have
|
|
// an HTree, then it's not animating and we're not interested.
|
|
RenderObjClass *robj = ::GetCurrentDocument()->GetDisplayedObject();
|
|
if (robj == NULL)
|
|
return;
|
|
const HTreeClass *htree = robj->Get_HTree();
|
|
if (htree == NULL)
|
|
return;
|
|
|
|
// Get a sorted array of animations that affect the currently active object.
|
|
HAnimClass **anim = m_Sheet->GetAnims();
|
|
int anim_count = m_Sheet->GetAnimCount();
|
|
|
|
|
|
/*
|
|
** Create a column in the report view for each animation.
|
|
*/
|
|
|
|
int column_count; // number of columns in the report view (EXCLUDING the bone column)
|
|
bool indirect; // true if we have one column per animation selected in the mixing page
|
|
if (m_Sheet->m_SelectedAnims.Count() > 0)
|
|
{
|
|
column_count = m_Sheet->m_SelectedAnims.Count();
|
|
indirect = true;
|
|
}
|
|
else
|
|
{
|
|
column_count = anim_count;
|
|
indirect = false;
|
|
}
|
|
|
|
int i, j;
|
|
int anim_idx; // column index, essentially (anim_idx + 1 == column for that anim)
|
|
for (i = 0; i < column_count; i++)
|
|
{
|
|
// Add a new column with the name of this animation as the title.
|
|
anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
|
|
if (m_AnimReport.InsertColumn(anim_idx+1, anim[anim_idx]->Get_Name(), LVCFMT_CENTER) == -1)
|
|
{
|
|
// Failed to add a new column to the list control.
|
|
ASSERT(false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Add a row to the report for each bone in the object affected by
|
|
** an animation. It's entry (row/col) will contain the animation
|
|
** channels with valid animation data.
|
|
*/
|
|
|
|
for (i = 0; i < column_count; i++)
|
|
{
|
|
// Grab the anim pointer directly.
|
|
anim_idx = indirect ? m_Sheet->m_SelectedAnims[i] : i;
|
|
HAnimClass *pAnim = anim[anim_idx];
|
|
|
|
// Which bones does it affect, and how?
|
|
int num_bones = robj->Get_Num_Bones();
|
|
for (j = 1; j < num_bones; j++) // skip bone 0, which is always the root bone
|
|
{
|
|
// Add each bone to the report (regardless of animation status)
|
|
// if it isn't already there.
|
|
int idx = FindItem(htree->Get_Bone_Name(j));
|
|
if (idx == -1)
|
|
{
|
|
// Wasn't present, add a new item for this bone.
|
|
idx = m_AnimReport.InsertItem(m_AnimReport.GetItemCount(),
|
|
htree->Get_Bone_Name(j));
|
|
}
|
|
|
|
if (pAnim->Is_Node_Motion_Present(j))
|
|
{
|
|
// Add motion channel info to the appropriate column.
|
|
char channels[6]; // strlen("XYZQV")+1
|
|
ZeroMemory(channels, sizeof(channels));
|
|
MakeChannelStr(j, pAnim, channels);
|
|
m_AnimReport.SetItem(idx, i+1, LVIF_TEXT, channels, 0,0,0,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Make the columns sized nicely.
|
|
m_AnimReport.SetColumnWidth(0, LVSCW_AUTOSIZE);
|
|
for (i = 0; i < column_count; i++)
|
|
m_AnimReport.SetColumnWidth(i+1, LVSCW_AUTOSIZE_USEHEADER);
|
|
|
|
// All done, the report view is set up.
|
|
}
|
|
|
|
int CAnimReportPage::FindItem (const char *item_name)
|
|
{
|
|
LVFINDINFO lvfi;
|
|
lvfi.flags = LVFI_STRING;
|
|
lvfi.psz = item_name;
|
|
return m_AnimReport.FindItem(&lvfi);
|
|
}
|
|
|
|
void CAnimReportPage::MakeChannelStr (int bone_idx, HAnimClass *hanim, char *channels)
|
|
{
|
|
if (hanim->Has_X_Translation(bone_idx))
|
|
strcat(channels, "X");
|
|
if (hanim->Has_Y_Translation(bone_idx))
|
|
strcat(channels, "Y");
|
|
if (hanim->Has_Z_Translation(bone_idx))
|
|
strcat(channels, "Z");
|
|
if (hanim->Has_Rotation(bone_idx))
|
|
strcat(channels, "Q");
|
|
if (hanim->Has_Visibility(bone_idx))
|
|
strcat(channels, "V");
|
|
}
|
|
|
|
BOOL CAnimReportPage::OnSetActive()
|
|
{
|
|
// Delete all info in the report view.
|
|
m_AnimReport.DeleteAllItems();
|
|
while (m_AnimReport.DeleteColumn(0));
|
|
|
|
// Fill the list control each time we're set active so that
|
|
// a change in selection on the mixing page will have an
|
|
// effect on this page.
|
|
FillListControl();
|
|
|
|
return CPropertyPage::OnSetActive();
|
|
}
|