mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-24 19:30:26 +01:00
1533 lines
44 KiB
C++
1533 lines
44 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
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, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
// BrowseWindow.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "BrowseWindow.h"
|
|
#include <shlobj.h>
|
|
#include <Engine/Templates/Stock_CTextureData.h>
|
|
#include <Engine/Templates/Stock_CEntityClass.h>
|
|
|
|
#ifdef _DEBUG
|
|
#undef new
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
INDEX _iLastHittedItem = -1;
|
|
static CTFileName _fnRightClickedItemFileName;
|
|
static BOOL _bRightClickedIsSelected;
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBrowseWindow
|
|
|
|
CBrowseWindow::CBrowseWindow()
|
|
{
|
|
m_pDrawPort = NULL;
|
|
m_pViewPort = NULL;
|
|
|
|
m_iLastHittedItem = 0;
|
|
m_bDirectoryOpen = FALSE;
|
|
}
|
|
|
|
CBrowseWindow::~CBrowseWindow()
|
|
{
|
|
if( m_pViewPort != NULL)
|
|
{
|
|
_pGfx->DestroyWindowCanvas( m_pViewPort);
|
|
m_pViewPort = NULL;
|
|
}
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CBrowseWindow, CWnd)
|
|
//{{AFX_MSG_MAP(CBrowseWindow)
|
|
ON_WM_VSCROLL()
|
|
ON_WM_PAINT()
|
|
ON_WM_DROPFILES()
|
|
ON_WM_SIZE()
|
|
ON_COMMAND(ID_INSERT_ITEMS, OnInsertItems)
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_COMMAND(ID_DELETE_ITEMS, OnDeleteItems)
|
|
ON_COMMAND(ID_BIG_ICONS, OnBigIcons)
|
|
ON_COMMAND(ID_MEDIUM_ICONS, OnMediumIcons)
|
|
ON_COMMAND(ID_SMALL_ICONS, OnSmallIcons)
|
|
ON_COMMAND(ID_SHOW_DESCRIPTION, OnShowDescription)
|
|
ON_COMMAND(ID_SHOW_FILENAME, OnShowFilename)
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_COMMAND(ID_RECREATE_TEXTURE, OnRecreateTexture)
|
|
ON_COMMAND(ID_CREATE_AND_ADD_TEXTURE, OnCreateAndAddTexture)
|
|
ON_COMMAND(ID_SELECT_BY_TEXTURE_IN_SELECTED_SECTORS, OnSelectByTextureInSelectedSectors)
|
|
ON_COMMAND(ID_SELECT_BY_TEXTURE_IN_WORLD, OnSelectByTextureInWorld)
|
|
ON_COMMAND(ID_SELECT_FOR_DROP_MARKER, OnSelectForDropMarker)
|
|
ON_COMMAND(ID_SET_AS_CURRENT_TEXTURE, OnSetAsCurrentTexture)
|
|
ON_COMMAND(ID_CONVERT_CLASS, OnConvertClass)
|
|
ON_WM_MOUSEMOVE()
|
|
ON_COMMAND(ID_MICRO_ICONS, OnMicroIcons)
|
|
ON_COMMAND(ID_SELECT_EXCEPT_TEXTURES, OnSelectExceptTextures)
|
|
ON_COMMAND(ID_ADD_TEXTURES_FROM_WORLD, OnAddTexturesFromWorld)
|
|
ON_COMMAND(ID_SHOW_TREE_SHORTCUTS, OnShowTreeShortcuts)
|
|
ON_COMMAND(ID_EXPORT_TEXTURE, OnExportTexture)
|
|
ON_COMMAND(ID_BROWSER_CONTEXT_HELP, OnBrowserContextHelp)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBrowseWindow message handlers
|
|
BOOL CBrowseWindow::AttachToControl( CWnd *pwndParent)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
bResult = Create( NULL, NULL, WS_BORDER|WS_VISIBLE|WS_VSCROLL, CRect(0,0,10,10),
|
|
pwndParent, IDW_BROWSER);
|
|
if( bResult)
|
|
{
|
|
DragAcceptFiles();
|
|
}
|
|
SetFocus();
|
|
EnableToolTips( TRUE);
|
|
return bResult;
|
|
}
|
|
|
|
void CBrowseWindow::SetBrowserPtr( CBrowser *pBrowser)
|
|
{
|
|
m_pBrowser = pBrowser;
|
|
}
|
|
|
|
void CBrowseWindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
int iPosition = GetScrollPos(SB_VERT);
|
|
int intMin, intMax;
|
|
GetScrollRange( SB_VERT, &intMin, &intMax);
|
|
INDEX iMin = intMin;
|
|
INDEX iMax = intMax;
|
|
switch( nSBCode )
|
|
{
|
|
case SB_THUMBTRACK:
|
|
case SB_THUMBPOSITION:
|
|
{
|
|
SetScrollPos(SB_VERT, nPos);
|
|
break;
|
|
}
|
|
case SB_LINEDOWN:
|
|
{
|
|
iPosition = Clamp( iPosition+m_IconHeight, iMin, iMax);
|
|
SetScrollPos(SB_VERT, iPosition);
|
|
break;
|
|
}
|
|
case SB_PAGEDOWN:
|
|
{
|
|
iPosition = Clamp( iPosition+m_IconsInColumn*m_IconHeight, iMin, iMax);
|
|
SetScrollPos(SB_VERT, iPosition);
|
|
break;
|
|
}
|
|
case SB_LINEUP:
|
|
{
|
|
iPosition = Clamp( iPosition-m_IconHeight, iMin, iMax);
|
|
SetScrollPos(SB_VERT, iPosition);
|
|
break;
|
|
}
|
|
case SB_PAGEUP:
|
|
{
|
|
iPosition = Clamp( iPosition-m_IconsInColumn*m_IconHeight, iMin, iMax);
|
|
SetScrollPos(SB_VERT, iPosition);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
#define BOX( dp, xs, ys, w, h, color, type) \
|
|
dp->DrawLine( xs, ys, xs, ys+h, color, type); \
|
|
dp->DrawLine( xs, ys+h, xs+w, ys+h, color, type); \
|
|
dp->DrawLine( xs+w, ys+h, xs+w, ys, color, type); \
|
|
dp->DrawLine( xs+w, ys, xs, ys, color, type);
|
|
|
|
#define ICONS_TRAY_WIDTH 16
|
|
#define ICONS_TRAY_HEIGHT 16
|
|
void CBrowseWindow::OnPaint()
|
|
{
|
|
{
|
|
CPaintDC dc(this); // device context for painting (does BeginPaint()/EndPaint()!)
|
|
}
|
|
CWorldEditorApp *pApp = (CWorldEditorApp *)AfxGetApp();
|
|
PIXaabbox2D rectPict;
|
|
INDEX i;
|
|
|
|
if (m_pDrawPort==NULL || !m_pDrawPort->Lock()) {
|
|
return;
|
|
}
|
|
|
|
// To write description
|
|
m_pDrawPort->SetFont( theApp.m_pfntSystem);
|
|
m_pDrawPort->SetTextAspect( 1.0f);
|
|
|
|
// clear browsing window
|
|
m_pDrawPort->FillZBuffer( ZBUF_BACK);
|
|
m_pDrawPort->Fill( C_BLACK | CT_OPAQUE);
|
|
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if (pVTNDir==NULL) {
|
|
m_pDrawPort->Unlock();
|
|
return;
|
|
}
|
|
|
|
if(m_bDirectoryOpen)
|
|
{
|
|
INDEX iYOffset = GetScrollPos( SB_VERT);
|
|
INDEX iLineVisible = iYOffset/m_IconHeight;
|
|
PIX pixStart = iYOffset%m_IconHeight;
|
|
for( i=0; i<m_IconsVisible+m_IconsInLine; i++)
|
|
{
|
|
CVirtualTreeNode *pVTN = GetItem( i + iLineVisible*m_IconsInLine);
|
|
if( pVTN == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
PIX x = (i%m_IconsInLine) * m_IconWidth;
|
|
PIX y = (i/m_IconsInLine) * m_IconHeight - pixStart + ICONS_TRAY_HEIGHT + 1;
|
|
|
|
switch( pVTNDir->vtn_bmBrowsingMode)
|
|
{
|
|
case BM_ICONS_MICRO:
|
|
case BM_ICONS_SMALL:
|
|
case BM_ICONS_MEDIUM:
|
|
case BM_ICONS_LARGE:
|
|
{
|
|
PIX pixIconWidth = m_IconWidth;
|
|
PIX pixIconHeight = m_IconHeight;
|
|
// if we are browsing large icons, leave some space for icon text
|
|
if( pVTNDir->vtn_bmBrowsingMode == BM_ICONS_LARGE)
|
|
{
|
|
pixIconHeight -= STRING_HEIGHT;
|
|
}
|
|
// set error texture
|
|
CTextureData *ptdIcon = pApp->m_ptdError;
|
|
if( pVTN->vtn_pTextureData != NULL)
|
|
{
|
|
ptdIcon = pVTN->vtn_pTextureData;
|
|
}
|
|
// get texture width and height
|
|
PIX pixTextureWidth = ptdIcon->GetWidth();
|
|
PIX pixTextureHeight= ptdIcon->GetHeight();
|
|
// apply texture aspect ratio to icon
|
|
if( pixTextureWidth>pixTextureHeight)
|
|
{
|
|
pixIconHeight /= pixTextureWidth/pixTextureHeight;
|
|
}
|
|
else
|
|
{
|
|
pixIconWidth /= pixTextureHeight/pixTextureWidth;
|
|
}
|
|
|
|
// if we have large icons
|
|
if( pVTNDir->vtn_bmBrowsingMode == BM_ICONS_LARGE)
|
|
{
|
|
// rectangle for texture polygon is smaller because of subtitling info text
|
|
rectPict = PIXaabbox2D(
|
|
PIX2D(x+m_IconWidth/2-pixIconWidth/2+1, y+m_IconHeight/2-pixIconHeight/2+1),
|
|
PIX2D(x+m_IconWidth/2+pixIconWidth/2-2, y+m_IconHeight/2+pixIconHeight/2-2-STRING_HEIGHT));
|
|
}
|
|
else
|
|
{
|
|
// texture box covers maximum space
|
|
rectPict = PIXaabbox2D(
|
|
PIX2D(x+m_IconWidth/2-pixIconWidth/2+1, y+m_IconHeight/2-pixIconHeight/2+1),
|
|
PIX2D(x+m_IconWidth/2+pixIconWidth/2-2, y+m_IconHeight/2+pixIconHeight/2-2));
|
|
}
|
|
|
|
// draw icon
|
|
CTextureObject toIcon;
|
|
toIcon.SetData( ptdIcon);
|
|
m_pDrawPort->PutTexture( &toIcon, rectPict);
|
|
|
|
// if we have large icons
|
|
if( pVTNDir->vtn_bmBrowsingMode == BM_ICONS_LARGE)
|
|
{
|
|
// type info text
|
|
if( pVTN->vtn_fnItem.FileExt() == ".tex")
|
|
{
|
|
m_pDrawPort->PutText( pVTN->vtn_fnItem.FileName(), x, y + m_IconHeight-2-STRING_HEIGHT);
|
|
}
|
|
else
|
|
{
|
|
m_pDrawPort->PutText( pVTN->vtn_strName, x, y + m_IconHeight-2-STRING_HEIGHT);
|
|
}
|
|
}
|
|
|
|
if( pVTN->vtn_bSelected)
|
|
{
|
|
BOX( m_pDrawPort, x, y, m_IconWidth-1, m_IconHeight-1, C_WHITE|CT_OPAQUE, _FULL_);
|
|
BOX( m_pDrawPort, x, y, m_IconWidth-1, m_IconHeight-1, C_lRED|CT_OPAQUE, _POINT_);
|
|
}
|
|
break;
|
|
}
|
|
case BM_DESCRIPTION:
|
|
case BM_FILENAME:
|
|
{
|
|
// First paint little icon
|
|
rectPict = PIXaabbox2D( PIX2D(x, y), PIX2D(x+STRING_HEIGHT, y+STRING_HEIGHT));
|
|
if( pVTN->vtn_pTextureData != NULL)
|
|
{
|
|
CTextureObject toIcon;
|
|
toIcon.SetData( pVTN->vtn_pTextureData);
|
|
m_pDrawPort->PutTexture( &toIcon, rectPict);
|
|
}
|
|
else
|
|
{
|
|
m_pDrawPort->PutTexture( pApp->m_ptoError, rectPict);
|
|
}
|
|
// if we are using descriptive name
|
|
if( pVTNDir->vtn_bmBrowsingMode == BM_DESCRIPTION)
|
|
{
|
|
if( pVTN->vtn_fnItem.FileExt() == ".tex")
|
|
{
|
|
m_pDrawPort->PutText( pVTN->vtn_fnItem.FileName(), x + STRING_HEIGHT, y);
|
|
}
|
|
else
|
|
{
|
|
m_pDrawPort->PutText( pVTN->vtn_strName, x + STRING_HEIGHT, y);
|
|
}
|
|
}
|
|
// if we are using file name
|
|
else
|
|
{
|
|
m_pDrawPort->PutText( pVTN->vtn_fnItem, x + STRING_HEIGHT, y);
|
|
}
|
|
|
|
if( pVTN->vtn_bSelected)
|
|
{
|
|
BOX( m_pDrawPort, x, y, m_IconWidth-1, m_IconHeight-1, C_WHITE|CT_OPAQUE, _FULL_);
|
|
BOX( m_pDrawPort, x, y, m_IconWidth-1, m_IconHeight-1, C_lRED|CT_OPAQUE, _POINT_);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ASSERTALWAYS( "Unrecognizible browsing type found !");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// draw icons tray
|
|
CTextureObject to;
|
|
to.SetData(theApp.m_ptdIconsTray);
|
|
INDEX iSelected=0;
|
|
switch( pVTNDir->vtn_bmBrowsingMode)
|
|
{
|
|
case BM_ICONS_MICRO: iSelected = 0; break;
|
|
case BM_ICONS_SMALL: iSelected = 1; break;
|
|
case BM_ICONS_MEDIUM: iSelected = 2; break;
|
|
case BM_ICONS_LARGE: iSelected = 3; break;
|
|
case BM_DESCRIPTION: iSelected = 4; break;
|
|
case BM_FILENAME: iSelected = 5; break;
|
|
}
|
|
|
|
FLOAT fRatio = theApp.m_ptdIconsTray->GetWidth()/theApp.m_ptdIconsTray->GetPixWidth();
|
|
MEX2D mex2dStart = MEX2D(0, MEX(iSelected*16*fRatio));
|
|
MEX2D mex2dEnd = MEX2D(MEX(16*8*fRatio), MEX((iSelected*16+16)*fRatio));
|
|
MEXaabbox2D boxTexture = MEXaabbox2D( mex2dStart, mex2dEnd);
|
|
PIXaabbox2D boxScreen = PIXaabbox2D( PIX2D(0, 0), PIX2D(8*16, 16));
|
|
m_pDrawPort->Fill( 0, 0, m_pDrawPort->GetWidth(), 17, C_BLACK|CT_OPAQUE);
|
|
m_pDrawPort->PutTexture( &to, boxScreen, boxTexture);
|
|
|
|
m_pDrawPort->Unlock();
|
|
m_pViewPort->SwapBuffers();
|
|
}
|
|
|
|
void CBrowseWindow::OnContextMenu( CPoint point)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
AfxMessageBox( L"Virtual tree doesn't yet exists. Create at least one virtual directory "
|
|
L"to be able to insert items into it.");
|
|
return;
|
|
}
|
|
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
|
|
// convert coordinates from screen to client
|
|
CPoint ptClientCoordinates = point;
|
|
ScreenToClient( &ptClientCoordinates);
|
|
|
|
// Add hit icon to selection
|
|
FLOAT fDummyX, fDummyY;
|
|
INDEX iHittedItem = HitItem( ptClientCoordinates, fDummyX, fDummyY);
|
|
_fnRightClickedItemFileName = CTString("");
|
|
if( iHittedItem != -1)
|
|
{
|
|
CVirtualTreeNode *pVTN = GetItem( iHittedItem);
|
|
ASSERT( pVTN != NULL);
|
|
_fnRightClickedItemFileName = pVTN->vtn_fnItem;
|
|
_bRightClickedIsSelected = pVTN->vtn_bSelected;
|
|
}
|
|
|
|
CMenu menu;
|
|
if( menu.LoadMenu(IDR_BROWSERPOPUP))
|
|
{
|
|
CMenu* pPopup = menu.GetSubMenu(0);
|
|
UINT iRecreateTextureCommandState = MF_DISABLED|MF_GRAYED;
|
|
if( _fnRightClickedItemFileName.FileExt()==CTString(".tex") ||
|
|
_fnRightClickedItemFileName.FileExt()==CTString(".tbn") )
|
|
{
|
|
iRecreateTextureCommandState = MF_ENABLED;
|
|
}
|
|
// enable recreate texture and set as current texture commands if texture right-clicked
|
|
pPopup->EnableMenuItem(ID_RECREATE_TEXTURE, iRecreateTextureCommandState);
|
|
pPopup->EnableMenuItem(ID_SET_AS_CURRENT_TEXTURE, iRecreateTextureCommandState);
|
|
pPopup->EnableMenuItem(ID_EXPORT_TEXTURE, iRecreateTextureCommandState);
|
|
|
|
UINT iSelectForDropMarkerCommandState = MF_DISABLED|MF_GRAYED;
|
|
if( _fnRightClickedItemFileName.FileExt()==CTString(".ecl"))
|
|
{
|
|
iSelectForDropMarkerCommandState = MF_ENABLED;
|
|
}
|
|
// enable recreate texture command if texture right-clicked
|
|
pPopup->EnableMenuItem(ID_SELECT_FOR_DROP_MARKER, iSelectForDropMarkerCommandState);
|
|
if( pDoc == NULL)
|
|
{
|
|
pPopup->EnableMenuItem(ID_ADD_TEXTURES_FROM_WORLD, MF_DISABLED|MF_GRAYED);
|
|
pPopup->EnableMenuItem(ID_SELECT_EXCEPT_TEXTURES, MF_DISABLED|MF_GRAYED);
|
|
}
|
|
|
|
// enable select by texture commands only if texture is right-clicked and document exists
|
|
UINT iSelectByTextureCommandState = MF_DISABLED|MF_GRAYED;
|
|
if( (_fnRightClickedItemFileName.FileExt()==CTString(".tex")) && (pDoc!=NULL))
|
|
{
|
|
iSelectByTextureCommandState = MF_ENABLED;
|
|
}
|
|
|
|
UINT iConvertClassCommandState = MF_DISABLED|MF_GRAYED;
|
|
if( (_fnRightClickedItemFileName.FileExt()==CTString(".ecl")) &&
|
|
(pDoc!=NULL) &&
|
|
(pDoc->m_selEntitySelection.Count() != 0) &&
|
|
(pDoc->m_iMode == ENTITY_MODE) )
|
|
{
|
|
iConvertClassCommandState = MF_ENABLED;
|
|
}
|
|
pPopup->EnableMenuItem(ID_SELECT_BY_TEXTURE_IN_SELECTED_SECTORS, iSelectByTextureCommandState);
|
|
pPopup->EnableMenuItem(ID_SELECT_BY_TEXTURE_IN_WORLD, iSelectByTextureCommandState);
|
|
pPopup->EnableMenuItem(ID_CONVERT_CLASS, iConvertClassCommandState);
|
|
|
|
UINT iClassHelp = MF_DISABLED|MF_GRAYED;
|
|
if( _fnRightClickedItemFileName.FileExt()==CTString(".ecl"))
|
|
{
|
|
iClassHelp = MF_ENABLED;
|
|
}
|
|
pPopup->EnableMenuItem(ID_BROWSER_CONTEXT_HELP, iClassHelp);
|
|
|
|
pPopup->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
|
|
point.x, point.y, this);
|
|
}
|
|
}
|
|
|
|
INDEX CBrowseWindow::HitItem( CPoint point, FLOAT &fHitXOffset, FLOAT &fHitYOffset) const
|
|
{
|
|
PIXaabbox2D rectItem;
|
|
PIXaabbox2D boxPoint;
|
|
INDEX i;
|
|
INDEX iYOffset = GetScrollPos( SB_VERT);
|
|
INDEX iLineVisible = iYOffset/m_IconHeight;
|
|
PIX pixStart = iYOffset%m_IconHeight;
|
|
for( i=0; i<m_IconsVisible; i++)
|
|
{
|
|
CVirtualTreeNode *pVTN = GetItem( i + iLineVisible*m_IconsInLine);
|
|
if( pVTN == NULL)
|
|
{
|
|
break;
|
|
}
|
|
PIX x = i%m_IconsInLine * m_IconWidth;
|
|
PIX y = i/m_IconsInLine * m_IconHeight - pixStart + ICONS_TRAY_HEIGHT + 1;
|
|
rectItem = PIXaabbox2D( PIX2D(x, y), PIX2D(x+m_IconWidth, y+m_IconHeight));
|
|
boxPoint = PIXaabbox2D( PIX2D(point.x, point.y) );
|
|
if( (rectItem & boxPoint) == boxPoint)
|
|
{
|
|
fHitXOffset = FLOAT((point.x-x))/m_IconWidth;
|
|
fHitYOffset = FLOAT((point.y-y))/m_IconHeight;
|
|
return (i + iLineVisible*m_IconsInLine);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
HGLOBAL CreateHDrop( const CTFileName &fnToDrag, BOOL bAddAppPath/*=TRUE*/)
|
|
{
|
|
CTFileName fnFullToDrag;
|
|
if( bAddAppPath)
|
|
{
|
|
fnFullToDrag = _fnmApplicationPath + fnToDrag;
|
|
}
|
|
else
|
|
{
|
|
fnFullToDrag = fnToDrag;
|
|
}
|
|
|
|
HGLOBAL hGlobal;
|
|
// allocate space for DROPFILE structure plus the number of file and one extra byte for final NULL terminator
|
|
hGlobal = GlobalAlloc(GHND|GMEM_SHARE,(DWORD) (sizeof(DROPFILES)+strlen(fnFullToDrag)+2));
|
|
if(hGlobal == NULL)
|
|
return hGlobal;
|
|
|
|
LPDROPFILES pDropFiles;
|
|
char *pchDropFileName;
|
|
pDropFiles = (LPDROPFILES)GlobalLock(hGlobal);
|
|
pchDropFileName = ((char *)pDropFiles)+sizeof(DROPFILES);
|
|
// set the offset where the starting point of the file start
|
|
pDropFiles->pFiles = sizeof(DROPFILES);
|
|
// filename does not contain wide characters
|
|
pDropFiles->fWide = FALSE;
|
|
// we want drop point's coordinates in client area
|
|
pDropFiles->fNC = FALSE;
|
|
|
|
strcpy(pchDropFileName, (const char *)fnFullToDrag);
|
|
// final null terminator as per CF_HDROP Format specs.
|
|
pchDropFileName[strlen(pchDropFileName)+1]=0;
|
|
GlobalUnlock(hGlobal);
|
|
return hGlobal;
|
|
}
|
|
|
|
|
|
void CBrowseWindow::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL) return;
|
|
|
|
// if we hitted icons tray
|
|
if( (point.x < ICONS_TRAY_WIDTH*6) && (point.y < (ICONS_TRAY_HEIGHT + 1)) )
|
|
{
|
|
INDEX iSelected = point.x/ICONS_TRAY_WIDTH;
|
|
switch( iSelected)
|
|
{
|
|
case 0: pVTNDir->vtn_bmBrowsingMode = BM_ICONS_MICRO; break;
|
|
case 1: pVTNDir->vtn_bmBrowsingMode = BM_ICONS_SMALL; break;
|
|
case 2: pVTNDir->vtn_bmBrowsingMode = BM_ICONS_MEDIUM; break;
|
|
case 3: pVTNDir->vtn_bmBrowsingMode = BM_ICONS_LARGE; break;
|
|
case 4: pVTNDir->vtn_bmBrowsingMode = BM_DESCRIPTION; break;
|
|
case 5: pVTNDir->vtn_bmBrowsingMode = BM_FILENAME; break;
|
|
}
|
|
Refresh();
|
|
return;
|
|
}
|
|
|
|
// toggle hitted icon selection status
|
|
FLOAT fDummyX, fDummyY;
|
|
INDEX iHittedItem = HitItem( point, fDummyX, fDummyY);
|
|
if( iHittedItem == -1) return;
|
|
|
|
BOOL bShift = (nFlags & MK_SHIFT);
|
|
BOOL bCtrl = (nFlags & MK_CONTROL);
|
|
|
|
if( !bCtrl)
|
|
{
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
it->vtn_bSelected = FALSE;
|
|
}
|
|
}
|
|
|
|
INDEX ctItems = 0;
|
|
{FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( !it->vtn_bIsDirectory) ctItems++;
|
|
}}
|
|
|
|
INDEX iMin = iHittedItem;
|
|
INDEX iMax = iHittedItem;
|
|
if( bShift)
|
|
{
|
|
iMin = ClampDn( Min( m_iLastHittedItem, iHittedItem), (INDEX)0);
|
|
iMax = ClampUp( Max( m_iLastHittedItem, iHittedItem), ctItems);
|
|
}
|
|
|
|
INDEX iCurrent = 0;
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
CVirtualTreeNode &vtn = *it;
|
|
if( !vtn.vtn_bIsDirectory)
|
|
{
|
|
if( (iCurrent >= iMin) && (iCurrent <= iMax) )
|
|
{
|
|
if( bCtrl&&!bShift)
|
|
{
|
|
vtn.vtn_bSelected = !vtn.vtn_bSelected;
|
|
}
|
|
else
|
|
{
|
|
vtn.vtn_bSelected = TRUE;
|
|
}
|
|
}
|
|
iCurrent++;
|
|
}
|
|
}
|
|
if( !bShift) m_iLastHittedItem = iHittedItem;
|
|
|
|
CVirtualTreeNode *pVTNHit = GetItem( iHittedItem);
|
|
HGLOBAL hglobal = CreateHDrop( pVTNHit->vtn_fnItem);
|
|
m_DataSource.CacheGlobalData( CF_HDROP, hglobal);
|
|
m_DataSource.DoDragDrop( DROPEFFECT_COPY);
|
|
Invalidate( FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::OnDropFiles(HDROP hDropInfo)
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
INDEX iNoOfFiles = DragQueryFile( hDropInfo, 0xFFFFFFFF, NULL, 0);
|
|
char chrFile[ 256];
|
|
|
|
// get dropped coordinates
|
|
CPoint point;
|
|
DragQueryPoint( hDropInfo, &point);
|
|
|
|
CVirtualTreeNode *pVTN = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTN != NULL)
|
|
{
|
|
CloseDirectory( pVTN);
|
|
for( INDEX i=0; i<iNoOfFiles; i++)
|
|
{
|
|
DragQueryFileA( hDropInfo, i, chrFile, 256);
|
|
CTFileName fnDroped = CTString(chrFile);
|
|
if( fnDroped != CTString("") )
|
|
{
|
|
try
|
|
{
|
|
fnDroped.RemoveApplicationPath_t();
|
|
InsertItem( fnDroped, point);
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
AfxMessageBox( CString(err_str));
|
|
}
|
|
}
|
|
}
|
|
OpenDirectory( pVTN);
|
|
}
|
|
else
|
|
{
|
|
AfxMessageBox( L"ERROR: Virtual tree doesn't exist.");
|
|
}
|
|
CWnd::OnDropFiles(hDropInfo);
|
|
}
|
|
|
|
CVirtualTreeNode *CBrowseWindow::GetItem( INDEX iItem) const
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
INDEX ct=0;
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
//
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
if( ct == iItem)
|
|
{
|
|
return( &it.Current());
|
|
}
|
|
ct++;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
INDEX CBrowseWindow::GetItemNo( CVirtualTreeNode *pVTN)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
if( pVTNDir->vtn_lhChildren.IsEmpty())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
INDEX ct=0;
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
if( &it.Current() == pVTN)
|
|
{
|
|
return( ct);
|
|
}
|
|
ct++;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void CBrowseWindow::InsertItem( CTFileName fnItem, CPoint pt)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FLOAT fHitXRatio;
|
|
FLOAT fHitYRatio;
|
|
INDEX iHittedItem = HitItem( pt, fHitXRatio, fHitYRatio);
|
|
CVirtualTreeNode *pVTNHit = NULL;
|
|
if( iHittedItem != -1)
|
|
{
|
|
pVTNHit = GetItem( iHittedItem);
|
|
}
|
|
|
|
CVirtualTreeNode *pvtnToRemove = NULL;
|
|
// check for all items in current virtual tree directory
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
// if it isn't directory means that it is item
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
// don't allow inserting same item twice
|
|
if( it->vtn_fnItem == fnItem)
|
|
{
|
|
if( pt.x == -1) return;
|
|
pvtnToRemove = &it.Current();
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (pVTNHit == pvtnToRemove) && (pVTNHit != NULL) ) return;
|
|
if( pvtnToRemove != NULL)
|
|
{
|
|
pvtnToRemove->vtn_lnInDirectory.Remove();
|
|
if( pvtnToRemove->vtn_pTextureData != NULL)
|
|
{
|
|
_pTextureStock->Release( pvtnToRemove->vtn_pTextureData);
|
|
}
|
|
delete pvtnToRemove;
|
|
}
|
|
|
|
// if item is texture
|
|
if( fnItem.FileExt() == ".tex")
|
|
{
|
|
CTextureData *ptdTexture;
|
|
// try to
|
|
try
|
|
{
|
|
// obtain texture
|
|
ptdTexture = _pTextureStock->Obtain_t( fnItem);
|
|
}
|
|
// catch and
|
|
catch( char *err_str)
|
|
{
|
|
// report errors
|
|
AfxMessageBox( CString(err_str));
|
|
return;
|
|
}
|
|
// now it must be valid
|
|
ASSERT( ptdTexture != NULL);
|
|
// get texture dimensions
|
|
MEX mexWidth = ptdTexture->GetWidth();
|
|
MEX mexHeight = ptdTexture->GetHeight();
|
|
// release texture, we don't need it any more
|
|
_pTextureStock->Release( ptdTexture);
|
|
// mark both dimensions as incorrect
|
|
BOOL bWidthOk = FALSE;
|
|
BOOL bHeightOk = FALSE;
|
|
// see if both width and height are potentions of 2
|
|
for( INDEX i=0; i<32; i++)
|
|
{
|
|
// check width, mark if correct
|
|
if( (1L << i) == mexWidth) bWidthOk = TRUE;
|
|
if( (1L << i) == mexHeight) bHeightOk = TRUE;
|
|
}
|
|
// if width or height are not potentios of 2
|
|
if( !bWidthOk || !bHeightOk)
|
|
{
|
|
char err_str[ 256];
|
|
sprintf( err_str, "Dropped texture \"%s\" has incorrect dimensions %.2f x %.2f."
|
|
"All textures must have dimensions that are potentions of 2.",
|
|
(CTString&)fnItem, METERS_MEX( mexWidth), METERS_MEX( mexHeight));
|
|
AfxMessageBox( CString(err_str));
|
|
return;
|
|
}
|
|
}
|
|
else if( fnItem.FileExt() == ".ecl")
|
|
{
|
|
// obtain class
|
|
CEntityClass *pec = _pEntityClassStock->Obtain_t( fnItem);
|
|
// get thumbnail file name from the class
|
|
CTFileName fnThumbnail = CTString(pec->ec_pdecDLLClass->dec_strIconFileName);
|
|
// release class
|
|
_pEntityClassStock->Release( pec);
|
|
// if thumbnail's name is "", don't add this item
|
|
if( fnThumbnail == CTString("") )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CVirtualTreeNode *pVTN = new CVirtualTreeNode;
|
|
pVTN->vtn_fnItem = fnItem;
|
|
pVTN->vtn_bIsDirectory = FALSE;
|
|
|
|
pVTN->vtn_strName = fnItem.FileName();
|
|
if( pVTNDir->vtn_lhChildren.Count() == 0)
|
|
{
|
|
pVTN->vtn_bSelected = TRUE;
|
|
}
|
|
if( pt.x == -1)
|
|
{
|
|
pVTNDir->vtn_lhChildren.AddTail( pVTN->vtn_lnInDirectory);
|
|
}
|
|
else
|
|
{
|
|
if( iHittedItem == -1)
|
|
{
|
|
pVTNDir->vtn_lhChildren.AddTail( pVTN->vtn_lnInDirectory);
|
|
}
|
|
else if( ((m_IconsInLine != 1) && (fHitXRatio < 0.5f)) ||
|
|
((m_IconsInLine == 1) && (fHitYRatio < 0.5f)) )
|
|
{
|
|
ASSERT( pVTNHit != NULL);
|
|
pVTNHit->vtn_lnInDirectory.AddBefore( pVTN->vtn_lnInDirectory);
|
|
}
|
|
else
|
|
{
|
|
ASSERT( pVTNHit != NULL);
|
|
pVTNHit->vtn_lnInDirectory.AddAfter( pVTN->vtn_lnInDirectory);
|
|
}
|
|
}
|
|
|
|
m_pBrowser->m_bVirtualTreeChanged = TRUE;
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::DeleteSelectedItems()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FORDELETELIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
if( it->vtn_bSelected)
|
|
{
|
|
it->vtn_lnInDirectory.Remove();
|
|
if( it->vtn_pTextureData != NULL)
|
|
{
|
|
_pTextureStock->Release( it->vtn_pTextureData);
|
|
}
|
|
delete &it.Current();
|
|
}
|
|
}
|
|
}
|
|
m_pBrowser->m_bVirtualTreeChanged = TRUE;
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::Refresh(void)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( (pVTNDir == NULL) || (!m_bDirectoryOpen) )
|
|
{
|
|
return;
|
|
}
|
|
switch( pVTNDir->vtn_bmBrowsingMode)
|
|
{
|
|
case BM_ICONS_MICRO:
|
|
{
|
|
m_IconWidth = 16;
|
|
m_IconHeight = 16;
|
|
break;
|
|
}
|
|
case BM_ICONS_SMALL:
|
|
{
|
|
m_IconWidth = 32;
|
|
m_IconHeight = 32;
|
|
break;
|
|
}
|
|
case BM_ICONS_MEDIUM:
|
|
{
|
|
m_IconWidth = 64;
|
|
m_IconHeight = 64;
|
|
break;
|
|
}
|
|
case BM_ICONS_LARGE:
|
|
{
|
|
m_IconWidth = 128;
|
|
// allow some space for text
|
|
m_IconHeight = 128 + STRING_HEIGHT;
|
|
break;
|
|
}
|
|
case BM_DESCRIPTION:
|
|
case BM_FILENAME:
|
|
{
|
|
m_IconWidth = m_BrowseWndWidth - 8;
|
|
m_IconHeight = STRING_HEIGHT;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ASSERTALWAYS( "Unrecognizible browsing type found !");
|
|
}
|
|
}
|
|
m_IconsInLine = m_BrowseWndWidth/m_IconWidth;
|
|
if( m_IconsInLine == 0)
|
|
{
|
|
m_IconsInLine = 1;
|
|
}
|
|
m_IconsInColumn = m_BrowseWndHeight/m_IconHeight + 1;
|
|
m_IconsVisible = m_IconsInLine * m_IconsInColumn;
|
|
|
|
INDEX iItemsCt = -1;
|
|
if( !pVTNDir->vtn_lhChildren.IsEmpty())
|
|
{
|
|
iItemsCt = GetItemNo( LIST_TAIL( pVTNDir->vtn_lhChildren,
|
|
CVirtualTreeNode, vtn_lnInDirectory) );
|
|
}
|
|
INDEX ctLines = iItemsCt/m_IconsInLine;
|
|
SetScrollRange( SB_VERT, 0, ctLines*m_IconHeight);
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::OpenDirectory( CVirtualTreeNode *pVTNDir)
|
|
{
|
|
CWorldEditorApp *pApp = (CWorldEditorApp *)AfxGetApp();
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
|
|
if(m_bDirectoryOpen || pVTNDir==NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ASSERT( pVTNDir != NULL);
|
|
// remember name of last opened virtual tree
|
|
theApp.m_strOpenedVTDirectory = theApp.GetNameForVirtualTreeNode( pVTNDir);
|
|
wchar_t achrOpenedDirectoryMessage[ 256];
|
|
swprintf( achrOpenedDirectoryMessage, L"Opened directory: \"%s\"",
|
|
CString(theApp.m_strOpenedVTDirectory));
|
|
// put selected directory name into status line
|
|
pMainFrame->m_wndStatusBar.SetPaneText( STATUS_LINE_PANE, achrOpenedDirectoryMessage, TRUE);
|
|
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
try
|
|
{
|
|
// if not directory
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
CTFileName fnThumbnail; // thumbnail's file name
|
|
// if texture
|
|
if( it->vtn_fnItem.FileExt() == ".tex")
|
|
{
|
|
// use same texture for thumbnail
|
|
fnThumbnail = it->vtn_fnItem;
|
|
}
|
|
// if world
|
|
else if ( it->vtn_fnItem.FileExt() == ".wld")
|
|
{
|
|
// use file name with extension .tbn for thumbnail
|
|
fnThumbnail = it->vtn_fnItem.FileDir() + it->vtn_fnItem.FileName() + ".tbn";
|
|
// use base name for description
|
|
it->vtn_strName = it->vtn_fnItem.FileName();
|
|
}
|
|
// if class
|
|
else if ( it->vtn_fnItem.FileExt() == ".ecl")
|
|
{
|
|
// obtain class
|
|
CEntityClass *pec = _pEntityClassStock->Obtain_t( it->vtn_fnItem);
|
|
// get thumbnail file name from the class
|
|
fnThumbnail = CTString(pec->ec_pdecDLLClass->dec_strIconFileName);
|
|
// get description name from the class
|
|
it->vtn_strName = pec->ec_pdecDLLClass->dec_strName;
|
|
// release class
|
|
_pEntityClassStock->Release( pec);
|
|
}
|
|
// if unknown extension
|
|
else
|
|
{
|
|
// use no thumbnail
|
|
fnThumbnail = CTString("");
|
|
}
|
|
|
|
// if no thumbnail
|
|
if( fnThumbnail == "")
|
|
{
|
|
it->vtn_pTextureData = NULL;
|
|
}
|
|
// if there is valid thumbnail file name
|
|
else
|
|
{
|
|
// obtain thumbnail
|
|
it->vtn_pTextureData = _pTextureStock->Obtain_t( fnThumbnail);
|
|
// must be valid
|
|
ASSERT( it->vtn_pTextureData != NULL);
|
|
// if it is really texture, type full info
|
|
if( it->vtn_fnItem.FileExt() == ".tex")
|
|
{
|
|
// use base name and dimension for desription
|
|
it->vtn_strName = (CTString&)it->vtn_fnItem+" "+it->vtn_pTextureData->GetDescription();
|
|
}
|
|
// else description is just item's file name
|
|
else
|
|
{
|
|
it->vtn_strName = it->vtn_fnItem.FileName();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch( char *error)
|
|
{
|
|
// ingnore errors
|
|
(void) error;
|
|
it->vtn_pTextureData = NULL;
|
|
}
|
|
}
|
|
|
|
SetScrollPos(SB_VERT, 0);
|
|
m_bDirectoryOpen = TRUE;
|
|
Refresh();
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::CloseDirectory( CVirtualTreeNode *pVTN)
|
|
{
|
|
if( !m_bDirectoryOpen)
|
|
{
|
|
return;
|
|
}
|
|
ASSERT( pVTN != NULL);
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTN->vtn_lhChildren, it)
|
|
{
|
|
if( !it->vtn_bIsDirectory)
|
|
{
|
|
if( it->vtn_pTextureData != NULL)
|
|
{
|
|
_pTextureStock->Release( it->vtn_pTextureData);
|
|
it->vtn_pTextureData = NULL;
|
|
}
|
|
}
|
|
}
|
|
m_bDirectoryOpen = FALSE;
|
|
}
|
|
|
|
void CBrowseWindow::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CWnd::OnSize(nType, cx, cy);
|
|
|
|
// if window canvas is valid
|
|
if( m_pViewPort!=NULL)
|
|
{
|
|
// resize it
|
|
m_pViewPort->Resize();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void CBrowseWindow::OnInsertItems()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir == NULL)
|
|
{
|
|
AfxMessageBox( L"ERROR: Virtual tree doesn't exist.");
|
|
return;
|
|
}
|
|
|
|
char *pFilters = "Items (*.tex, *.wld, *.ecl)\0*.tex;*.wld;*.ecl\0"
|
|
"World Files (*.wld)\0*.wld\0"
|
|
"Texture files (*.tex)\0*.tex\0"
|
|
"Class files (*.ecl)\0*.ecl\0"
|
|
"All files (*.*)\0*.*\0\0";
|
|
// call file requester for opening textures
|
|
CDynamicArray<CTFileName> afnItems;
|
|
_EngineGUI.FileRequester( "Insert items", pFilters, KEY_NAME_CREATE_TEXTURE_DIR,
|
|
"Textures\\", "", &afnItems);
|
|
if( afnItems.Count() == 0) return;
|
|
|
|
// insert items
|
|
FOREACHINDYNAMICARRAY( afnItems, CTFileName, itItem)
|
|
{
|
|
try
|
|
{
|
|
InsertItem( *itItem, CPoint(-1, -1));
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
AfxMessageBox( CString(err_str));
|
|
}
|
|
}
|
|
CloseDirectory( pVTNDir);
|
|
OpenDirectory( pVTNDir);
|
|
}
|
|
|
|
void CBrowseWindow::OnDeleteItems()
|
|
{
|
|
DeleteSelectedItems();
|
|
}
|
|
|
|
void CBrowseWindow::OnBigIcons()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_ICONS_LARGE;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnMediumIcons()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_ICONS_MEDIUM;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnMicroIcons()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_ICONS_MICRO;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnSmallIcons()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_ICONS_SMALL;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnShowDescription()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_DESCRIPTION;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnShowFilename()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
pVTNDir->vtn_bmBrowsingMode = BM_FILENAME;
|
|
Refresh();
|
|
}
|
|
|
|
void CBrowseWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
// get hitted item's index
|
|
FLOAT fDummyX, fDummyY;
|
|
INDEX iHittedItem = HitItem( point, fDummyX, fDummyY);
|
|
// if hit none reported, return
|
|
if( iHittedItem == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get item object from hitted index
|
|
CVirtualTreeNode *pVTN = GetItem( iHittedItem);
|
|
// must not be null
|
|
ASSERT( pVTN != NULL);
|
|
// get item's file name
|
|
CTFileName fnItem = pVTN->vtn_fnItem;
|
|
// if it is texture
|
|
if( fnItem.FileExt() == ".tex")
|
|
{
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL && pDoc->GetEditingMode()==TERRAIN_MODE)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer();
|
|
CTerrain *ptTerrain=GetTerrain();
|
|
if(ptlLayer!=NULL && ptTerrain!=NULL)
|
|
{
|
|
try
|
|
{
|
|
ptlLayer->SetLayerTexture_t(fnItem);
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
ptTerrain->RefreshTerrain();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// set it as new primitive's material default texture
|
|
theApp.SetNewActiveTexture( _fnmApplicationPath + fnItem);
|
|
// paste new active texture over polygon selection
|
|
theApp.TexturizeSelection();
|
|
}
|
|
}
|
|
// if it is world (template)
|
|
else if( fnItem.FileExt() == ".wld")
|
|
{
|
|
// open document with item's file name
|
|
theApp.m_pDocTemplate->OpenDocumentFile( CString(_fnmApplicationPath + fnItem));
|
|
}
|
|
}
|
|
|
|
void CBrowseWindow::OnRecreateTexture()
|
|
{
|
|
if( _bRightClickedIsSelected)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( it->vtn_bSelected && it->vtn_fnItem.FileExt()==CTString(".tex") )
|
|
{
|
|
_EngineGUI.CreateTexture( it->vtn_fnItem);
|
|
}
|
|
}
|
|
}
|
|
else if( _fnRightClickedItemFileName.FileExt()==CTString(".tex"))
|
|
{
|
|
_EngineGUI.CreateTexture( _fnRightClickedItemFileName);
|
|
}
|
|
Refresh();
|
|
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
if( pDoc != NULL) pDoc->UpdateAllViews( NULL);
|
|
}
|
|
|
|
void CBrowseWindow::OnSelectByTextureInSelectedSectors()
|
|
{
|
|
SelectByTextures( TRUE, FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::OnCreateAndAddTexture()
|
|
{
|
|
CDynamicArray<CTFileName> afnCreatedTextures;
|
|
CTFileName fnCreatedTexture = _EngineGUI.CreateTexture( CTString(""), &afnCreatedTextures);
|
|
if( afnCreatedTextures.Count() != 0)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
if( pVTNDir != NULL)
|
|
{
|
|
CloseDirectory( pVTNDir);
|
|
}
|
|
|
|
// insert created textures
|
|
FOREACHINDYNAMICARRAY( afnCreatedTextures, CTFileName, itTexture)
|
|
{
|
|
CTFileName &fn=*itTexture;
|
|
InsertItem( fn, CPoint(-1, -1));
|
|
}
|
|
if( pVTNDir != NULL)
|
|
{
|
|
OpenDirectory( pVTNDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CBrowseWindow::OnSelectForDropMarker()
|
|
{
|
|
theApp.m_fnClassForDropMarker = _fnRightClickedItemFileName;
|
|
}
|
|
|
|
void CBrowseWindow::OnSetAsCurrentTexture()
|
|
{
|
|
// set it as new primitive's material default texture
|
|
theApp.SetNewActiveTexture( _fnmApplicationPath + _fnRightClickedItemFileName);
|
|
}
|
|
|
|
void CBrowseWindow::OnConvertClass()
|
|
{
|
|
if( _fnRightClickedItemFileName.FileExt()!=CTString(".ecl"))
|
|
{
|
|
WarningMessage( "Only classes can be used for converting classe");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
|
|
{
|
|
// create the entity of requested class
|
|
CEntity *penNewClass;
|
|
penNewClass = pDoc->m_woWorld.CreateEntity_t(
|
|
iten->GetPlacement(), _fnRightClickedItemFileName);
|
|
// try to copy entity properties
|
|
CDLLEntityClass *pdecDLLClassNew = penNewClass->GetClass()->ec_pdecDLLClass;
|
|
for(;pdecDLLClassNew!=NULL; pdecDLLClassNew = pdecDLLClassNew->dec_pdecBase)
|
|
{
|
|
for(INDEX iPropertyNew=0; iPropertyNew<pdecDLLClassNew->dec_ctProperties; iPropertyNew++)
|
|
{
|
|
CEntityProperty &epPropertyNew = pdecDLLClassNew->dec_aepProperties[iPropertyNew];
|
|
CDLLEntityClass *pdecDLLClassOld = iten->GetClass()->ec_pdecDLLClass;
|
|
for(;pdecDLLClassOld!=NULL; pdecDLLClassOld = pdecDLLClassOld->dec_pdecBase)
|
|
{
|
|
for(INDEX iPropertyOld=0; iPropertyOld<pdecDLLClassOld->dec_ctProperties; iPropertyOld++)
|
|
{
|
|
CEntityProperty &epPropertyOld = pdecDLLClassOld->dec_aepProperties[iPropertyOld];
|
|
if( (CTString(epPropertyNew.ep_strName) == epPropertyOld.ep_strName) &&
|
|
(epPropertyNew.ep_eptType == epPropertyOld.ep_eptType) )
|
|
{
|
|
penNewClass->CopyOneProperty( epPropertyOld, epPropertyNew, *iten, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// prepare the entity
|
|
penNewClass->Initialize();
|
|
}
|
|
CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
|
|
if( pWorldEditorView != NULL)
|
|
{
|
|
pWorldEditorView->OnDeleteEntities();
|
|
}
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
AfxMessageBox( CString(err_str));
|
|
}
|
|
}
|
|
|
|
static void GetToolTipText(void *pBrowser, char *pToolTipText)
|
|
{
|
|
CBrowseWindow *pBrowseWindow = (CBrowseWindow *) pBrowser;
|
|
pBrowseWindow->GetToolTipText( pToolTipText);
|
|
}
|
|
|
|
void CBrowseWindow::GetToolTipText( char *pToolTipText)
|
|
{
|
|
CPoint point;
|
|
::GetCursorPos(&point);
|
|
ScreenToClient(&point);
|
|
|
|
// get hitted item's index
|
|
FLOAT fDummyX, fDummyY;
|
|
INDEX iHittedItem = HitItem( point, fDummyX, fDummyY);
|
|
// if hit none reported, return
|
|
if( iHittedItem == -1)
|
|
{
|
|
strcpy( pToolTipText, "");
|
|
return;
|
|
}
|
|
// get item object from hitted index
|
|
CVirtualTreeNode *pVTN = GetItem( iHittedItem);
|
|
strcpy(pToolTipText, pVTN->vtn_strName);
|
|
}
|
|
|
|
void CBrowseWindow::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
theApp.m_cttToolTips.MouseMoveNotify( m_hWnd, 500, &::GetToolTipText, this);
|
|
|
|
CWnd::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CBrowseWindow::OnSelectByTextureInWorld()
|
|
{
|
|
SelectByTextures( FALSE, FALSE);
|
|
}
|
|
|
|
void CBrowseWindow::OnSelectExceptTextures( void)
|
|
{
|
|
SelectByTextures( FALSE, TRUE);
|
|
}
|
|
|
|
void CBrowseWindow::SelectByTextures( BOOL bInSelectedSectors, BOOL bExceptSelected)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
if( pDoc == NULL) return;
|
|
|
|
// for each entity in the world
|
|
FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten) {
|
|
// if it is brush entity
|
|
if (iten->en_RenderType == CEntity::RT_BRUSH) {
|
|
// for each mip in its brush
|
|
FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) {
|
|
// for all sectors in this mip
|
|
FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
|
|
// if sector is selected
|
|
if( !bInSelectedSectors || itbsc->IsSelected(BSCF_SELECTED))
|
|
{
|
|
// for all polygons in sector
|
|
FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
|
|
{
|
|
// if it is not non translucent portal and is not selected and has same texture
|
|
if ( /*(!(itbpo->bpo_ulFlags&BPOF_PORTAL) || (itbpo->bpo_ulFlags&BPOF_TRANSLUCENT) ||
|
|
(itbpo->bpo_bppProperties.bpp_uwPretenderDistance!=0) ) &&*/
|
|
!itbpo->IsSelected(BPOF_SELECTED) &&
|
|
(itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData() != NULL) )
|
|
{
|
|
CTFileName fnTexture = itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData()->GetName();
|
|
BOOL bSelect = bExceptSelected;
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( _bRightClickedIsSelected)
|
|
{
|
|
if(it->vtn_bSelected && it->vtn_fnItem.FileExt()==CTString(".tex") &&
|
|
fnTexture == it->vtn_fnItem)
|
|
{
|
|
bSelect = !bExceptSelected;
|
|
break;
|
|
}
|
|
}
|
|
else if( fnTexture == _fnRightClickedItemFileName)
|
|
{
|
|
bSelect = !bExceptSelected;
|
|
break;
|
|
}
|
|
}
|
|
if( bSelect) pDoc->m_selPolygonSelection.Select(*itbpo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pDoc->SetEditingMode( POLYGON_MODE);
|
|
pDoc->m_chSelections.MarkChanged();
|
|
pDoc->UpdateAllViews( NULL);
|
|
}
|
|
|
|
void CBrowseWindow::OnAddTexturesFromWorld()
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
if (pDoc == NULL) return;
|
|
|
|
CloseDirectory( pVTNDir);
|
|
// for each entity in the world
|
|
FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten) {
|
|
// if it is brush entity
|
|
if (iten->en_RenderType == CEntity::RT_BRUSH) {
|
|
// for each mip in its brush
|
|
FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) {
|
|
// for all sectors in this mip
|
|
FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
|
|
// for all polygons in sector
|
|
FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
|
|
{
|
|
try
|
|
{
|
|
CTextureObject &to1 = itbpo->bpo_abptTextures[0].bpt_toTexture;
|
|
if(to1.GetData() != NULL)
|
|
InsertItem( to1.GetData()->GetName(), CPoint(-1, -1));
|
|
CTextureObject &to2 = itbpo->bpo_abptTextures[1].bpt_toTexture;
|
|
if(to2.GetData() != NULL)
|
|
InsertItem( to2.GetData()->GetName(), CPoint(-1, -1));
|
|
CTextureObject &to3 = itbpo->bpo_abptTextures[2].bpt_toTexture;
|
|
if(to3.GetData() != NULL)
|
|
InsertItem( to3.GetData()->GetName(), CPoint(-1, -1));
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
AfxMessageBox( CString(err_str));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
OpenDirectory( pVTNDir);
|
|
}
|
|
|
|
void CBrowseWindow::OnShowTreeShortcuts()
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
pMainFrame->OnShowTreeShortcuts();
|
|
}
|
|
|
|
void ExportTexture( CTFileName fnTexture)
|
|
{
|
|
CTextureData *ptd;
|
|
CImageInfo ii;
|
|
|
|
try
|
|
{
|
|
ptd = _pTextureStock->Obtain_t( fnTexture);
|
|
for( INDEX iFrame=0; iFrame<ptd->td_ctFrames; iFrame++)
|
|
{
|
|
ptd->Export_t( ii, iFrame);
|
|
// obtain name for export file
|
|
CTFileName fnFrame;
|
|
if( ptd->td_ctFrames == 1)
|
|
{
|
|
fnFrame = fnTexture.NoExt()+".tga";
|
|
}
|
|
else
|
|
{
|
|
fnFrame.PrintF("%s%03d.tga", (const char *)fnTexture.NoExt(), iFrame);
|
|
}
|
|
// if file exists, ask for substitution name
|
|
if( FileExists( fnFrame) && iFrame==0 )
|
|
{
|
|
CTString strDefaultDir = fnFrame.FileDir();
|
|
CTString strDefaultFile = fnFrame.FileName()+fnFrame.FileExt();
|
|
// invoke "Save as" dialog
|
|
fnFrame = _EngineGUI.FileRequester( "Save As", FILTER_TGA FILTER_END,
|
|
"Export texture directory", strDefaultDir, strDefaultFile, NULL, FALSE);
|
|
}
|
|
if( fnFrame != "")
|
|
{
|
|
ii.SaveTGA_t(fnFrame);
|
|
ii.Clear();
|
|
}
|
|
}
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
AfxMessageBox( CString(strError));
|
|
ii.Clear();
|
|
}
|
|
}
|
|
|
|
void CBrowseWindow::OnExportTexture()
|
|
{
|
|
if( _bRightClickedIsSelected)
|
|
{
|
|
CVirtualTreeNode *pVTNDir = m_pBrowser->GetSelectedDirectory();
|
|
ASSERT( pVTNDir != NULL);
|
|
FOREACHINLIST( CVirtualTreeNode, vtn_lnInDirectory, pVTNDir->vtn_lhChildren, it)
|
|
{
|
|
if( it->vtn_bSelected && it->vtn_fnItem.FileExt()==CTString(".tex") ||
|
|
it->vtn_bSelected && it->vtn_fnItem.FileExt()==CTString(".tbn") )
|
|
{
|
|
ExportTexture( it->vtn_fnItem);
|
|
}
|
|
}
|
|
}
|
|
else if( _fnRightClickedItemFileName.FileExt()==CTString(".tex") ||
|
|
_fnRightClickedItemFileName.FileExt()==CTString(".tbn") )
|
|
{
|
|
ExportTexture( _fnRightClickedItemFileName);
|
|
}
|
|
}
|
|
|
|
void CBrowseWindow::OnBrowserContextHelp()
|
|
{
|
|
if( _fnRightClickedItemFileName.FileExt()==CTString(".ecl"))
|
|
{
|
|
theApp.DisplayHelp(_fnRightClickedItemFileName, HH_DISPLAY_TOPIC, NULL);
|
|
}
|
|
}
|