1518 lines
43 KiB
C++
1518 lines
43 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/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : W3DView *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Tools/W3DView/DataTreeView.cpp $*
|
||
|
* *
|
||
|
* Author:: Patrick Smith *
|
||
|
* *
|
||
|
* $Modtime:: 6/18/01 9:11a $*
|
||
|
* *
|
||
|
* $Revision:: 35 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
|
||
|
#include "StdAfx.H"
|
||
|
#include "W3DView.H"
|
||
|
#include "DataTreeView.H"
|
||
|
#include "RendObj.H"
|
||
|
#include "ViewerAssetMgr.H"
|
||
|
#include "Globals.h"
|
||
|
#include "W3DViewDoc.H"
|
||
|
#include "MainFrm.H"
|
||
|
#include "DistLod.H"
|
||
|
#include "AnimObj.H"
|
||
|
#include "HcAnim.H"
|
||
|
#include "AssetInfo.H"
|
||
|
#include "Utils.H"
|
||
|
#include "Vector.H"
|
||
|
#include "Part_Emt.H"
|
||
|
#include "Agg_Def.H"
|
||
|
#include "BMP2D.H"
|
||
|
#include "HLod.H"
|
||
|
#include "ViewerScene.h"
|
||
|
#include "texture.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// Local Prototypes
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void Set_Highest_LOD (RenderObjClass *render_obj);
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// MFC Stuff
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
IMPLEMENT_DYNCREATE(CDataTreeView, CTreeView)
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CDataTreeView
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
CDataTreeView::CDataTreeView (void)
|
||
|
: m_hMaterialsRoot (NULL),
|
||
|
m_hMeshRoot (NULL),
|
||
|
m_hMeshCollectionRoot (NULL),
|
||
|
m_hAggregateRoot (NULL),
|
||
|
m_hPrimitivesRoot (NULL),
|
||
|
m_hEmitterRoot (NULL),
|
||
|
m_hLODRoot (NULL),
|
||
|
m_hSoundRoot (NULL),
|
||
|
m_iPrimitivesIcon (-1),
|
||
|
m_iAnimationIcon (-1),
|
||
|
m_iTCAnimationIcon(-1),
|
||
|
m_iADAnimationIcon(-1),
|
||
|
m_iMeshIcon (-1),
|
||
|
m_iMaterialIcon (-1),
|
||
|
m_iLODIcon (-1),
|
||
|
m_iAggregateIcon (-1),
|
||
|
m_iEmitterIcon (-1),
|
||
|
m_iSoundIcon (-1),
|
||
|
m_RestrictAnims (true)
|
||
|
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// ~CDataTreeView
|
||
|
//
|
||
|
CDataTreeView::~CDataTreeView (void)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(CDataTreeView, CTreeView)
|
||
|
//{{AFX_MSG_MAP(CDataTreeView)
|
||
|
ON_WM_CREATE()
|
||
|
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged)
|
||
|
ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem)
|
||
|
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnDraw
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::OnDraw (CDC *pDC)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDataTreeView diagnostics
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
void CDataTreeView::AssertValid() const
|
||
|
{
|
||
|
CTreeView::AssertValid();
|
||
|
}
|
||
|
|
||
|
void CDataTreeView::Dump(CDumpContext& dc) const
|
||
|
{
|
||
|
CTreeView::Dump(dc);
|
||
|
}
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDataTreeView message handlers
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// PreCreateWindow
|
||
|
//
|
||
|
BOOL
|
||
|
CDataTreeView::PreCreateWindow (CREATESTRUCT& cs)
|
||
|
{
|
||
|
// Modify the style bits for the window so it will
|
||
|
// have buttons and lines between nodes.
|
||
|
cs.style |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS;
|
||
|
|
||
|
// Allow the base class to process this message
|
||
|
return CTreeView::PreCreateWindow(cs);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnInitialUpdate
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::OnInitialUpdate (void)
|
||
|
{
|
||
|
// Allow the base class to process this message
|
||
|
CTreeView::OnInitialUpdate ();
|
||
|
|
||
|
// TODO: Add your specialized code here and/or call the base class
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreateRootNodes
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::CreateRootNodes (void)
|
||
|
{
|
||
|
// Insert all the root nodes
|
||
|
m_hMaterialsRoot = GetTreeCtrl ().InsertItem ("Materials", m_iMaterialIcon, m_iMaterialIcon);
|
||
|
m_hMeshRoot = GetTreeCtrl ().InsertItem ("Mesh", m_iMeshIcon, m_iMeshIcon);
|
||
|
m_hHierarchyRoot = GetTreeCtrl ().InsertItem ("Hierarchy", m_iHierarchyIcon, m_iHierarchyIcon);
|
||
|
m_hLODRoot = GetTreeCtrl ().InsertItem ("H-LOD", m_iLODIcon, m_iLODIcon);
|
||
|
m_hMeshCollectionRoot = GetTreeCtrl ().InsertItem ("Mesh Collection", m_iMeshIcon, m_iMeshIcon);
|
||
|
m_hAggregateRoot = GetTreeCtrl ().InsertItem ("Aggregate", m_iAggregateIcon, m_iAggregateIcon);
|
||
|
m_hEmitterRoot = GetTreeCtrl ().InsertItem ("Emitter", m_iEmitterIcon, m_iEmitterIcon);
|
||
|
m_hPrimitivesRoot = GetTreeCtrl ().InsertItem ("Primitives", m_iPrimitivesIcon, m_iPrimitivesIcon);
|
||
|
m_hSoundRoot = GetTreeCtrl ().InsertItem ("Sounds", m_iSoundIcon, m_iSoundIcon);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnCreate
|
||
|
//
|
||
|
int
|
||
|
CDataTreeView::OnCreate (LPCREATESTRUCT lpCreateStruct)
|
||
|
{
|
||
|
if (CTreeView::OnCreate(lpCreateStruct) == -1)
|
||
|
return -1;
|
||
|
|
||
|
CImageList imageList;
|
||
|
imageList.Create (16, 18, ILC_COLOR | ILC_MASK, 5, 10);
|
||
|
|
||
|
// Add the icons to the imagelist
|
||
|
m_iAnimationIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_ANIMATION)));
|
||
|
m_iTCAnimationIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_ANIMATION_COMPRESSED)));
|
||
|
m_iADAnimationIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_ANIMATION_COMPRESSED_DELTA)));
|
||
|
m_iMeshIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_MESH)));
|
||
|
m_iMaterialIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_MATERIAL)));
|
||
|
m_iLODIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_LOD)));
|
||
|
m_iAggregateIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_HIERARCHY)));
|
||
|
m_iEmitterIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_HIERARCHY)));
|
||
|
m_iHierarchyIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_HIERARCHY)));
|
||
|
m_iPrimitivesIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_PRIMITIVES)));
|
||
|
m_iSoundIcon = imageList.Add (::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_SOUND)));
|
||
|
|
||
|
// Pass the imagelist onto the tree control
|
||
|
GetTreeCtrl ().SetImageList (&imageList, TVSIL_NORMAL);
|
||
|
imageList.Detach ();
|
||
|
|
||
|
// Create the root nodes that will hold the contain
|
||
|
// asset types.
|
||
|
CreateRootNodes ();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Load_Materials_Into_Tree
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Load_Materials_Into_Tree (void)
|
||
|
{
|
||
|
// Get an iterator from the asset manager that we can
|
||
|
// use to enumerate the currently loaded textures
|
||
|
HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
|
||
|
|
||
|
// Loop through all the textures in the manager
|
||
|
for (ite.First ();
|
||
|
!ite.Is_Done ();
|
||
|
ite.Next ()) {
|
||
|
|
||
|
// Get the current texture name
|
||
|
TextureClass* ptexture=ite.Peek_Value();
|
||
|
LPCTSTR texture_name = ptexture->Get_Texture_Name();
|
||
|
|
||
|
if ((ptexture != NULL) &&
|
||
|
FindChildItem (m_hMaterialsRoot, texture_name) == NULL) {
|
||
|
|
||
|
// Add this entry to the tree
|
||
|
HTREEITEM tree_item = GetTreeCtrl ().InsertItem (texture_name, m_iMaterialIcon, m_iMaterialIcon, m_hMaterialsRoot, TVI_SORT);
|
||
|
ASSERT (tree_item != NULL);
|
||
|
|
||
|
// Allocate a new asset information class to associate with this entry
|
||
|
ptexture->Add_Ref ();
|
||
|
AssetInfoClass *asset_info = new AssetInfoClass (texture_name, TypeMaterial, NULL, (DWORD)ptexture);
|
||
|
GetTreeCtrl ().SetItemData (tree_item, (ULONG)asset_info);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// LoadAssetsIntoTree
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::LoadAssetsIntoTree (void)
|
||
|
{
|
||
|
// Turn off repainting
|
||
|
GetTreeCtrl ().SetRedraw (FALSE);
|
||
|
|
||
|
DynamicVectorClass<CString> dist_lod_list;
|
||
|
|
||
|
// Get an iterator from the asset manager that we can
|
||
|
// use to enumerate the currently loaded assets
|
||
|
RenderObjIterator *pObjEnum = WW3DAssetManager::Get_Instance()->Create_Render_Obj_Iterator ();
|
||
|
ASSERT (pObjEnum);
|
||
|
if (pObjEnum) {
|
||
|
|
||
|
// Loop through all the assets in the manager
|
||
|
for (pObjEnum->First ();
|
||
|
pObjEnum->Is_Done () == FALSE;
|
||
|
pObjEnum->Next ()) {
|
||
|
|
||
|
// Does this render obj really exist?
|
||
|
LPCTSTR pszItemName = pObjEnum->Current_Item_Name ();
|
||
|
if (WW3DAssetManager::Get_Instance()->Render_Obj_Exists (pszItemName)) {
|
||
|
|
||
|
BOOL bInsert = FALSE;
|
||
|
HTREEITEM hParentNode = NULL;
|
||
|
ASSET_TYPE assetType = TypeUnknown;
|
||
|
int iIconIndex = -1;
|
||
|
|
||
|
// What type of asset is this?
|
||
|
switch (pObjEnum->Current_Item_Class_ID ()) {
|
||
|
|
||
|
case RenderObjClass::CLASSID_COLLECTION:
|
||
|
// This is a 'mesh collection', we want to add this under the 'collection' node.
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hMeshCollectionRoot;
|
||
|
assetType = TypeMesh;
|
||
|
iIconIndex = m_iMeshIcon;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// This is a mesh render object, we want to add this under the mesh node.
|
||
|
//
|
||
|
case RenderObjClass::CLASSID_MESH:
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hMeshRoot;
|
||
|
assetType = TypeMesh;
|
||
|
iIconIndex = m_iMeshIcon;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// This is a sound render obj, we want to add this under the sound node.
|
||
|
//
|
||
|
case RenderObjClass::CLASSID_SOUND:
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hSoundRoot;
|
||
|
assetType = TypeSound;
|
||
|
iIconIndex = m_iSoundIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_HMODEL:
|
||
|
// Shouldn't happen
|
||
|
ASSERT (0);
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_PARTICLEEMITTER:
|
||
|
// This is an 'emitter', we want to add this under the 'emitter' node.
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hEmitterRoot;
|
||
|
assetType = TypeEmitter;
|
||
|
iIconIndex = m_iEmitterIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_SPHERE:
|
||
|
case RenderObjClass::CLASSID_RING:
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hPrimitivesRoot;
|
||
|
assetType = TypePrimitives;
|
||
|
iIconIndex = m_iPrimitivesIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_DISTLOD:
|
||
|
dist_lod_list.Add (pszItemName);
|
||
|
case RenderObjClass::CLASSID_HLOD:
|
||
|
// Assume this is a simple hierarchy LOD, we want to add this under the hierarchy node.
|
||
|
bInsert = TRUE;
|
||
|
hParentNode = m_hHierarchyRoot;
|
||
|
assetType = TypeHierarchy;
|
||
|
iIconIndex = m_iHierarchyIcon;
|
||
|
|
||
|
// Test this HLOD to see if its a true LOD or a simple hierarchy
|
||
|
if (::Is_Real_LOD (pszItemName)) {
|
||
|
hParentNode = m_hLODRoot;
|
||
|
assetType = TypeLOD;
|
||
|
iIconIndex = m_iLODIcon;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (bInsert) {
|
||
|
|
||
|
// Check to see if this object is an aggregate
|
||
|
if (::Is_Aggregate (pszItemName)) {
|
||
|
hParentNode = m_hAggregateRoot;
|
||
|
assetType = TypeAggregate;
|
||
|
iIconIndex = m_iAggregateIcon;
|
||
|
}
|
||
|
|
||
|
// If this object isn't already in the tree then add it
|
||
|
if (FindChildItem (hParentNode, pszItemName) == NULL) {
|
||
|
|
||
|
// Add this entry to the tree
|
||
|
HTREEITEM hItem = GetTreeCtrl ().InsertItem (pszItemName, iIconIndex, iIconIndex, hParentNode, TVI_SORT);
|
||
|
ASSERT (hItem != NULL);
|
||
|
|
||
|
// Allocate a new asset information class to associate with this entry
|
||
|
AssetInfoClass *asset_info = new AssetInfoClass (pszItemName, assetType);
|
||
|
GetTreeCtrl ().SetItemData (hItem, (ULONG)asset_info);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Free the enumerator object we created earlier
|
||
|
SAFE_DELETE (pObjEnum);
|
||
|
}
|
||
|
|
||
|
// Loop through all the old-style dist lod's and convert their prototypes
|
||
|
// to the new HLOD format
|
||
|
for (int index = 0; index < dist_lod_list.Count (); index ++) {
|
||
|
HLodClass *plod = (HLodClass *)WW3DAssetManager::Get_Instance ()->Create_Render_Obj (dist_lod_list[index]);
|
||
|
if (plod != NULL) {
|
||
|
HLodDefClass *definition = new HLodDefClass (*plod);
|
||
|
HLodPrototypeClass *prototype = new HLodPrototypeClass (definition);
|
||
|
WW3DAssetManager::Get_Instance ()->Remove_Prototype (dist_lod_list[index]);
|
||
|
WW3DAssetManager::Get_Instance ()->Add_Prototype (prototype);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now that we've added all the hierarchies to the tree, add their animations
|
||
|
// as well.
|
||
|
LoadAnimationsIntoTree ();
|
||
|
Load_Materials_Into_Tree ();
|
||
|
|
||
|
// Turn;repainting back on
|
||
|
GetTreeCtrl ().SetRedraw (TRUE);
|
||
|
|
||
|
// Force the window to be repainted
|
||
|
Invalidate (FALSE);
|
||
|
UpdateWindow ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// LoadAnimationsIntoTree
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::LoadAnimationsIntoTree (void)
|
||
|
{
|
||
|
// Get an iterator from the asset manager that we can
|
||
|
// use to enumerate the currently loaded assets
|
||
|
AssetIterator *pAnimEnum = WW3DAssetManager::Get_Instance()->Create_HAnim_Iterator ();
|
||
|
ASSERT (pAnimEnum);
|
||
|
if (pAnimEnum)
|
||
|
{
|
||
|
// Loop through all the animations in the manager
|
||
|
for (pAnimEnum->First ();
|
||
|
(pAnimEnum->Is_Done () == FALSE);
|
||
|
pAnimEnum->Next ())
|
||
|
{
|
||
|
LPCTSTR pszAnimName = pAnimEnum->Current_Item_Name ();
|
||
|
|
||
|
// Get an instance of the animation object
|
||
|
HAnimClass *pHierarchyAnim = WW3DAssetManager::Get_Instance()->Get_HAnim (pszAnimName);
|
||
|
|
||
|
ASSERT (pHierarchyAnim);
|
||
|
if (pHierarchyAnim)
|
||
|
{
|
||
|
// Get the name of the hierarchy that this animation belongs to
|
||
|
LPCTSTR pszHierarchyName = pHierarchyAnim->Get_HName ();
|
||
|
|
||
|
// Loop through all the hierarchies and add this animation to any pertinent ones
|
||
|
for (HTREEITEM hNode = FindFirstChildItemBasedOnHierarchyName (m_hHierarchyRoot, pszHierarchyName);
|
||
|
(hNode != NULL);
|
||
|
hNode = FindSiblingItemBasedOnHierarchyName (hNode, pszHierarchyName))
|
||
|
{
|
||
|
// Is this animation already loaded into the tree?
|
||
|
HTREEITEM hAnimationNode = FindChildItem (hNode, pszAnimName);
|
||
|
if (hAnimationNode == NULL)
|
||
|
{
|
||
|
// Add this animation as a child of the hierarchy
|
||
|
hAnimationNode = GetTreeCtrl ().InsertItem (pszAnimName, m_iAnimationIcon, m_iAnimationIcon, hNode, TVI_SORT);
|
||
|
ASSERT (hAnimationNode != NULL);
|
||
|
|
||
|
// Associate the items name with its entry
|
||
|
GetTreeCtrl ().SetItemData (hAnimationNode, (ULONG)new AssetInfoClass (pszAnimName, TypeAnimation));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Loop through all the aggregates and add this animation to any pertinent ones
|
||
|
for (hNode = FindFirstChildItemBasedOnHierarchyName (m_hAggregateRoot, pszHierarchyName);
|
||
|
(hNode != NULL);
|
||
|
hNode = FindSiblingItemBasedOnHierarchyName (hNode, pszHierarchyName))
|
||
|
{
|
||
|
// Is this animation already loaded into the tree?
|
||
|
HTREEITEM hAnimationNode = FindChildItem (hNode, pszAnimName);
|
||
|
if (hAnimationNode == NULL)
|
||
|
{
|
||
|
// Add this animation as a child of the hierarchy
|
||
|
hAnimationNode = GetTreeCtrl ().InsertItem (pszAnimName, m_iAnimationIcon, m_iAnimationIcon, hNode, TVI_SORT);
|
||
|
ASSERT (hAnimationNode != NULL);
|
||
|
|
||
|
// Associate the items name with its entry
|
||
|
GetTreeCtrl ().SetItemData (hAnimationNode, (ULONG)new AssetInfoClass (pszAnimName, TypeAnimation));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Loop through all the hierarchies and add this animation to any pertinent ones
|
||
|
for (hNode = FindFirstChildItemBasedOnHierarchyName (m_hLODRoot, pszHierarchyName);
|
||
|
(hNode != NULL);
|
||
|
hNode = FindSiblingItemBasedOnHierarchyName (hNode, pszHierarchyName))
|
||
|
{
|
||
|
// Is this animation already loaded into the tree?
|
||
|
HTREEITEM hAnimationNode = FindChildItem (hNode, pszAnimName);
|
||
|
if (hAnimationNode == NULL)
|
||
|
{
|
||
|
// Add this animation as a child of the hierarchy
|
||
|
hAnimationNode = GetTreeCtrl ().InsertItem (pszAnimName, m_iAnimationIcon, m_iAnimationIcon, hNode, TVI_SORT);
|
||
|
ASSERT (hAnimationNode != NULL);
|
||
|
|
||
|
// Associate the items name with its entry
|
||
|
GetTreeCtrl ().SetItemData (hAnimationNode, (ULONG)new AssetInfoClass (pszAnimName, TypeAnimation));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Release our hold on this animation...
|
||
|
MEMBER_RELEASE (pHierarchyAnim);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Free the object
|
||
|
delete pAnimEnum;
|
||
|
pAnimEnum = NULL;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// LoadAnimationsIntoTree
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::LoadAnimationsIntoTree (HTREEITEM hItem)
|
||
|
{
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (hItem);
|
||
|
ASSERT (asset_info != NULL);
|
||
|
|
||
|
// Get an iterator from the asset manager that we can
|
||
|
// use to enumerate the currently loaded assets
|
||
|
AssetIterator *pAnimEnum = WW3DAssetManager::Get_Instance()->Create_HAnim_Iterator ();
|
||
|
ASSERT (pAnimEnum);
|
||
|
if (pAnimEnum)
|
||
|
{
|
||
|
// Loop through all the animations in the manager
|
||
|
for (pAnimEnum->First ();
|
||
|
(pAnimEnum->Is_Done () == FALSE);
|
||
|
pAnimEnum->Next ())
|
||
|
{
|
||
|
LPCTSTR pszAnimName = pAnimEnum->Current_Item_Name ();
|
||
|
|
||
|
// Get an instance of the animation object
|
||
|
HAnimClass *pHierarchyAnim = WW3DAssetManager::Get_Instance()->Get_HAnim (pszAnimName);
|
||
|
|
||
|
ASSERT (pHierarchyAnim);
|
||
|
if (pHierarchyAnim)
|
||
|
{
|
||
|
// Get the name of the hierarchy that this animation belongs to
|
||
|
LPCTSTR pszHierarchyName = pHierarchyAnim->Get_HName ();
|
||
|
|
||
|
// Does the item match the hierarchy name?
|
||
|
if (::lstrcmp (asset_info->Get_Hierarchy_Name (), pszHierarchyName) == 0)
|
||
|
{
|
||
|
// Is this animation already loaded into the tree?
|
||
|
HTREEITEM hAnimationNode = FindChildItem (hItem, pszAnimName);
|
||
|
if (hAnimationNode == NULL)
|
||
|
{
|
||
|
// Add this animation as a child of the hierarchy
|
||
|
hAnimationNode = GetTreeCtrl ().InsertItem (pszAnimName, m_iAnimationIcon, m_iAnimationIcon, hItem, TVI_SORT);
|
||
|
ASSERT (hAnimationNode != NULL);
|
||
|
|
||
|
// Associate the items name with its entry
|
||
|
GetTreeCtrl ().SetItemData (hAnimationNode, (ULONG)new AssetInfoClass (pszAnimName, TypeAnimation));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Release our hold on the animation object
|
||
|
MEMBER_RELEASE (pHierarchyAnim);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Free the object
|
||
|
delete pAnimEnum;
|
||
|
pAnimEnum = NULL;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Determine_Tree_Location
|
||
|
//
|
||
|
ASSET_TYPE
|
||
|
CDataTreeView::Determine_Tree_Location
|
||
|
(
|
||
|
RenderObjClass &render_obj,
|
||
|
HTREEITEM &hroot,
|
||
|
int &icon_index
|
||
|
)
|
||
|
{
|
||
|
ASSET_TYPE type = TypeUnknown;
|
||
|
|
||
|
// What class does this render object belong to?
|
||
|
switch (render_obj.Class_ID ()) {
|
||
|
|
||
|
case RenderObjClass::CLASSID_COLLECTION:
|
||
|
hroot = m_hMeshCollectionRoot;
|
||
|
type = TypeMesh;
|
||
|
icon_index = m_iMeshIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_MESH:
|
||
|
hroot = m_hMeshRoot;
|
||
|
type = TypeMesh;
|
||
|
icon_index = m_iMeshIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_SOUND:
|
||
|
hroot = m_hSoundRoot;
|
||
|
type = TypeSound;
|
||
|
icon_index = m_iSoundIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_HMODEL:
|
||
|
// Shouldn't happen
|
||
|
ASSERT (0);
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_PARTICLEEMITTER:
|
||
|
hroot = m_hEmitterRoot;
|
||
|
type = TypeEmitter;
|
||
|
icon_index = m_iEmitterIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_SPHERE:
|
||
|
case RenderObjClass::CLASSID_RING:
|
||
|
hroot = m_hPrimitivesRoot;
|
||
|
type = TypePrimitives;
|
||
|
icon_index = m_iPrimitivesIcon;
|
||
|
break;
|
||
|
|
||
|
case RenderObjClass::CLASSID_DISTLOD:
|
||
|
case RenderObjClass::CLASSID_HLOD:
|
||
|
hroot = m_hHierarchyRoot;
|
||
|
type = TypeHierarchy;
|
||
|
icon_index = m_iHierarchyIcon;
|
||
|
|
||
|
//
|
||
|
// Determine if this is a true LOD or a simple hierarchy
|
||
|
//
|
||
|
if (((HLodClass &)render_obj).Get_LOD_Count () > 1) {
|
||
|
hroot = m_hLODRoot;
|
||
|
type = TypeLOD;
|
||
|
icon_index = m_iLODIcon;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Is this an aggregate?
|
||
|
//
|
||
|
if (render_obj.Get_Base_Model_Name () != NULL) {
|
||
|
hroot = m_hAggregateRoot;
|
||
|
type = TypeAggregate;
|
||
|
icon_index = m_iAggregateIcon;
|
||
|
}
|
||
|
|
||
|
// Return the type of node
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Determine_Tree_Location
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Determine_Tree_Location
|
||
|
(
|
||
|
ASSET_TYPE type,
|
||
|
HTREEITEM &hroot,
|
||
|
int &icon_index
|
||
|
)
|
||
|
{
|
||
|
// What type of asset is this?
|
||
|
switch (type) {
|
||
|
|
||
|
case TypeMesh:
|
||
|
hroot = m_hMeshRoot;
|
||
|
icon_index = m_iMeshIcon;
|
||
|
break;
|
||
|
|
||
|
case TypeSound:
|
||
|
hroot = m_hSoundRoot;
|
||
|
icon_index = m_iSoundIcon;
|
||
|
break;
|
||
|
|
||
|
case TypeAggregate:
|
||
|
hroot = m_hAggregateRoot;
|
||
|
icon_index = m_iAggregateIcon;
|
||
|
break;
|
||
|
|
||
|
case TypeHierarchy:
|
||
|
// Shouldn't happen
|
||
|
ASSERT (0);
|
||
|
break;
|
||
|
|
||
|
case TypeEmitter:
|
||
|
hroot = m_hEmitterRoot;
|
||
|
icon_index = m_iEmitterIcon;
|
||
|
break;
|
||
|
|
||
|
case TypePrimitives:
|
||
|
hroot = m_hPrimitivesRoot;
|
||
|
icon_index = m_iPrimitivesIcon;
|
||
|
break;
|
||
|
|
||
|
case TypeLOD:
|
||
|
hroot = m_hLODRoot;
|
||
|
icon_index = m_iLODIcon;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Add_Asset_To_Tree
|
||
|
//
|
||
|
bool
|
||
|
CDataTreeView::Add_Asset_To_Tree
|
||
|
(
|
||
|
LPCTSTR name,
|
||
|
ASSET_TYPE type,
|
||
|
bool bselect
|
||
|
)
|
||
|
{
|
||
|
// Assume failure
|
||
|
bool retval = false;
|
||
|
|
||
|
// Param OK?
|
||
|
ASSERT (name != NULL);
|
||
|
if (name != NULL) {
|
||
|
|
||
|
// Turn off repainting
|
||
|
GetTreeCtrl ().SetRedraw (FALSE);
|
||
|
|
||
|
// Determime where this asset should go
|
||
|
HTREEITEM hparent = NULL;
|
||
|
int icon_index = 0;
|
||
|
Determine_Tree_Location (type, hparent, icon_index);
|
||
|
|
||
|
// Is this asset already in the tree?
|
||
|
HTREEITEM htree_item = FindChildItem (hparent, name);
|
||
|
if (htree_item == NULL) {
|
||
|
|
||
|
// Add this object to the tree
|
||
|
htree_item = GetTreeCtrl ().InsertItem (name,
|
||
|
icon_index,
|
||
|
icon_index,
|
||
|
hparent,
|
||
|
TVI_SORT);
|
||
|
|
||
|
// Associate the render object with its entry in the tree
|
||
|
AssetInfoClass *asset_info = new AssetInfoClass (name, type);
|
||
|
GetTreeCtrl ().SetItemData (htree_item, (ULONG)asset_info);
|
||
|
|
||
|
// Load the object's animations into the tree (if necessary)
|
||
|
if (asset_info->Can_Asset_Have_Animations ()) {
|
||
|
LoadAnimationsIntoTree (htree_item);
|
||
|
}
|
||
|
|
||
|
// Success!
|
||
|
retval = (htree_item != NULL);
|
||
|
}
|
||
|
|
||
|
// Select the instance (if requested)
|
||
|
if (bselect) {
|
||
|
GetTreeCtrl ().SelectItem (htree_item);
|
||
|
GetTreeCtrl ().EnsureVisible (htree_item);
|
||
|
}
|
||
|
|
||
|
// Turn painting back on
|
||
|
GetTreeCtrl ().SetRedraw (TRUE);
|
||
|
|
||
|
// Force the window to be repainted
|
||
|
Invalidate (FALSE);
|
||
|
UpdateWindow ();
|
||
|
}
|
||
|
|
||
|
// Return the true/false result code
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// FindChildItem
|
||
|
//
|
||
|
HTREEITEM
|
||
|
CDataTreeView::FindChildItem
|
||
|
(
|
||
|
HTREEITEM hParentItem,
|
||
|
RenderObjClass *prender_obj
|
||
|
)
|
||
|
{
|
||
|
// Assume we won't find the item
|
||
|
HTREEITEM hchild_item = NULL;
|
||
|
|
||
|
// Loop through all the children of this node
|
||
|
for (HTREEITEM htree_item = GetTreeCtrl ().GetChildItem (hParentItem);
|
||
|
(htree_item != NULL) && (hchild_item == NULL);
|
||
|
htree_item = GetTreeCtrl ().GetNextSiblingItem (htree_item)) {
|
||
|
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
|
||
|
// Is this the item we were looking for?
|
||
|
if (asset_info &&
|
||
|
asset_info->Peek_Render_Obj () == prender_obj) {
|
||
|
|
||
|
// This was the item we were looking for, return
|
||
|
// its handle to the caller
|
||
|
hchild_item = htree_item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the child item handle
|
||
|
return hchild_item;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// FindChildItem
|
||
|
//
|
||
|
HTREEITEM
|
||
|
CDataTreeView::FindChildItem
|
||
|
(
|
||
|
HTREEITEM hParentItem,
|
||
|
LPCTSTR pszChildItemName
|
||
|
)
|
||
|
{
|
||
|
// Assume we won't find the item
|
||
|
HTREEITEM hChildItem = NULL;
|
||
|
|
||
|
// Loop through all the children of this node
|
||
|
for (HTREEITEM hTreeItem = GetTreeCtrl ().GetChildItem (hParentItem);
|
||
|
(hTreeItem != NULL) && (hChildItem == NULL);
|
||
|
hTreeItem = GetTreeCtrl ().GetNextSiblingItem (hTreeItem))
|
||
|
{
|
||
|
// Is this the child item we were looking for?
|
||
|
if (::lstrcmp (GetTreeCtrl ().GetItemText (hTreeItem), pszChildItemName) == 0)
|
||
|
{
|
||
|
// This was the child item we were looking for, return
|
||
|
// its handle to the caller
|
||
|
hChildItem = hTreeItem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the child item handle
|
||
|
return hChildItem;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// FindSiblingItemBasedOnHierarchyName
|
||
|
//
|
||
|
HTREEITEM
|
||
|
CDataTreeView::FindSiblingItemBasedOnHierarchyName
|
||
|
(
|
||
|
HTREEITEM hCurrentItem,
|
||
|
LPCTSTR pszHierarchyName
|
||
|
)
|
||
|
{
|
||
|
// Assume we won't find the item
|
||
|
HTREEITEM hSiblingItem = NULL;
|
||
|
|
||
|
// Loop through all the siblings of this node
|
||
|
HTREEITEM hTreeItem = hCurrentItem;
|
||
|
while (((hTreeItem = GetTreeCtrl ().GetNextSiblingItem (hTreeItem)) != NULL) &&
|
||
|
(hSiblingItem == NULL))
|
||
|
{
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (hTreeItem);
|
||
|
|
||
|
// Is this the item we were looking for?
|
||
|
if (m_RestrictAnims == false ||
|
||
|
(asset_info && ::lstrcmp (asset_info->Get_Hierarchy_Name (), pszHierarchyName) == 0))
|
||
|
{
|
||
|
// This was the item we were looking for, return
|
||
|
// its handle to the caller
|
||
|
hSiblingItem = hTreeItem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the sibling item handle
|
||
|
return hSiblingItem;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// FindFirstChildItemBasedOnHierarchyName
|
||
|
//
|
||
|
HTREEITEM
|
||
|
CDataTreeView::FindFirstChildItemBasedOnHierarchyName
|
||
|
(
|
||
|
HTREEITEM hParentItem,
|
||
|
LPCTSTR pszHierarchyName
|
||
|
)
|
||
|
{
|
||
|
// Assume we won't find the item
|
||
|
HTREEITEM hChildItem = NULL;
|
||
|
|
||
|
// Loop through all the children of this node
|
||
|
for (HTREEITEM hTreeItem = GetTreeCtrl ().GetChildItem (hParentItem);
|
||
|
(hTreeItem != NULL) && (hChildItem == NULL);
|
||
|
hTreeItem = GetTreeCtrl ().GetNextSiblingItem (hTreeItem))
|
||
|
{
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (hTreeItem);
|
||
|
|
||
|
//
|
||
|
// Is this the item we were looking for?
|
||
|
//
|
||
|
if (m_RestrictAnims == false ||
|
||
|
(asset_info && ::lstrcmp (asset_info->Get_Hierarchy_Name (), pszHierarchyName) == 0))
|
||
|
{
|
||
|
// This was the child item we were looking for, return
|
||
|
// its handle to the caller
|
||
|
hChildItem = hTreeItem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the child item handle
|
||
|
return hChildItem;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnSelChanged
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::OnSelChanged
|
||
|
(
|
||
|
NMHDR* pNMHDR,
|
||
|
LRESULT* pResult
|
||
|
)
|
||
|
{
|
||
|
// Display the new selection
|
||
|
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
||
|
Display_Asset (pNMTreeView->itemNew.hItem);
|
||
|
(*pResult) = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Display_Asset
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Display_Asset (HTREEITEM htree_item)
|
||
|
{
|
||
|
if (htree_item == NULL) {
|
||
|
htree_item = GetTreeCtrl ().GetSelectedItem ();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the object associated with this entry
|
||
|
//
|
||
|
AssetInfoClass *asset_info = NULL;
|
||
|
if (htree_item != NULL) {
|
||
|
asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
}
|
||
|
|
||
|
if (asset_info != NULL) {
|
||
|
|
||
|
// Get the current document, so we can get a pointer to the scene
|
||
|
CW3DViewDoc *pdoc = (CW3DViewDoc *)GetDocument ();
|
||
|
ASSERT (pdoc != NULL);
|
||
|
if (pdoc != NULL) {
|
||
|
|
||
|
// What type of asset is it?
|
||
|
switch (asset_info->Get_Type ())
|
||
|
{
|
||
|
case TypeCompressedAnimation:
|
||
|
case TypeAnimation:
|
||
|
{
|
||
|
HTREEITEM hParentItem = GetTreeCtrl ().GetParentItem (htree_item);
|
||
|
if (hParentItem != NULL) {
|
||
|
|
||
|
// Ask the document to start playing the animation for this object
|
||
|
RenderObjClass *prender_obj = Create_Render_Obj_To_Display (hParentItem);
|
||
|
pdoc->PlayAnimation (prender_obj,
|
||
|
asset_info->Get_Name ());
|
||
|
MEMBER_RELEASE (prender_obj);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TypeEmitter:
|
||
|
{
|
||
|
// Ask the document to display this object
|
||
|
ParticleEmitterClass *emitter = (ParticleEmitterClass *)Create_Render_Obj_To_Display (htree_item);
|
||
|
pdoc->Display_Emitter (emitter);
|
||
|
MEMBER_RELEASE (emitter);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TypeHierarchy:
|
||
|
{
|
||
|
// If the advanced animation option is turned on, display a dialog
|
||
|
// where the user can choose which animations to play together.
|
||
|
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
// Ask the document to display this object
|
||
|
RenderObjClass *prender_obj = Create_Render_Obj_To_Display (htree_item);
|
||
|
pdoc->DisplayObject (prender_obj);
|
||
|
MEMBER_RELEASE (prender_obj);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the main window of our app
|
||
|
CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
|
||
|
if (pCMainWnd != NULL) {
|
||
|
|
||
|
// Let the main window know our selection type has changed
|
||
|
pCMainWnd->OnSelectionChanged (asset_info->Get_Type ());
|
||
|
|
||
|
if (asset_info->Get_Type () == TypeAggregate) {
|
||
|
pCMainWnd->Update_Emitters_List ();
|
||
|
} else {
|
||
|
|
||
|
::EnableMenuItem (::GetSubMenu (::GetMenu (*pCMainWnd), 3), 3, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
|
||
|
HMENU hsub_menu = pCMainWnd->Get_Emitters_List_Menu ();
|
||
|
int index = 0;
|
||
|
while (::RemoveMenu (hsub_menu, index, MF_BYPOSITION)) {
|
||
|
//index ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
// Reset the display
|
||
|
CW3DViewDoc* pdoc = (CW3DViewDoc *)GetDocument ();
|
||
|
ASSERT (pdoc != NULL);
|
||
|
if (pdoc != NULL) {
|
||
|
pdoc->DisplayObject ((RenderObjClass *)NULL);
|
||
|
|
||
|
CMainFrame *main_wnd = (CMainFrame *)::AfxGetMainWnd ();
|
||
|
if (main_wnd != NULL) {
|
||
|
main_wnd->OnSelectionChanged (TypeUnknown);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnDeleteItem
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::OnDeleteItem
|
||
|
(
|
||
|
NMHDR *pNMHDR,
|
||
|
LRESULT *pResult
|
||
|
)
|
||
|
{
|
||
|
// Get the information object for this asset
|
||
|
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)pNMTreeView->itemOld.lParam;
|
||
|
|
||
|
// If this is a texture, then free our hold on its interface
|
||
|
if (asset_info && (asset_info->Get_Type () == TypeMaterial)) {
|
||
|
TextureClass *ptexture = (TextureClass *)asset_info->Get_User_Number ();
|
||
|
REF_PTR_RELEASE (ptexture);
|
||
|
}
|
||
|
|
||
|
// Free the asset information object
|
||
|
SAFE_DELETE (asset_info);
|
||
|
|
||
|
// Reset the data associated with this entry
|
||
|
GetTreeCtrl ().SetItemData (pNMTreeView->itemOld.hItem, NULL);
|
||
|
(*pResult) = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Get_Current_Asset_Info
|
||
|
//
|
||
|
AssetInfoClass *
|
||
|
CDataTreeView::Get_Current_Asset_Info (void) const
|
||
|
{
|
||
|
AssetInfoClass *asset_info = NULL;
|
||
|
|
||
|
// Get the currently selected node from the tree control
|
||
|
HTREEITEM htree_item = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (htree_item != NULL) {
|
||
|
|
||
|
// Get the data associated with this item
|
||
|
asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
}
|
||
|
|
||
|
// Return the asset information associated with the current item
|
||
|
return asset_info;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Get_Current_Render_Obj
|
||
|
//
|
||
|
RenderObjClass *
|
||
|
CDataTreeView::Get_Current_Render_Obj (void) const
|
||
|
{
|
||
|
RenderObjClass *prender_obj = NULL;
|
||
|
|
||
|
// Get the currently selected node from the tree control
|
||
|
HTREEITEM htree_item = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (htree_item != NULL) {
|
||
|
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
|
||
|
// Return the render object pointer
|
||
|
prender_obj = asset_info->Peek_Render_Obj ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the render object pointer
|
||
|
return prender_obj;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetCurrentSelectionName
|
||
|
//
|
||
|
LPCTSTR
|
||
|
CDataTreeView::GetCurrentSelectionName (void)
|
||
|
{
|
||
|
LPCTSTR pname = NULL;
|
||
|
|
||
|
// Get the currently selected node from the tree control
|
||
|
HTREEITEM htree_item = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (htree_item != NULL) {
|
||
|
|
||
|
// Get the data associated with this item
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
|
||
|
// Return the name of the asset to the caller
|
||
|
pname = asset_info->Get_Name ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the name of the selected node
|
||
|
return pname;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetCurrentSelectionType
|
||
|
//
|
||
|
ASSET_TYPE
|
||
|
CDataTreeView::GetCurrentSelectionType (void)
|
||
|
{
|
||
|
ASSET_TYPE type = TypeUnknown;
|
||
|
|
||
|
// Get the currently selected node from the tree control
|
||
|
HTREEITEM htree_item = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (htree_item != NULL) {
|
||
|
|
||
|
// Get the associated asset information for this node.
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
type = asset_info->Get_Type ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the type of the selected node
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// OnDblclk
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::OnDblclk
|
||
|
(
|
||
|
NMHDR* pNMHDR,
|
||
|
LRESULT* pResult
|
||
|
)
|
||
|
{
|
||
|
// Get the main window of our app
|
||
|
CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
|
||
|
if (pCMainWnd != NULL)
|
||
|
{
|
||
|
// Display the properties for the currently selected object
|
||
|
//pCMainWnd->ShowObjectProperties ();
|
||
|
}
|
||
|
|
||
|
(*pResult) = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Build_Render_Object_List
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Build_Render_Object_List
|
||
|
(
|
||
|
DynamicVectorClass <CString> &asset_list,
|
||
|
HTREEITEM hparent
|
||
|
)
|
||
|
{
|
||
|
// Loop through all the children of this node
|
||
|
for (HTREEITEM htree_item = GetTreeCtrl ().GetChildItem (hparent);
|
||
|
(htree_item != NULL);
|
||
|
htree_item = GetTreeCtrl ().GetNextSiblingItem (htree_item)) {
|
||
|
|
||
|
// Determine if this is an asset type we want to add to the list
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if ((asset_info != NULL) &&
|
||
|
(asset_info->Get_Type () != TypeAnimation) &&
|
||
|
(asset_info->Get_Type () != TypeCompressedAnimation) &&
|
||
|
(asset_info->Get_Type () != TypeMaterial))
|
||
|
{
|
||
|
asset_list.Add (GetTreeCtrl ().GetItemText (htree_item));
|
||
|
}
|
||
|
|
||
|
// If this item has children, then add the children recursively
|
||
|
if (GetTreeCtrl ().ItemHasChildren (htree_item)) {
|
||
|
Build_Render_Object_List (asset_list, htree_item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Create_Render_Obj_To_Display
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
RenderObjClass *
|
||
|
CDataTreeView::Create_Render_Obj_To_Display (HTREEITEM htree_item)
|
||
|
{
|
||
|
// Lookup the information object associated with this asset
|
||
|
RenderObjClass *render_obj = NULL;
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
|
||
|
// Use the asset's instance if there is one, otherwise attempt to create one
|
||
|
render_obj = asset_info->Get_Render_Obj ();
|
||
|
if (render_obj == NULL) {
|
||
|
|
||
|
// If this is a texture, then create a special BMP obj from it
|
||
|
if (asset_info->Get_Type () == TypeMaterial) {
|
||
|
TextureClass *ptexture = (TextureClass *)asset_info->Get_User_Number ();
|
||
|
if (ptexture != NULL) {
|
||
|
render_obj = new Bitmap2DObjClass (ptexture, 0.5F, 0.5F, true, false, false, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Finally, if we aren't successful, create a new instance based on its name
|
||
|
//
|
||
|
if (render_obj == NULL) {
|
||
|
render_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj (asset_info->Get_Name ());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Force the highest level LOD
|
||
|
//
|
||
|
if ( render_obj != NULL &&
|
||
|
::GetCurrentDocument ()->GetScene ()->Are_LODs_Switching () == false)
|
||
|
{
|
||
|
Set_Highest_LOD (render_obj);
|
||
|
}
|
||
|
|
||
|
return render_obj;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Refresh_Asset
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Refresh_Asset
|
||
|
(
|
||
|
LPCTSTR new_name,
|
||
|
LPCTSTR old_name,
|
||
|
ASSET_TYPE type
|
||
|
)
|
||
|
{
|
||
|
// Params OK?
|
||
|
if ((new_name != NULL) && (old_name != NULL)) {
|
||
|
|
||
|
// Turn off repainting
|
||
|
GetTreeCtrl ().SetRedraw (FALSE);
|
||
|
|
||
|
// Determime where this asset should go
|
||
|
HTREEITEM hparent = NULL;
|
||
|
int icon_index = 0;
|
||
|
Determine_Tree_Location (type, hparent, icon_index);
|
||
|
|
||
|
// Can we find the item we are supposed to refresh?
|
||
|
HTREEITEM htree_item = FindChildItem (hparent, old_name);
|
||
|
if (htree_item != NULL) {
|
||
|
|
||
|
// Refresh the item's text in the tree control
|
||
|
GetTreeCtrl ().SetItemText (htree_item, new_name);
|
||
|
|
||
|
// Refresh the associated asset info structure
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (htree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
asset_info->Set_Name (new_name);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
// This asset wasn't already in the tree, so add it...
|
||
|
Add_Asset_To_Tree (new_name, type, true);
|
||
|
}
|
||
|
|
||
|
// Turn painting back on
|
||
|
GetTreeCtrl ().SetRedraw (TRUE);
|
||
|
|
||
|
// Force the window to be repainted
|
||
|
Invalidate (FALSE);
|
||
|
UpdateWindow ();
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Select_Next
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Select_Next (void)
|
||
|
{
|
||
|
//
|
||
|
// Get the selected entry in the tree control
|
||
|
//
|
||
|
HTREEITEM hselected = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (hselected != NULL) {
|
||
|
|
||
|
//
|
||
|
// Select the item that follows the currently selected item
|
||
|
//
|
||
|
HTREEITEM hitem = GetTreeCtrl ().GetNextItem (hselected, TVGN_NEXT);
|
||
|
if (hitem != NULL) {
|
||
|
GetTreeCtrl ().SelectItem (hitem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Select_Prev
|
||
|
//
|
||
|
void
|
||
|
CDataTreeView::Select_Prev (void)
|
||
|
{
|
||
|
//
|
||
|
// Get the selected entry in the tree control
|
||
|
//
|
||
|
HTREEITEM hselected = GetTreeCtrl ().GetSelectedItem ();
|
||
|
if (hselected != NULL) {
|
||
|
|
||
|
//
|
||
|
// Select the item that follows the currently selected item
|
||
|
//
|
||
|
HTREEITEM hitem = GetTreeCtrl ().GetNextItem (hselected, TVGN_PREVIOUS);
|
||
|
if (hitem != NULL) {
|
||
|
GetTreeCtrl ().SelectItem (hitem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Reload_Lightmap_Models
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
CDataTreeView::Reload_Lightmap_Models (void)
|
||
|
{
|
||
|
Free_Child_Models (m_hMeshCollectionRoot);
|
||
|
Free_Child_Models (m_hHierarchyRoot);
|
||
|
Free_Child_Models (m_hMeshRoot);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Free_Child_Models
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
CDataTreeView::Free_Child_Models (HTREEITEM parent_item)
|
||
|
{
|
||
|
//
|
||
|
// Loop through all the children of this node
|
||
|
//
|
||
|
for ( HTREEITEM tree_item = GetTreeCtrl ().GetChildItem (parent_item);
|
||
|
tree_item != NULL;
|
||
|
tree_item = GetTreeCtrl ().GetNextSiblingItem (tree_item))
|
||
|
{
|
||
|
//
|
||
|
// Get the data associated with this item
|
||
|
//
|
||
|
AssetInfoClass *asset_info = (AssetInfoClass *)GetTreeCtrl ().GetItemData (tree_item);
|
||
|
if (asset_info != NULL) {
|
||
|
WW3DAssetManager::Get_Instance ()->Remove_Prototype (asset_info->Get_Name ());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Highest_LOD
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Set_Highest_LOD (RenderObjClass *render_obj)
|
||
|
{
|
||
|
if (render_obj != NULL) {
|
||
|
for (int index = 0; index < render_obj->Get_Num_Sub_Objects (); index ++) {
|
||
|
RenderObjClass *sub_obj = render_obj->Get_Sub_Object (index);
|
||
|
if (sub_obj != NULL) {
|
||
|
Set_Highest_LOD (sub_obj);
|
||
|
}
|
||
|
MEMBER_RELEASE (sub_obj);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Switcht this LOD to its highest level
|
||
|
//
|
||
|
if (render_obj->Class_ID () == RenderObjClass::CLASSID_HLOD) {
|
||
|
((HLodClass *)render_obj)->Set_LOD_Level (((HLodClass *)render_obj)->Get_Lod_Count () - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Restrict_Anims
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
CDataTreeView::Restrict_Anims (bool onoff)
|
||
|
{
|
||
|
if (m_RestrictAnims != onoff) {
|
||
|
m_RestrictAnims = onoff;
|
||
|
|
||
|
//
|
||
|
// Reload the tree
|
||
|
//
|
||
|
GetTreeCtrl ().DeleteAllItems ();
|
||
|
CreateRootNodes ();
|
||
|
LoadAssetsIntoTree ();
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|