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

828 lines
21 KiB
C++

// MFC GosView.cpp : implementation of the CMFCGosView class
//
#include "stdafx.h"
#include "MFC Gos.h"
#include "MFC GosDoc.h"
#include "MFC GosView.h"
#include <GameOS\GameOS.hpp>
#include <ElementRenderer\ElementRenderer.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <ElementRenderer\CameraElement.hpp>
#include <ElementRenderer\ShapeElement.hpp>
#include <ElementRenderer\ListElement.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <ElementRenderer\SwitchElement.hpp>
#include <ElementRenderer\LODElement.hpp>
#include <ElementRenderer\MultiLODElement.hpp>
#include <ElementRenderer\ShapeLODElement.hpp>
#include <ElementRenderer\TreeElement.hpp>
#include <MLR\MLR_I_L_TMesh.hpp>
#include "EditMLRStateDlg.h"
extern CMFCGosApp theApp;
extern ElementRenderer::GroupElement *Scene;
extern MidLevelRenderer::DrawEffectInformation *drawEffectInfo[2];
extern Stuff::RGBAColor Color_Data[2][2*MidLevelRenderer::Limits::Max_Number_Vertices_Per_Mesh];
extern bool drawPointsYes, drawNormalsYes;
extern CList<Stuff::MString*, Stuff::MString*> m_pErf_Name_List;
Stuff::Point3D Normal_Data[2*MidLevelRenderer::Limits::Max_Number_Vertices_Per_Mesh];
/////////////////////////////////////////////////////////////////////////////
// CMFCGosView
IMPLEMENT_DYNCREATE(CMFCGosView, CView)
BEGIN_MESSAGE_MAP(CMFCGosView, CView)
//{{AFX_MSG_MAP(CMFCGosView)
ON_WM_SIZE()
ON_COMMAND(ID_FILE_IMPORT, OnFileImport)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMFCGosView construction/destruction
CMFCGosView *CMFCGosView::Instance;
CMFCGosView::CMFCGosView()
{
erftree=NULL;
imlist=NULL;
CMFCGosView::Instance=this;
}
CMFCGosView::~CMFCGosView()
{
if(imlist)
{
delete imlist;
imlist=NULL;
}
if(erftree)
{
delete erftree;
erftree=NULL;
}
}
BOOL CMFCGosView::PreCreateWindow(CREATESTRUCT& cs)
{
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CMFCGosView drawing
void CMFCGosView::OnDraw(CDC* pDC)
{
CMFCGosDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CMFCGosView diagnostics
#ifdef _DEBUG
void CMFCGosView::AssertValid() const
{
CView::AssertValid();
}
void CMFCGosView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMFCGosDoc* CMFCGosView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCGosDoc)));
return (CMFCGosDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMFCGosView message handlers
LRESULT CMFCGosView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
return CView::WindowProc(message, wParam, lParam);
}
void CMFCGosView::OnInitialUpdate()
{
CView::OnInitialUpdate();
if(!imlist)
{
imlist=new CImageList;
imlist->Create(16,16,ILC_COLOR24|ILC_MASK,4,0);
imlist->Add(ExtractIcon(theApp.m_hInstance,"shell32.dll",12));
imlist->Add(ExtractIcon(theApp.m_hInstance,"shell32.dll",24));
imlist->Add(::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON3D)));
imlist->Add(::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME)));
}
if(!erftree)
{
CRect rct;
GetClientRect(&rct);
erftree=new CErfDataTree;
erftree->Create(TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_EDITLABELS,
rct,this,NULL);
erftree->SetImageList(imlist,TVSIL_NORMAL);
}
erftree->DeleteAllItems();
if(Scene!=NULL)
{
AddErfBranch(TVI_ROOT, Scene);
}
else
{
HTREEITEM tmpitm;
tmpitm=erftree->InsertItem("empty",0,1,TVI_ROOT,TVI_LAST);
erftree->SetItemData(tmpitm,0);
}
erftree->ShowWindow(SW_SHOW);
}
BOOL CMFCGosView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
BOOL ret;
ret=CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
return ret;
}
BOOL CMFCGosView::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
delete imlist;
delete erftree;
return CView::DestroyWindow();
}
void CMFCGosView::AddErfBranch(HTREEITEM node, ElementRenderer::Element *elmt)
{
if(elmt->GetClassID()== ElementRenderer::CameraElementClassID)
{
return;
}
HTREEITEM tmpitm;
CString strTemp;
Stuff::MString * pTempMString=NULL;
PlugOf<MString *>* pTemp = ((*(theApp.m_phashErfNameMapping))
.Find( (DWORD)(void*)elmt ));
if (pTemp && (pTempMString = (pTemp->GetItem()) )!=NULL)
{
strTemp.Format("%s : %s", (LPCSTR)(*pTempMString), (LPCSTR)(elmt->GetClassString()));
}
else
{
strTemp.Format("%s", (LPCSTR)(elmt->GetClassString()));
}
tmpitm = erftree->InsertItem((LPCSTR)strTemp, 0, 1, node, TVI_LAST);
erftree->SetItemData(tmpitm,(DWORD) elmt);
//tmpitm=erftree->InsertItem("Root",0,1,node,TVI_LAST);
switch(elmt->GetClassID())
{
/*
case ElementRenderer::FXElementClassID:
{
}
break;
*/
case ElementRenderer::GroupElementClassID:
{
ElementRenderer::GroupElement *group = Cast_Pointer(ElementRenderer::GroupElement *, elmt);
Stuff::ChainIteratorOf<ElementRenderer::Element*> *children = group->MakeIterator();
Register_Object(children);
ElementRenderer::Element *child = NULL;
while ((child = children->ReadAndNext()) != NULL)
{
AddErfBranch(tmpitm, child);
}
Unregister_Object(children);
delete children;
}
break;
case ElementRenderer::ListElementClassID:
{
ElementRenderer::ListElement *group = Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
AddErfBranch(tmpitm,group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::GridElementClassID:
{
ElementRenderer::GridElement *group = Cast_Pointer(ElementRenderer::GridElement *, elmt);
unsigned char xSize, zSize;
group->GetSize(&xSize, &zSize);
for(int i=0;i<zSize;i++)
for(int j=0;j<xSize;j++)
{
AddErfBranch(tmpitm, group->GetIndexedElement(i, j));
}
}
break;
case ElementRenderer::LODElementClassID:
{
ElementRenderer::ListElement *group = Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
AddErfBranch(tmpitm,group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::PointCloudElementClassID:
{
}
break;
case ElementRenderer::ScalableShapeElementClassID:
{
ElementRenderer::ShapeElement *group = Cast_Pointer(ElementRenderer::ShapeElement *, elmt);
MidLevelRenderer::MLRShape *shape=group->GetMLRShape();
for(int i=0;i<shape->GetNum();i++)
{
AddErfBranch(tmpitm,shape->Find(i));
}
}
break;
case ElementRenderer::ScreenQuadsElementClassID:
{
}
break;
case ElementRenderer::ShapeElementClassID:
{
ElementRenderer::ShapeElement *group = Cast_Pointer(ElementRenderer::ShapeElement *, elmt);
MidLevelRenderer::MLRShape *shape=group->GetMLRShape();
for(int i=0;i<shape->GetNum();i++)
{
AddErfBranch(tmpitm,shape->Find(i));
}
}
break;
case ElementRenderer::SwitchElementClassID:
{
ElementRenderer::ListElement *group = Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
AddErfBranch(tmpitm,group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::TriangleCloudElementClassID:
{
}
break;
case ElementRenderer::MultiLODElementClassID:
{
ElementRenderer::MultiLODElement *group = Cast_Pointer(ElementRenderer::MultiLODElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
AddErfBranch(tmpitm,group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::ShapeLODElementClassID:
{
ElementRenderer::ShapeLODElement *group = Cast_Pointer(ElementRenderer::ShapeLODElement *, elmt);
for(int i=0;i<group->GetSize();i++)
{
MidLevelRenderer::MLRShape *shape;
const ElementRenderer::LODElement::Entry *entry;
group->GetLOD(i,&shape,&entry);
HTREEITEM hChild = erftree->InsertItem((LPCSTR)(shape->GetClassString()), 0, 1, tmpitm, TVI_LAST);
erftree->SetItemData(hChild,(DWORD) shape);
for(int j=0;j<shape->GetNum();j++)
{
AddErfBranch(hChild,shape->Find(j));
}
}
}
break;
case ElementRenderer::TreeElementClassID:
{
ElementRenderer::TreeElement *group = Cast_Pointer(ElementRenderer::TreeElement *, elmt);
for(int i=0;i<group->GetSize();i++)
{
MidLevelRenderer::MLRShape *shape;
const ElementRenderer::TreeElement::Entry *entry;
group->GetLOD(i,&shape,&entry);
HTREEITEM hChild = erftree->InsertItem((LPCSTR)(shape->GetClassString()), 0, 1, tmpitm, TVI_LAST);
erftree->SetItemData(hChild,(DWORD) shape);
for(int j=0;j<shape->GetNum();j++)
{
AddErfBranch(hChild,shape->Find(j));
}
}
}
break;
}
}
void CMFCGosView::AddErfBranch(HTREEITEM node,MidLevelRenderer::MLRPrimitiveBase *prim)
{
HTREEITEM tmpitm;
CString strTemp;
Stuff::MString * pTempMString=NULL;
PlugOf<MString *>* pTemp = ((*(theApp.m_phashErfNameMapping))
.Find( (DWORD)(void*)prim ));
if (pTemp && (pTempMString = (pTemp->GetItem()) )!=NULL)
// if ((pTempMString = (((*(theApp.m_phashErfNameMapping)).Find((DWORD)(void*)prim))->GetItem()))!=NULL)
{
strTemp.Format("%s : %s", (LPCSTR)(*pTempMString), (LPCSTR)(prim->GetClassString()));
}
else
{
strTemp.Format("%s", (LPCSTR)(prim->GetClassString()));
}
tmpitm=erftree->InsertItem((LPCSTR)strTemp,0,1,node,TVI_LAST);
erftree->SetItemData(tmpitm,(DWORD) prim);
switch(prim->GetClassID())
{
case MidLevelRenderer::MLR_I_PMeshClassID:
{
}
break;
case MidLevelRenderer::MLR_I_C_PMeshClassID:
{
}
break;
case MidLevelRenderer::MLR_I_L_PMeshClassID:
{
}
break;
case MidLevelRenderer::MLR_I_DT_PMeshClassID:
{
}
break;
case MidLevelRenderer::MLR_I_C_DT_PMeshClassID:
{
}
break;
case MidLevelRenderer::MLR_I_L_DT_PMeshClassID:
{
}
break;
}
}
BOOL CMFCGosView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
LPNMHDR msg=(LPNMHDR )lParam;
CDocument* pDoc = GetDocument();
CMFCGosDoc *GDoc=(CMFCGosDoc *)pDoc;
//if(GDoc->UnStable) return ;
switch(msg->code)
{
case NM_DBLCLK :
{
Stuff::RegisteredClass *rcls;
rcls=(Stuff::RegisteredClass *)erftree->GetItemData(erftree->GetSelectedItem( ));
if(rcls != 0)
{
GDoc->cele=NULL;
GDoc->cmlr=NULL;
if(rcls->IsDerivedFrom(ElementRenderer::ElementClassID))
{
CEditMLRStateDlg dlg1;
ElementRenderer::Element *prim;
prim=Cast_Pointer(ElementRenderer::Element *, rcls);
GDoc->cele=prim;
ElementRenderer::StateChange *schange;
schange=prim->GetStateChange();
if(schange==NULL)
{
schange=new ElementRenderer::StateChange;
prim->AdoptStateChange(schange);
Register_Object(schange);
}
Stuff::DynamicArrayOf< MidLevelRenderer::MLRState> States(1);
States[0]=schange->GetMLRState();
dlg1.SetStates(&States);
if(dlg1.DoModal()==IDOK)
{
schange->SetMLRState(States[0]);
GDoc->SetModifiedFlag();
}
}
else
{
CEditMLRStateDlg dlg1;
if(rcls->IsDerivedFrom(MidLevelRenderer::MLRPrimitiveBaseClassID))
{
MidLevelRenderer::MLRPrimitiveBase *prim;
prim=Cast_Pointer(MidLevelRenderer::MLRPrimitiveBase *, rcls);
GDoc->cmlr=prim;
Stuff::DynamicArrayOf< MidLevelRenderer::MLRState> States(prim->GetNumPasses());
for(int i=0;i<prim->GetNumPasses();i++)
{
States[i]=prim->GetReferenceState(i);
}
dlg1.SetStates(&States);
if(dlg1.DoModal()==IDOK)
{
for(i=0;i<prim->GetNumPasses();i++)
{
prim->SetReferenceState(States[i],i);
}
GDoc->SetModifiedFlag();
}
}
else
{
// rcls is a mlrshape
MidLevelRenderer::MLRShape *shape;
shape=Cast_Pointer(MidLevelRenderer::MLRShape *, rcls);
}
}
GDoc->UpdateAllViews(this);
}
}
break;
case TVN_SELCHANGED:
if(!GDoc->UnStable)
{
drawPointsYes = false;
drawNormalsYes = false;
Stuff::RegisteredClass *rcls;
rcls=(Stuff::RegisteredClass *)erftree->GetItemData(erftree->GetSelectedItem( ));
if(rcls != 0)
{
GDoc->cmlr=NULL;
if(rcls->IsDerivedFrom(ElementRenderer::ElementClassID))
{
ElementRenderer::Element *elmt = Cast_Object(ElementRenderer::Element *, rcls);
if(GDoc->cele!=NULL)
{
// GDoc->cele->SetInvisibleBounds();
}
GDoc->cele = elmt;
// GDoc->cele->SetGreenBounds();
}
else
{
if(rcls->IsDerivedFrom(MidLevelRenderer::MLRPrimitiveBaseClassID))
{
if(GDoc->cele!=NULL)
{
// GDoc->cele->SetInvisibleBounds();
GDoc->cele=NULL;
}
MidLevelRenderer::MLRPrimitiveBase *prim;
prim=Cast_Pointer(MidLevelRenderer::MLRPrimitiveBase *, rcls);
GDoc->cmlr=prim;
//Set Point Cloud Here
Stuff::RegisteredClass *pcls;
HTREEITEM selitm=erftree->GetSelectedItem();
do
{
selitm=erftree->GetParentItem(selitm);
pcls=(Stuff::RegisteredClass *)erftree->GetItemData(selitm);
}
while(!pcls || !pcls->IsDerivedFrom(ElementRenderer::ElementClassID));
if(pcls != 0)
{
if(pcls->IsDerivedFrom(ElementRenderer::ElementClassID))
{
ElementRenderer::Element *ParElmt;
ParElmt=Cast_Pointer(ElementRenderer::Element *, pcls);
const Stuff::Point3D *points;
static int point_count;
prim->GetCoordData(&points, &point_count);
drawEffectInfo[0]->effect->SetData(
&point_count,
points,
Color_Data[0]
);
drawEffectInfo[0]->effectToWorld = &ParElmt->GetLocalToWorld();
drawPointsYes = true;
const Stuff::Vector3D *normals;
static int normal_count;
if(rcls->IsDerivedFrom(MidLevelRenderer::MLR_I_L_TMeshClassID))
{
MidLevelRenderer::MLR_I_L_TMesh *nprim=Cast_Pointer(MidLevelRenderer::MLR_I_L_TMesh *, rcls);
nprim->GetNormalData(&normals, &normal_count);
for(int i=0;i<normal_count;i++)
{
Normal_Data[2*i] = points[i];
Normal_Data[2*i+1].AddScaled(points[i], normals[i], 3.0f);
Color_Data[1][2*i+1].red = normals[i].x*0.2f + 0.2f;
Color_Data[1][2*i+1].green = normals[i].y*0.1f + 0.9f;
Color_Data[1][2*i+1].blue = normals[i].y*0.2f + 0.2f;
}
normal_count *= 2;
drawEffectInfo[1]->effect->SetData(
&normal_count,
Normal_Data,
Color_Data[1]
);
drawEffectInfo[1]->effectToWorld = &ParElmt->GetLocalToWorld();
drawNormalsYes = true;
}
}// end else rcls elementclassid
}// end of pcls !=0
}// end of rcls primitiveclassid
else
{
// rcls is an MLRShape?
if(GDoc->cele!=NULL)
{
// GDoc->cele->SetInvisibleBounds();
GDoc->cele=NULL;
}
MidLevelRenderer::MLRShape *shape;
shape=Cast_Pointer(MidLevelRenderer::MLRShape *, rcls);
}
}// end else rcls elementclassid
GDoc->UpdateAllViews(this);
} //end of rcls=!=0
}//end of ! Unstable
break;
}
return CView::OnNotify(wParam, lParam, pResult);
}
void CMFCGosView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if(erftree)
{
erftree->SetWindowPos(NULL,0,0,cx,cy,SWP_NOZORDER|SWP_NOMOVE|SWP_SHOWWINDOW);
}
// TODO: Add your message handler code here
}
void CMFCGosView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
if(lHint)
{
drawPointsYes = false;
drawNormalsYes = false;
OnInitialUpdate();
}
}
extern ElementRenderer::StateChange *Camera_State;
extern ElementRenderer::CameraElement *Camera;
extern Stuff::Point3D Camera_LookAt;
extern Stuff::YawPitchRange Camera_Direction;
void CMFCGosView::OnFileImport()
{
CFileDialog dlg1(TRUE,"mlr",NULL,NULL,"MLR Geometry(*.mlr)|*.mlr||",this);
if(dlg1.DoModal()==IDOK)
{
CString tstr(dlg1.GetPathName());
Stuff::MString erf_name((LPCSTR)tstr);
Check_Object(Stuff::FileStreamManager::Instance);
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
Stuff::FileStream * erf_file = new Stuff::FileStream(erf_name);
int mlr_version = MidLevelRenderer::ReadMLRVersion(erf_file);
OBB obb;
*erf_file >> obb;
MidLevelRenderer::MLRShape *shape;
if(mlr_version>13)
{
RegisteredClass::ClassID class_id;
*erf_file >> class_id;
switch(class_id)
{
case MidLevelRenderer::MLRShapeClassID:
shape = MLRShape::Make(erf_file, mlr_version);
break;
case MidLevelRenderer::MLRCulturShapeClassID:
shape = MLRCulturShape::Make(erf_file, mlr_version);
break;
}
}
else
{
shape = MidLevelRenderer::MLRShape::Make(
erf_file,
mlr_version
);
}
gos_PopCurrentHeap();
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement *eshape = new ElementRenderer::ShapeElement;
gos_PopCurrentHeap();
eshape->SetMLRShape(shape);
// eshape->NeedNewBounds();
// Scene->NeedMatrixSync();
eshape->m_localOBB = obb;
Unregister_Object(Scene);
delete Scene;
Stuff::FileStream * pFile;
POSITION pos = NULL;
while ((pos = theApp.m_pFileSet_List.GetHeadPosition()) != NULL)
{
pFile = theApp.m_pFileSet_List.GetHead();
delete pFile;
theApp.m_pFileSet_List.RemoveHead();
}
theApp.m_pFileSet_List.AddHead(erf_file);
m_pErf_Name_List.AddTail(new Stuff::MString((LPCSTR)erf_name));
(*(theApp.m_phashErfNameMapping)).AddValue(new Stuff::PlugOf<MString *> (m_pErf_Name_List.GetTail()), (DWORD)(void*)eshape);
Register_Object(m_pErf_Name_List.GetTail());
Scene = new ElementRenderer::GroupElement;
Register_Object(Scene);
Scene->LockBounds();
Scene->AttachChild(eshape);
eshape->SetVolumeCullMode();
//---------------
// Build a camera
//---------------
//
Camera_State = new ElementRenderer::StateChange();
Register_Object(Camera_State);
Camera_State->EnableBackfaceCulling();
Camera_State->EnableDithering();
Camera_State->EnablePerspectiveCorrection();
Camera_State->EnableZBufferWrite();
Camera_State->EnableZBufferCompare();
Camera = new ElementRenderer::CameraElement(Camera_State);
Register_Object(Camera);
Scene->AttachChild(Camera);
Camera->SetPerspective(1.0f, 1000.0f, Stuff::Pi_Over_3);
Camera->SetScene(Scene);
Camera->SetScene(Scene);
Scene->Sync();
// Camera_LookAt = eshape->m_localOBB.localToParent;
Camera_Direction.range = (eshape->m_localOBB.sphereRadius>Stuff::SMALL ? eshape->m_localOBB.sphereRadius : 10.0f) * 2.0f;
//
//-----------------------------------------------------
// Sync the matrices of the scene and load the textures
//-----------------------------------------------------
//
MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
GetDocument()->UpdateAllViews(NULL,1);
theApp.DrawScreen();
GetDocument()->UnStable=false;
}
}
void CMFCGosView::OnExpandAll()
{
if (!erftree)
return;
if (!erftree->GetRootItem())
return;
ExpandTreeData(erftree, erftree->GetRootItem(), true);
}
void CMFCGosView::ExpandTreeData(CErfDataTree * tree, HTREEITEM hItem, BOOL expand)
{
HTREEITEM hTempItem = hItem;
if (!hItem)
return;
do
{
HTREEITEM hChildItem = tree->GetNextItem(hTempItem, TVGN_CHILD);
tree->Expand(hTempItem, expand ? TVE_EXPAND : TVE_COLLAPSE );
ExpandTreeData(tree, hChildItem, expand);
} while (hTempItem = erftree->GetNextItem(hTempItem, TVGN_NEXT));
}
void CMFCGosView::OnCollapseAll()
{
if (!erftree)
return;
ExpandTreeData(erftree, erftree->GetRootItem(), false);
}