mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-27 07:54:51 +01:00
524 lines
15 KiB
C++
524 lines
15 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
|
|
|
// 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);
|
|
}
|