// PageTriggerContainer.cpp : implementation file // #include "stdafx.h" #include "worldcreator.h" #include "PageTriggerContainer.h" #include "resource.h" #include "DlgTriggerPoint.h" #include "DlgTriggerProperty.h" #include "MainFrm.h" #include "WorldCreatorView.h" #include #include #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif typedef unsigned char byte; ///////////////////////////////////////////////////////////////////////////// // enum eNodeType { TYPE_CATEGORY = 0, TYPE_TRIGGER = 1, TYPE_POINTS = 2, TYPE_POINT = 3, TYPE_EVENTS = 4, TYPE_EVENT = 5, }; ///////////////////////////////////////////////////////////////////////////// // struct SNodeData { union { struct { DWORD type : 4; DWORD index1 : 14; DWORD index2 : 14; }; DWORD value; }; operator DWORD() { return value; } SNodeData(); SNodeData( eNodeType Type ); SNodeData( DWORD nodeValue ); SNodeData( int eventID, const char * szArg ); SNodeData( float x, float y, float z, long objID ); void Delete(); void GetPoint( float & x, float & y, float & z, long & objID ) const; void GetEvent( int & eventID, char * szArg ) const; void SetEvent( int eventID, const char * szArg ); bool operator=( const SNodeData & rhs ) const { return value == rhs.value; } void Select() const; }; ///////////////////////////////////////////////////////////////////////////// // SNodeData::SNodeData() : type( TYPE_CATEGORY ) , index1( 0 ) , index2( 0 ) {} SNodeData::SNodeData( eNodeType Type ) : type( Type ) , index1( 0 ) , index2( 0 ) { if( type == TYPE_TRIGGER ) { CBGMController & BGMC = CBGMController::GetInstance(); index1 = BGMC.AddTrigger(); } } SNodeData::SNodeData( DWORD nodeValue ) : value( nodeValue ) {} SNodeData::SNodeData( int eventID, const char * szArg ) : type( TYPE_EVENT ) { CBGMController & BGMC = CBGMController::GetInstance(); index1 = BGMC.GetSelectTrigger(); index2 = BGMC.AddEvent( eventID, szArg ); } SNodeData::SNodeData( float x, float y, float z, long objID ) : type( TYPE_POINT ) { CBGMController & BGMC = CBGMController::GetInstance(); index1 = BGMC.GetSelectTrigger(); index2 = BGMC.AddPoint( x, y, z, objID ); } void SNodeData::Delete() { CBGMController & BGMC = CBGMController::GetInstance(); switch( type ) { case TYPE_TRIGGER : BGMC.SelectTrigger( index1 ); BGMC.DeleteTrigger(); break; case TYPE_CATEGORY : case TYPE_POINTS : case TYPE_EVENTS : break; case TYPE_POINT : BGMC.SelectPoint( index1, index2 ); BGMC.DeletePoint(); break; case TYPE_EVENT : BGMC.SelectTrigger( index1 ); BGMC.DeleteEvent( index2 ); break; } } void SNodeData::GetPoint( float & x, float & y, float & z, long & objID ) const { CBGMController & BGMC = CBGMController::GetInstance(); BGMC.SelectPoint( index1, index2 ); BGMC.GetPoint( x, y, z, objID ); } void SNodeData::GetEvent( int & eventID, char * szArg ) const { CBGMController & BGMC = CBGMController::GetInstance(); BGMC.SelectTrigger( index1 ); BGMC.GetEvent( index2, eventID, szArg ); } void SNodeData::SetEvent( int eventID, const char * szArg ) { CBGMController & BGMC = CBGMController::GetInstance(); BGMC.SelectTrigger( index1 ); BGMC.SetEvent( index2, eventID, szArg ); } void SNodeData::Select() const { CBGMController & BGMC = CBGMController::GetInstance(); if( type == TYPE_TRIGGER ) { BGMC.SelectTrigger( index1 ); } else if( type == TYPE_POINT ) { BGMC.SelectPoint( index1, index2 ); } } ///////////////////////////////////////////////////////////////////////////// // CPageTriggerContainer property page IMPLEMENT_DYNCREATE(CPageTriggerContainer, CPropertyPage) CPageTriggerContainer::CPageTriggerContainer() : CPropertyPage(CPageTriggerContainer::IDD) { //{{AFX_DATA_INIT(CPageTriggerContainer) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } CPageTriggerContainer::~CPageTriggerContainer() { } void CPageTriggerContainer::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPageTriggerContainer) DDX_Control(pDX, IDC_EDIT_EPSILON, m_editEpsilon); DDX_Control(pDX, IDC_TREE1, m_Tree); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CPageTriggerContainer, CPropertyPage) //{{AFX_MSG_MAP(CPageTriggerContainer) ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnRclickTree1) ON_COMMAND(MENU_NEWTRIGGER, OnNewtrigger) ON_COMMAND(MENU_ADDPOINT, OnAddpoint) ON_COMMAND(MENU_ADDCATEGORY, OnAddcategory) ON_COMMAND(MENU_TRIGGERPROPERTY, OnTriggerproperty) ON_COMMAND(MENU_DELETENODE, OnDeletenode) ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE1, OnEndlabeleditTree1) ON_COMMAND(MENU_LOADTRIGGER, OnLoadtrigger) ON_COMMAND(MENU_SAVETRIGGER, OnSavetrigger) ON_COMMAND(MENU_BUILDTRIGGER, OnBuildtrigger) ON_NOTIFY(TVN_BEGINDRAG, IDC_TREE1, OnBegindragTree1) ON_COMMAND(ID_ADDEVENT, OnAddevent) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPageTriggerContainer message handlers float CPageTriggerContainer::GetEpsilon() { char szEpsilon[1024]; m_editEpsilon.GetWindowText( szEpsilon, 1024 ); float epsilon; epsilon = (float)strtod( szEpsilon, NULL ); return epsilon; } int CPageTriggerContainer::GetChildCount( HTREEITEM hItem ) { if( hItem == NULL ) return 0; HTREEITEM hChild = m_Tree.GetChildItem( hItem ); int i = 0; while( hChild != NULL ) { i++; hChild = m_Tree.GetNextItem( hChild, TVGN_NEXT ); } return i; } void CPageTriggerContainer::SetPos( HTREEITEM hItem, float x, float y, float z, long objID ) { SNodeData nodeData = m_Tree.GetItemData( hItem ); CBGMController & BGMC = CBGMController::GetInstance(); if( nodeData.type == TYPE_POINT ) { nodeData.Select(); BGMC.MovePoint( x, y, z ); BGMC.SetObjID( objID ); } } void CPageTriggerContainer::GetPos( HTREEITEM hItem, float & x, float & y, float & z, long & objID ) { if( hItem == NULL ) { x = y = z = 0.0f; objID = 0; } SNodeData nodeData = m_Tree.GetItemData( hItem ); CBGMController & BGMC = CBGMController::GetInstance(); if( nodeData.type == TYPE_POINT ) { nodeData.GetPoint( x, y, z, objID ); } } void CPageTriggerContainer::OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) { CPoint point; GetCursorPos(&point); CMenu menu; menu.LoadMenu(IDR_MENU_TRIGGER); menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this); *pResult = 0; } void CPageTriggerContainer::OnNewtrigger() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected == NULL ) return; SNodeData nodeData = m_Tree.GetItemData( selected ); //¼±ÅÃµÈ ¾ÆÀÌÅÛÀÌ Á¾·ù ³ëµåÀÏ °æ¿ì¿¡¸¸... if( nodeData.type != TYPE_CATEGORY ) return; HTREEITEM added = m_Tree.InsertItem( "Æ®¸®°Å", selected ); m_Tree.Expand( selected, TVE_EXPAND ); m_Tree.SetItemData( added, SNodeData( TYPE_TRIGGER ) ); HTREEITEM vertexes = m_Tree.InsertItem( "Á¤Á¡", added, NULL ); m_Tree.SetItemData( vertexes, SNodeData( TYPE_POINTS ) ); HTREEITEM events = m_Tree.InsertItem( "À̺¥Æ®", added, NULL ); m_Tree.SetItemData( events, SNodeData( TYPE_EVENTS ) ); HTREEITEM hItem = m_Tree.InsertItem( "Á¡ #1", vertexes, NULL ); m_Tree.SetItemData( hItem, SNodeData( 0.0f, 0.0f, 0.0f, 0 ) ); hItem = m_Tree.InsertItem( "Á¡ #2", vertexes, NULL ); m_Tree.SetItemData( hItem, SNodeData( 0.0f, 0.0f, 0.0f, 0 ) ); hItem = m_Tree.InsertItem( "Á¡ #3", vertexes, NULL ); m_Tree.SetItemData( hItem, SNodeData( 0.0f, 0.0f, 0.0f, 0 ) ); hItem = m_Tree.InsertItem( "À̺¥Æ® #1", events, NULL ); m_Tree.SetItemData( hItem, SNodeData( EVENT_NONE, "" ) ); m_Tree.Expand( added, TVE_EXPAND ); } void CPageTriggerContainer::OnAddpoint() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected != NULL ) { SNodeData nodeData = m_Tree.GetItemData( selected ); if( nodeData.type == TYPE_POINTS ) { int ItemNum = GetChildCount( selected ) + 1; CString itemText; itemText.Format( "Á¡ #%d", ItemNum ); nodeData.Select(); HTREEITEM added = m_Tree.InsertItem( itemText, selected ); m_Tree.SetItemData( added, SNodeData( 0.0f, 0.0f, 0.0f, 0 ) ); m_Tree.Expand( selected, TVE_EXPAND ); } } } void CPageTriggerContainer::OnAddcategory() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected != NULL ) { SNodeData nodeData = m_Tree.GetItemData( selected ); //¼±ÅÃµÈ ¾ÆÀÌÅÛÀÌ Á¾·ù ³ëµåÀÏ °æ¿ì¿¡¸¸... if( nodeData.type == TYPE_CATEGORY ) { HTREEITEM added = m_Tree.InsertItem( "Á¾·ù", selected ); m_Tree.SetItemData( added, SNodeData( TYPE_CATEGORY ) ); m_Tree.Expand( selected, TVE_EXPAND ); } } } void CPageTriggerContainer::OnAddevent() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected != NULL ) { SNodeData nodeData = m_Tree.GetItemData( selected ); if( nodeData.type == TYPE_EVENTS ) { int ItemNum = GetChildCount( selected ) + 1; CString itemText; itemText.Format( "À̺¥Æ® #%d", ItemNum ); SNodeData parentNode = m_Tree.GetItemData( m_Tree.GetParentItem( selected ) ); assert( parentNode.type == TYPE_TRIGGER ); parentNode.Select(); HTREEITEM added = m_Tree.InsertItem( itemText, selected ); m_Tree.SetItemData( added, SNodeData( EVENT_NONE, "" ) ); m_Tree.Expand( selected, TVE_EXPAND ); } } } void CPageTriggerContainer::OnDeletenode() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected == NULL ) return; SNodeData nodeData = m_Tree.GetItemData( selected ); switch( nodeData.type ) { case TYPE_POINT : { if( GetChildCount( m_Tree.GetParentItem( selected ) ) <= 3 ) { MessageBox( "Æ®¸®°Å¸¦ ÀÌ·ç´Â Á¡µéÀÌ 3°³ ÀÌ»óÀÌ µÇ¾î¾ß ÇϹǷΠÁÖ¾îÁø ³ëµå¸¦ Áö¿ï ¼ö ¾ø½À´Ï´Ù." ); return; } float x, y, z; long objID; nodeData.GetPoint( x, y, z, objID ); CMainFrame *mf=(CMainFrame*)AfxGetApp()->m_pMainWnd; CWorldCreatorView *av=(CWorldCreatorView *)mf->GetActiveView(); av->m_SceneManager->m_MapStorage.DelMeshMap( x, y, z, objID ); m_Tree.DeleteItem( selected ); nodeData.Delete(); break; } case TYPE_POINTS : case TYPE_EVENTS : break; case TYPE_EVENT : m_Tree.DeleteItem( selected ); nodeData.Delete(); break; case TYPE_TRIGGER : { nodeData.Select(); CBGMController & BGMC = CBGMController::GetInstance(); CMainFrame *mf=(CMainFrame*)AfxGetApp()->m_pMainWnd; CWorldCreatorView *av=(CWorldCreatorView *)mf->GetActiveView(); int i = 0; float x, y, z; long objID; while( BGMC.SelectPoint( nodeData.index1, i ) ) { BGMC.GetPoint( x, y, z, objID ); av->m_SceneManager->m_MapStorage.DelMeshMap( x, y, z, objID ); i++; } nodeData.Delete(); m_Tree.DeleteItem( selected ); break; } case TYPE_CATEGORY : if( GetChildCount( selected ) == 0 ) m_Tree.DeleteItem( selected ); break; } } BOOL CPageTriggerContainer::OnInitDialog() { CPropertyPage::OnInitDialog(); HTREEITEM added = m_Tree.InsertItem( "ÀÏ¹Ý Æ®¸®°Å" ); SNodeData nodeData( TYPE_CATEGORY ); m_Tree.SetItemData( added, nodeData ); m_editEpsilon.SetWindowText( "1000.0" ); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CPageTriggerContainer::OnTriggerproperty() { HTREEITEM selected = m_Tree.GetSelectedItem(); if( selected == NULL ) return; SNodeData nodeData = m_Tree.GetItemData( selected ); switch( nodeData.type ) { case TYPE_CATEGORY : case TYPE_TRIGGER : case TYPE_POINTS : case TYPE_EVENTS : break; case TYPE_POINT : { CDlgTriggerPoint dlg; long objID; nodeData.GetPoint( dlg.m_xPos, dlg.m_yPos, dlg.m_zPos, objID ); dlg.DoModal(); break; } case TYPE_EVENT : { CDlgTriggerProperty dlg; char szArgBuf[1024]; int eventType; nodeData.GetEvent( eventType, szArgBuf ); dlg.m_strEventArg = szArgBuf; dlg.SetEventType( eventType ); if( dlg.DoModal() == IDOK ) { nodeData.SetEvent( dlg.GetEventType(), dlg.m_strEventArg ); m_Tree.SetItemData( selected, nodeData ); } break; } } } void CPageTriggerContainer::OnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult) { TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR; *pResult = 1; } void CPageTriggerContainer::OnLoadtrigger() { CBGMController & BGMC = CBGMController::GetInstance(); CFileDialog FileDlg( TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY , "Trigger Files (*.Trg)|*.trg|AllFiles (*.*)|*.*||", this ); if( FileDlg.DoModal() == IDOK ) { m_Tree.DeleteAllItems(); FILE * fp = fopen( FileDlg.GetPathName(), "rb" ); LoadAllItems( fp ); BGMC.Create( fp, true ); fclose( fp ); RenderAllObjects(); } } void CPageTriggerContainer::OnSavetrigger() { CBGMController & BGMC = CBGMController::GetInstance(); CFileDialog FileDlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT , "Trigger Files (*.trg)|*.trg|AllFiles (*.*)|*.*||", this ); if( FileDlg.DoModal() == IDOK ) { BGMC.Rebuild( GetEpsilon() ); FILE * fp = fopen( FileDlg.GetPathName(), "wb" ); SaveAllItems( fp ); BGMC.Save( fp ); fclose( fp ); } } void CPageTriggerContainer::LoadItem( HTREEITEM hItem, FILE * fp ) { if( hItem == NULL ) return; DWORD value; int textLen = 0; char szBuffer[1024]; fread( &value, sizeof( DWORD ), 1, fp ); fread( &textLen, sizeof( int ), 1, fp ); fread( szBuffer, sizeof( char ), textLen, fp ); szBuffer[ textLen ] = '\0'; m_Tree.SetItemData( hItem, value ); m_Tree.SetItemText( hItem, szBuffer ); } void CPageTriggerContainer::SaveItem( HTREEITEM hItem, FILE * fp ) { if( hItem == NULL ) return; SNodeData nodeData = m_Tree.GetItemData( hItem ); CString itemText = m_Tree.GetItemText( hItem ); int textLen = itemText.GetLength(); fwrite( &nodeData.value, sizeof( DWORD ), 1, fp ); fwrite( &textLen, sizeof( int ), 1, fp ); fwrite( (const char*)itemText, sizeof( char ), textLen, fp ); } void CPageTriggerContainer::LoadAllItems( FILE * fp ) { if( fp == NULL ) return; typedef pair QueueNode; queue ItemQueue; //¾ÆÀÌÅÛ ÇÚµé, ÀÚ½Ä °³¼ö int nChild = 0; //1. ·çÆ® ³ëµå°¡ ÀÖ´ÂÁö¸¦ Àоî¿Â´Ù. fread( &nChild, sizeof( int ), 1, fp ); //2. Àоî¿Â °ªÀÌ 0ÀÌ¸é ³¡³½´Ù. if( nChild == 0 ) return; //3. ·çÆ® ³ëµå¸¦ Ãß°¡Çϰí Àоî¿Â´Ù. HTREEITEM hItem = m_Tree.InsertItem( "" ); LoadItem( hItem, fp ); fread( &nChild, sizeof( int ), 1, fp ); //4. ·çÆ® ³ëµå¸¦ Å¥¿¡ »ðÀÔÇÑ´Ù. ItemQueue.push( QueueNode( hItem, nChild ) ); //5. ¾ÆÀÌÅÛÅ¥°¡ ºñ¾îÀÖÁö ¾ÊÀº µ¿¾È while( !ItemQueue.empty() ) { //5-1. Å¥¿¡¼­ Çϳª¸¦ »©¿Í¼­ ÇöÀç ³ëµå·Î ¼¼ÆÃÇÑ´Ù. QueueNode node = ItemQueue.front(); ItemQueue.pop(); //5-3. ÀÚ½Ä °³¼ö¸¸Å­ for( int i = 0; i < node.second; i++ ) { //5-3-1. ³ëµåÁ¤º¸¸¦ Àоî¿Í¼­ ³ëµå¸¦ Ãß°¡ÇÑ´Ù. HTREEITEM hChildItem = m_Tree.InsertItem( "", node.first ); m_Tree.SetItemData( hChildItem, 0 ); LoadItem( hChildItem, fp ); //5-2. ÀÚ½Ä °³¼ö¸¦ Àоî¿Â´Ù. fread( &nChild, sizeof( int ), 1, fp ); //5-3-2. Ãß°¡ÇÑ ³ëµå¸¦ Å¥¿¡ »ðÀÔÇÑ´Ù. ItemQueue.push( QueueNode( hChildItem, nChild ) ); } } } void CPageTriggerContainer::SaveAllItems( FILE * fp ) { if( fp == NULL ) return; queue ItemQueue; //1.·çÆ® ³ëµå¸¦ Å¥¿¡ push HTREEITEM hItem = m_Tree.GetRootItem(); int nChild = 0; if( hItem != NULL ) { nChild = 1; ItemQueue.push( hItem ); } fwrite( &nChild, sizeof( int ), 1, fp ); //2.Å¥°¡ ºñ¾îÀÖÁö ¾ÊÀº µ¿¾È while( !ItemQueue.empty() ) { //2-1.Å¥¿¡¼­ Çϳª¸¦ popÇØ¿Í¼­ ÇöÀç ³ëµå¿¡ ¼³Á¤ hItem = ItemQueue.front(); ItemQueue.pop(); //2-2.ÇöÀç ³ëµå¸¦ ÀúÀå SaveItem( hItem, fp ); //2-3.ÇöÀç ³ëµåÀÇ ÀÚ½Ä °³¼ö¸¦ ÀúÀå nChild = GetChildCount( hItem ); fwrite( &nChild, sizeof( int ), 1, fp ); //2-4.ÇöÀç ³ëµåÀÇ ÀÚ½Ä ³ëµåµéÀ» Å¥¿¡ push HTREEITEM hChild = m_Tree.GetChildItem( hItem ); while( hChild != NULL ) { ItemQueue.push( hChild ); hChild = m_Tree.GetNextItem( hChild, TVGN_NEXT ); } } } void CPageTriggerContainer::RenderAllObjects() { CBGMController & BGMC = CBGMController::GetInstance(); CMainFrame *mf=(CMainFrame*)AfxGetApp()->m_pMainWnd; CWorldCreatorView *av=(CWorldCreatorView *)mf->GetActiveView(); int nPolygon = BGMC.GetPolygonCount(); for( int i = 0; i < nPolygon; i++ ) { int nVertex = BGMC.GetVertexCount( i ); for( int j = 0; j < nVertex; j++ ) { float x, y, z; BGMC.GetVertex( i, j, x, y, z ); mf->m_MeshContainerBar.m_MeshContainerSheet->m_PageObjectContainer.AddObject(vector3( x, y, z ),"Cube.R3S"); long objID=av->m_SceneManager->m_MapStorage.m_TotalObjectSceneCount-1; BGMC.SelectPoint( i, j ); BGMC.SetObjID( objID ); CSectorScene * pSector=av->m_SceneManager->PickTerrain( x, y, z ); if( pSector ) pSector->GenerateObject(); } } } void CPageTriggerContainer::OnBuildtrigger() { CBGMController & BGMC = CBGMController::GetInstance(); BGMC.Rebuild( GetEpsilon() ); } void CPageTriggerContainer::OnBegindragTree1(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; HTREEITEM CurrentSelected = m_Tree.GetSelectedItem(); SNodeData nodeData = m_Tree.GetItemData( CurrentSelected ); if( nodeData.type == TYPE_POINT ) { CMainFrame *mf=(CMainFrame*)AfxGetApp()->m_pMainWnd; CWorldCreatorView *av=(CWorldCreatorView *)mf->GetActiveView(); av->ChangeMouseInterface(90); } *pResult = 0; } void CPageTriggerContainer::DeleteNode( unsigned index ) { HTREEITEM item = m_Tree.GetRootItem(); SNodeData node; node.type = TYPE_POINT; node.index1 = ( index & 0xfffc000 ) >> 14; node.index2 = index & 0x00003fff; HTREEITEM finded = SearchItem( item, node ); if( finded != NULL ) { m_Tree.DeleteItem( finded ); } } HTREEITEM CPageTriggerContainer::SearchItem( HTREEITEM item, DWORD nodeData ) { item = m_Tree.GetChildItem( item ); SNodeData node = nodeData; while( item != NULL ) { SNodeData tempNode = m_Tree.GetItemData( item ); if( tempNode == node ) return item; HTREEITEM hItemFinded = SearchItem( item, nodeData ); if( hItemFinded != NULL ) return hItemFinded; item = m_Tree.GetNextItem( item, TVGN_NEXT ); } return NULL; }