Serious-Engine/Sources/Modeler/ModelerDoc.cpp
2016-03-11 18:20:51 -06:00

537 lines
16 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. */
// ModelerDoc.cpp : implementation of the CModelerDoc class
//
#include "stdafx.h"
#include <Engine/Templates/Stock_CAnimData.h>
#include <Engine/Templates/Stock_CTextureData.h>
#include <Engine/Templates/Stock_CSoundData.h>
#include <Engine/Templates/Stock_CModelData.h>
#include <Engine/Build.h>
#ifdef _DEBUG
#undef new
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CModelerDoc
IMPLEMENT_DYNCREATE(CModelerDoc, CDocument)
BEGIN_MESSAGE_MAP(CModelerDoc, CDocument)
//{{AFX_MSG_MAP(CModelerDoc)
ON_COMMAND(ID_FILE_ADD_TEXTURE, OnFileAddTexture)
ON_UPDATE_COMMAND_UI(ID_FILE_ADD_TEXTURE, OnUpdateFileAddTexture)
ON_COMMAND(ID_NEXT_SURFACE, OnNextSurface)
ON_COMMAND(ID_PREV_SURFACE, OnPrevSurface)
ON_COMMAND(ID_LINK_SURFACES, OnLinkSurfaces)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CModelerDoc construction/destruction
CModelerDoc::CModelerDoc()
{
// Default clipboard variables used for storing copy/paste data
m_f3ClipboardCenter = FLOAT3D( 0.0f, 0.0f, 0.0f);
m_fClipboardZoom = FLOAT( 0.0f);
m_f3ClipboardHPB = FLOAT3D( 0.0f, 0.0f, 0.0f);
m_iCurrentMip = 0;
}
CModelerDoc::~CModelerDoc()
{
_pAnimStock->FreeUnused();
_pTextureStock->FreeUnused();
_pModelStock->FreeUnused();
_pSoundStock->FreeUnused();
}
BOOL CModelerDoc::CreateModelFromScriptFile( CTFileName fnScrFileName, char *strError)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
try
{
CWaitCursor StartWaitCursor;
CRect rectMainFrameSize;
CRect rectProgress, rectProgressNew;
pMainFrame->GetWindowRect( &rectMainFrameSize);
pMainFrame->m_NewProgress.Create( IDD_NEW_PROGRESS, pMainFrame);
pMainFrame->m_NewProgress.GetWindowRect( &rectProgress);
rectProgressNew.left = rectMainFrameSize.Width()/2 - rectProgress.Width()/2;
rectProgressNew.top = rectMainFrameSize.Height()/2 - rectProgress.Height()/2;
rectProgressNew.right = rectProgressNew.left + rectProgress.Width();
rectProgressNew.bottom = rectProgressNew.top + rectProgress.Height();
pMainFrame->m_NewProgress.MoveWindow( rectProgressNew);
pMainFrame->m_NewProgress.ShowWindow(SW_SHOW);
m_emEditModel.LoadFromScript_t( fnScrFileName);
}
catch( char *err_str)
{
strcpy( strError, err_str);
pMainFrame->m_NewProgress.DestroyWindow();
return FALSE;
}
pMainFrame->m_NewProgress.DestroyWindow();
m_bDocLoadedOk = TRUE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CModelerDoc serialization
void CModelerDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
}
}
/////////////////////////////////////////////////////////////////////////////
// CModelerDoc diagnostics
#ifdef _DEBUG
void CModelerDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CModelerDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CModelerDoc commands
BOOL CModelerDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
m_bDocLoadedOk = FALSE;
CTFileName fnModelFile = CTString(CStringA(lpszPathName));
try
{
fnModelFile.RemoveApplicationPath_t();
}
catch( char *err_str)
{
AfxMessageBox( CString(err_str));
return FALSE;
}
try
{
m_emEditModel.Load_t( fnModelFile);
}
catch( char *err_str)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
MessageBoxA(pMainFrame->m_hWnd, err_str, "Warning! Model load failed.", MB_OK|MB_ICONHAND|MB_SYSTEMMODAL);
return FALSE;
}
INDEX ctLoadedModels=m_emEditModel.edm_aamAttachedModels.Count();
INDEX ctAttachmentPositions=m_emEditModel.edm_md.md_aampAttachedPosition.Count();
if(ctLoadedModels<ctAttachmentPositions)
{
for( INDEX iPos=ctLoadedModels; iPos<ctAttachmentPositions; iPos++)
{
m_emEditModel.edm_aamAttachedModels.New();
m_emEditModel.edm_aamAttachedModels.Lock();
CAttachedModel &am=m_emEditModel.edm_aamAttachedModels[iPos];
DECLARE_CTFILENAME( fnAxis, "Models\\Editor\\Axis.mdl");
am.am_bVisible=TRUE;
am.am_strName="Not loaded";
am.am_iAnimation=0;
try
{
am.SetModel_t(fnAxis);
}
catch( char *strError)
{
WarningMessage( strError);
}
m_emEditModel.edm_aamAttachedModels.Unlock();
}
}
m_bDocLoadedOk = TRUE;
// flush stale caches
_pShell->Execute("FreeUnusedStock();");
SelectSurface( 0, TRUE);
return TRUE;
}
BOOL CModelerDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
//return CDocument::OnSaveDocument(lpszPathName);
CTFileName fnModelFile = CTString(CStringA(lpszPathName));
try
{
fnModelFile.RemoveApplicationPath_t();
}
catch( char *err_str)
{
AfxMessageBox( CString(err_str));
return FALSE;
}
try
{
m_emEditModel.Save_t( fnModelFile);
m_emEditModel.SaveMapping_t( fnModelFile.NoExt()+".map", 0);
}
catch( char *err_str)
{
MessageBoxA(pMainFrame->m_hWnd, err_str, "Warning! Model Save failed.", MB_OK|MB_ICONHAND|MB_SYSTEMMODAL);
return FALSE;
}
SetModifiedFlag( FALSE);
CModelerView *pModelerView = CModelerView::GetActiveView();
if( pModelerView != NULL)
{
pModelerView->SaveThumbnail();
}
// reload attachments of all loaded models
POSITION pos = theApp.m_pdtModelDocTemplate->GetFirstDocPosition();
while (pos!=NULL)
{
CModelerDoc *pmdCurrent = (CModelerDoc *)theApp.m_pdtModelDocTemplate->GetNextDoc(pos);
if( pmdCurrent != this)
{
BOOL bUpdateAttachments = TRUE;
// if document is modified
if( pmdCurrent->IsModified())
{
CTString strMessage;
CTFileName fnDoc = CTString(CStringA(pmdCurrent->GetPathName()));
strMessage.PrintF("Do you want to save model \"%s\" before reloading its attachments?", fnDoc.FileName() );
if( ::MessageBoxA( pMainFrame->m_hWnd, strMessage,
"Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1 |
MB_TASKMODAL | MB_TOPMOST) != IDYES)
{
bUpdateAttachments = FALSE;
}
// save document
else
{
pmdCurrent->OnSaveDocument(pmdCurrent->GetPathName());
}
}
if( bUpdateAttachments)
{
POSITION pos = pmdCurrent->GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
((CModelerView *)pView)->m_ModelObject.AutoSetAttachments();
//CModelData *pmd = (CModelData *) ((CModelerView *)pView)->m_ModelObject.GetData();
//pmd->Reload();
}
}
}
}
return TRUE;
}
void CModelerDoc::OnIdle(void)
{
POSITION pos = GetFirstViewPosition();
while ( pos !=NULL) {
CModelerView *pmvCurrent = (CModelerView *) GetNextView(pos);
pmvCurrent->OnIdle();
}
}
// overridden from mfc to discard rendering precalculations
void CModelerDoc::SetModifiedFlag( BOOL bModified /*= TRUE*/ )
{
CDocument::SetModifiedFlag(bModified);
}
extern UINT APIENTRY ModelerFileRequesterHook( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
void CModelerDoc::OnFileAddTexture()
{
CModelerView *pModelerView = CModelerView::GetActiveView();
if( pModelerView == NULL)
return;
// call file requester for adding textures
CDynamicArray<CTFileName> afnTextures;
CTFileName fnDocName = CTString(CStringA(GetPathName()));
theApp.WriteProfileString( L"Scape", L"Add texture directory", CString(fnDocName.FileDir()));
_EngineGUI.FileRequester( "Choose textures to add", FILTER_TEX FILTER_END,
"Add texture directory", "Textures\\", fnDocName.FileName()+".tex", &afnTextures);
MEX mexWidth, mexHeight;
m_emEditModel.edm_md.GetTextureDimensions( mexWidth, mexHeight);
// add selected textures
FOREACHINDYNAMICARRAY( afnTextures, CTFileName, itTexture)
{
CTextureDataInfo *pNewTDI;
// add texture
CTFileName fnTexName = itTexture.Current();
try
{
pNewTDI =m_emEditModel.AddTexture_t( fnTexName, mexWidth, mexHeight);
}
catch( char *err_str)
{
pNewTDI = NULL;
AfxMessageBox( CString(err_str));
}
if( pNewTDI != NULL)
{
SetModifiedFlag();
pModelerView->m_ptdiTextureDataInfo = pNewTDI;
// switch to texture mode
pModelerView->OnRendUseTexture();
UpdateAllViews( NULL);
}
}
}
void CModelerDoc::OnUpdateFileAddTexture(CCmdUI* pCmdUI)
{
CModelerView *pModelerView = CModelerView::GetActiveView();
pCmdUI->Enable( pModelerView != NULL);
}
CTString CModelerDoc::GetModelDirectory( void)
{
CTFileName fnResult = CTFileName( CTString(CStringA(GetPathName()))).FileDir();
return CTString( fnResult);
}
CTString CModelerDoc::GetModelName( void)
{
CTFileName fnResult = CTFileName( CTString(CStringA(GetPathName()))).FileName();
return CTString( fnResult);
}
void CModelerDoc::SelectMipModel( INDEX iMipToSelect)
{
m_iCurrentMip = iMipToSelect;
POSITION pos = GetFirstViewPosition();
while ( pos !=NULL) {
CModelerView *pmvCurrent = (CModelerView *) GetNextView(pos);
pmvCurrent->m_ModelObject.SetManualMipLevel( iMipToSelect);
}
SpreadSurfaceSelection();
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::ClearAttachments( void)
{
POSITION pos = GetFirstViewPosition();
while ( pos !=NULL)
{
CModelerView *pmvView = (CModelerView *) GetNextView(pos);
pmvView->m_ModelObject.RemoveAllAttachmentModels();
}
}
void CModelerDoc::SetupAttachments( void)
{
POSITION pos = GetFirstViewPosition();
while ( pos !=NULL)
{
CModelerView *pmvView = (CModelerView *) GetNextView(pos);
INDEX iAttachment = 0;
FOREACHINDYNAMICARRAY( m_emEditModel.edm_aamAttachedModels, CAttachedModel, itam)
{
m_emEditModel.edm_aamAttachedModels.Lock();
CAttachedModel *pamAttachedModel = &m_emEditModel.edm_aamAttachedModels[ iAttachment];
if( pamAttachedModel->am_bVisible)
{
CAttachmentModelObject *pamo = pmvView->m_ModelObject.AddAttachmentModel( iAttachment);
CModelData *pMD = (CModelData *) pamAttachedModel->am_moAttachedModel.GetData();
ASSERT(pMD != NULL);
pamo->amo_moModelObject.SetData( pMD);
pamo->amo_moModelObject.AutoSetTextures();
pamo->amo_moModelObject.AutoSetAttachments();
pamo->amo_moModelObject.StartAnim( itam->am_iAnimation);
}
m_emEditModel.edm_aamAttachedModels.Unlock();
iAttachment++;
}
}
}
void CModelerDoc::ClearSurfaceSelection(void)
{
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
for( INDEX iSurface=0; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++) {
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
ms.ms_ulRenderingFlags &= ~SRF_SELECTED;
}
}
void CModelerDoc::SelectAllSurfaces(void)
{
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
for( INDEX iSurface=0; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++) {
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
ms.ms_ulRenderingFlags |= SRF_SELECTED;
}
}
INDEX CModelerDoc::GetCountOfSelectedSurfaces(void)
{
INDEX ctSelectedSurfaces = 0;
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
for( INDEX iSurface=0; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++)
{
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
if( ms.ms_ulRenderingFlags&SRF_SELECTED) ctSelectedSurfaces++;
}
return ctSelectedSurfaces;
}
INDEX CModelerDoc::GetOnlySelectedSurface(void)
{
if( GetCountOfSelectedSurfaces() != 1) return -1;
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
INDEX iSurface=0;
for( ; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++)
{
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
if( ms.ms_ulRenderingFlags&SRF_SELECTED) break;
}
return iSurface;
}
void CModelerDoc::OnPrevSurface()
{
SelectPreviousSurface();
}
void CModelerDoc::OnNextSurface()
{
SelectNextSurface();
}
void CModelerDoc::SelectPreviousSurface(void)
{
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
INDEX iFirstSelected = 1;
for( INDEX iSurface=0; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++) {
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
if( ms.ms_ulRenderingFlags&SRF_SELECTED) {
iFirstSelected = iSurface;
break;
}
}
ClearSurfaceSelection();
iFirstSelected = (iFirstSelected+mmi.mmpi_MappingSurfaces.Count()-1)%mmi.mmpi_MappingSurfaces.Count();
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iFirstSelected];
ms.ms_ulRenderingFlags |= SRF_SELECTED;
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::SelectSurface(INDEX iSurface, BOOL bClearRest)
{
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
if( iSurface >= mmi.mmpi_MappingSurfaces.Count()) return;
if( bClearRest) ClearSurfaceSelection();
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
ms.ms_ulRenderingFlags |= SRF_SELECTED;
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::SelectNextSurface(void)
{
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
INDEX iFirstSelected = 1;
for( INDEX iSurface=0; iSurface<mmi.mmpi_MappingSurfaces.Count(); iSurface++) {
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurface];
if( ms.ms_ulRenderingFlags&SRF_SELECTED) {
iFirstSelected = iSurface;
break;
}
}
ClearSurfaceSelection();
iFirstSelected = (iFirstSelected+1)%mmi.mmpi_MappingSurfaces.Count();
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iFirstSelected];
ms.ms_ulRenderingFlags |= SRF_SELECTED;
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::ToggleSurfaceSelection( INDEX iSurfaceToToggle)
{
BOOL bAllreadyExisted = FALSE;
ClearSurfaceSelection();
ModelMipInfo &mmi = m_emEditModel.edm_md.md_MipInfos[ m_iCurrentMip];
MappingSurface &ms = mmi.mmpi_MappingSurfaces[ iSurfaceToToggle];
ms.ms_ulRenderingFlags ^= SRF_SELECTED;
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::SpreadSurfaceSelection( void)
{
ModelMipInfo &mmiSrc = m_emEditModel.edm_md.md_MipInfos[ 0];
for( INDEX iMip=1; iMip<m_emEditModel.edm_md.md_MipCt; iMip++) {
ModelMipInfo &mmiDst = m_emEditModel.edm_md.md_MipInfos[ iMip];
// copy selected flag for surfaces with same names
for( INDEX iSurfaceSrc=0; iSurfaceSrc<mmiSrc.mmpi_MappingSurfaces.Count(); iSurfaceSrc++) {
MappingSurface &msSrc = mmiSrc.mmpi_MappingSurfaces[ iSurfaceSrc];
for( INDEX iSurfaceDst=0; iSurfaceDst<mmiDst.mmpi_MappingSurfaces.Count(); iSurfaceDst++) {
MappingSurface &msDst = mmiDst.mmpi_MappingSurfaces[ iSurfaceDst];
if( CTString(msSrc.ms_Name) == msDst.ms_Name) {
msDst.ms_ulRenderingFlags &= ~SRF_SELECTED;
msDst.ms_ulRenderingFlags |= msSrc.ms_ulRenderingFlags & SRF_SELECTED;
}
}
}
}
theApp.m_chGlobal.MarkChanged();
}
void CModelerDoc::OnLinkSurfaces()
{
CDlgMarkLinkedSurfaces dlgMarkLinkedSurfaces;
dlgMarkLinkedSurfaces.DoModal();
UpdateAllViews( NULL);
}