mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-25 07:14:50 +01:00
994 lines
30 KiB
C++
994 lines
30 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. */
|
|
|
|
// Modeler.cpp : Defines the class behaviors for the application.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include <Engine/Templates/Stock_CModelData.h>
|
|
#include <Engine/Templates/Stock_CTextureData.h>
|
|
|
|
#ifdef _DEBUG
|
|
#undef new
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// Macros used for ini i/o operations
|
|
#define INI_READ( strname, def) \
|
|
wcscpy( strIni, theApp.GetProfileString( L"Modeler prefs", CString(strname), CString(def)))
|
|
#define GET_FLAG( var) \
|
|
if( wcscmp( strIni, L"YES") == 0) var = TRUE; \
|
|
else var = FALSE;
|
|
#define GET_COLOR( var) \
|
|
swscanf( strIni, L"0X%08x", &var);
|
|
#define GET_INDEX( var) \
|
|
swscanf( strIni, L"%d", &var);
|
|
#define GET_FLOAT( var) \
|
|
swscanf( strIni, L"%f", &var);
|
|
|
|
#define SET_FLAG( var) \
|
|
if( var) wcscpy( strIni, L"YES"); \
|
|
else wcscpy( strIni, L"NO");
|
|
#define SET_COLOR( var) \
|
|
swprintf( strIni, L"0x%08x", var); \
|
|
_wcsupr( strIni);
|
|
#define SET_INDEX( var) \
|
|
swprintf( strIni, L"%d", var); \
|
|
_wcsupr( strIni);
|
|
#define SET_FLOAT( var) \
|
|
swprintf( strIni, L"%f", var); \
|
|
_wcsupr( strIni);
|
|
#define INI_WRITE( strname) \
|
|
theApp.WriteProfileString( L"Modeler prefs", CString(strname), strIni)
|
|
|
|
BOOL GetFlagFromProfile( CTString strVarName, BOOL bDefault)
|
|
{
|
|
CTString strDefault;
|
|
if( bDefault) strDefault = "YES";
|
|
else strDefault = "NO";
|
|
CTString strTemp = CStringA(theApp.GetProfileString( L"Modeler prefs", CString(strVarName), CString(strDefault)));
|
|
if( strTemp == "YES") return TRUE;
|
|
return FALSE;
|
|
};
|
|
|
|
void SetFlagToProfile( CTString strVarName, BOOL bValue)
|
|
{
|
|
if( bValue) theApp.WriteProfileString( L"Modeler prefs", CString(strVarName), L"YES");
|
|
else theApp.WriteProfileString( L"Modeler prefs", CString(strVarName), L"NO");
|
|
};
|
|
|
|
INDEX GetIndexFromProfile( CTString strVarName, INDEX iDefault)
|
|
{
|
|
CTString strDefault;
|
|
strDefault.PrintF("%d", iDefault);
|
|
CTString strTemp = CStringA(theApp.GetProfileString( L"Modeler prefs", CString(strVarName), CString(strDefault)));
|
|
INDEX iValue;
|
|
sscanf( strTemp, "%d", &iValue);
|
|
return iValue;
|
|
};
|
|
|
|
void SetIndexToProfile( CTString strVarName, INDEX iValue)
|
|
{
|
|
CTString strTemp;
|
|
strTemp.PrintF("%d", iValue);
|
|
theApp.WriteProfileString( L"Modeler prefs", CString(strVarName), CString(strTemp));
|
|
};
|
|
|
|
COLOR GetColorFromProfile( CTString strVarName, COLOR colDefault)
|
|
{
|
|
CTString strDefault;
|
|
strDefault.PrintF("0x%08x", colDefault);
|
|
CTString strTemp = CStringA(theApp.GetProfileString( L"Modeler prefs", CString(strVarName), CString(strDefault)));
|
|
COLOR colValue;
|
|
sscanf( strTemp, "0x%08x", &colValue);
|
|
return colValue;
|
|
};
|
|
|
|
void SetColorToProfile( CTString strVarName, COLOR colValue)
|
|
{
|
|
CTString strTemp;
|
|
strTemp.PrintF("0x%08x", colValue);
|
|
theApp.WriteProfileString( L"Modeler prefs", CString(strVarName), CString(strTemp));
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CModelerApp
|
|
|
|
BEGIN_MESSAGE_MAP(CModelerApp, CWinApp)
|
|
//{{AFX_MSG_MAP(CModelerApp)
|
|
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
|
ON_COMMAND(ID_FILE_NEW, OnFileNew)
|
|
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
|
|
ON_COMMAND(ID_FILE_PREFERENCES, OnFilePreferences)
|
|
//}}AFX_MSG_MAP
|
|
// Standard file based document commands
|
|
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
|
// Standard print setup command
|
|
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
UINT APIENTRY ModelerFileRequesterHook( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if( uiMsg == WM_INITDIALOG)
|
|
{
|
|
CRect rectMainFrame, rectFileReqPos, rectFileReqNewPos;
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
LONG left, top;
|
|
|
|
GetWindowRect( GetParent( hdlg), rectFileReqPos);
|
|
pMainFrame->GetWindowRect( rectMainFrame);
|
|
|
|
left = (rectMainFrame.right - rectMainFrame.left)/2
|
|
- rectFileReqPos.Width()/2;
|
|
top = (rectMainFrame.bottom - rectMainFrame.top)/2
|
|
- rectFileReqPos.Height()/2;
|
|
MoveWindow( GetParent( hdlg), left, top,
|
|
rectFileReqPos.Width(), rectFileReqPos.Height(), TRUE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CModelerApp construction
|
|
|
|
CModelerApp::CModelerApp()
|
|
{
|
|
m_bRefreshPatchPalette = FALSE;
|
|
m_OnIdlePaused = FALSE;
|
|
m_pLampModelData = NULL;
|
|
m_pFloorModelData = NULL;
|
|
m_pCollisionBoxModelData = NULL;
|
|
m_ptdCollisionBoxTexture = NULL;
|
|
m_ptdLamp = NULL;
|
|
m_ptdFloorTexture = NULL;
|
|
m_pfntFont = NULL;
|
|
}
|
|
|
|
CBcgTexture::CBcgTexture()
|
|
{
|
|
wt_TextureData = NULL;
|
|
}
|
|
|
|
CBcgTexture::~CBcgTexture()
|
|
{
|
|
}
|
|
|
|
CModelerApp::~CModelerApp()
|
|
{
|
|
if( m_pLampModelData != NULL)
|
|
{
|
|
_pModelStock->Release( m_pLampModelData);
|
|
delete m_LampModelObject;
|
|
}
|
|
|
|
if( m_pCollisionBoxModelData != NULL)
|
|
{
|
|
_pModelStock->Release( m_pCollisionBoxModelData);
|
|
delete m_pCollisionBoxModelObject;
|
|
m_pCollisionBoxModelObject = NULL;
|
|
}
|
|
|
|
if( m_pFloorModelData != NULL)
|
|
{
|
|
_pModelStock->Release( m_pFloorModelData);
|
|
delete m_pFloorModelObject;
|
|
m_pFloorModelObject = NULL;
|
|
}
|
|
|
|
if( m_ptdCollisionBoxTexture != NULL)
|
|
{
|
|
_pTextureStock->Release( m_ptdCollisionBoxTexture);
|
|
m_ptdCollisionBoxTexture = NULL;
|
|
}
|
|
|
|
if( m_ptdLamp != NULL)
|
|
{
|
|
_pTextureStock->Release( m_ptdLamp);
|
|
m_ptdLamp = NULL;
|
|
}
|
|
|
|
if( m_ptdFloorTexture != NULL)
|
|
{
|
|
_pTextureStock->Release( m_ptdFloorTexture);
|
|
m_ptdFloorTexture = NULL;
|
|
}
|
|
|
|
|
|
FORDELETELIST( CBcgTexture, wt_ListNode, m_WorkingTextures, litTex)
|
|
{
|
|
ASSERT( litTex->wt_TextureData != NULL);
|
|
_pTextureStock->Release( litTex->wt_TextureData);
|
|
delete &litTex.Current();
|
|
}
|
|
|
|
FORDELETELIST( CWorkingPatch, wp_ListNode, m_WorkingPatches, litPatch)
|
|
{
|
|
CTextureData *pTD = litPatch->wp_TextureData;
|
|
_pTextureStock->Release( litPatch->wp_TextureData);
|
|
delete &litPatch.Current();
|
|
}
|
|
|
|
SE_EndEngine();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// The one and only CModelerApp object
|
|
|
|
CModelerApp theApp;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CModelerApp initialization
|
|
|
|
BOOL CModelerApp::InitInstance()
|
|
{
|
|
BOOL bResult;
|
|
CTSTREAM_BEGIN {
|
|
bResult = SubInitInstance();
|
|
} CTSTREAM_END;
|
|
return bResult;
|
|
}
|
|
|
|
BOOL CModelerApp::SubInitInstance()
|
|
{
|
|
wchar_t strIni[ 128];
|
|
// Standard initialization
|
|
// If you are not using these features and wish to reduce the size
|
|
// of your final executable, you should remove from the following
|
|
// the specific initialization routines you do not need.
|
|
|
|
#ifdef _AFXDLL
|
|
Enable3dControls(); // Call this when using MFC in a shared DLL
|
|
#else
|
|
Enable3dControlsStatic(); // Call this when linking to MFC statically
|
|
#endif
|
|
|
|
// settings will be saved into registry instead of ini file
|
|
SetRegistryKey( L"CroTeam");
|
|
|
|
LoadStdProfileSettings(8); // Load standard INI file options (including MRU)
|
|
|
|
// Register the application's document templates. Document templates
|
|
// serve as the connection between documents, frame windows and views.
|
|
|
|
CMultiDocTemplate* pDocTemplate;
|
|
m_pdtModelDocTemplate = pDocTemplate = new CMultiDocTemplate(
|
|
IDR_MDLDOCTYPE,
|
|
RUNTIME_CLASS(CModelerDoc),
|
|
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
|
|
RUNTIME_CLASS(CModelerView));
|
|
AddDocTemplate(pDocTemplate);
|
|
|
|
m_pdtScriptTemplate = pDocTemplate = new CMultiDocTemplate(
|
|
IDR_SCRIPTDOCTYPE,
|
|
RUNTIME_CLASS(CScriptDoc),
|
|
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
|
|
RUNTIME_CLASS(CScriptView));
|
|
AddDocTemplate(pDocTemplate);
|
|
|
|
// initialize engine, without network
|
|
SE_InitEngine(""); // DO NOT SPECIFY NAME HERE!
|
|
SE_LoadDefaultFonts();
|
|
|
|
// create main MDI Frame window
|
|
CMainFrame* pMainFrame = new CMainFrame;
|
|
if( !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;
|
|
m_pMainWnd = pMainFrame;
|
|
|
|
// set main window for engine
|
|
SE_UpdateWindowHandle( m_pMainWnd->m_hWnd);
|
|
|
|
// Enable drag/drop open
|
|
m_pMainWnd->DragAcceptFiles();
|
|
|
|
// Enable DDE Execute open
|
|
EnableShellOpen();
|
|
RegisterShellFileTypes(TRUE);
|
|
|
|
// Parse command line for standard shell commands, DDE, file open
|
|
CCommandLineInfo cmdInfo;
|
|
ParseCommandLine(cmdInfo);
|
|
|
|
// load startup script
|
|
_pShell->Execute( "include \"Scripts\\Modeler_startup.ini\"");
|
|
|
|
m_iApi=GAT_OGL;
|
|
m_iApi=GetProfileInt(L"Display modes", L"SED Gfx API", GAT_OGL);
|
|
// (re)set default display mode
|
|
_pGfx->ResetDisplayMode((enum GfxAPIType) m_iApi);
|
|
|
|
m_Preferences.ReadFromIniFile();
|
|
|
|
// load background textures
|
|
INDEX iWorkingTexturesCt = theApp.GetProfileInt( L"Modeler prefs",
|
|
L"Modeler working textures count", -1);
|
|
if( iWorkingTexturesCt != -1) {
|
|
char strWTName[ 128];
|
|
for( INDEX i=0; i<iWorkingTexturesCt; i++) {
|
|
sprintf( strWTName, "Working texture %02d", i);
|
|
INI_READ( strWTName, "Error in INI .file!");
|
|
AddModelerWorkingTexture( CTString(CStringA(strIni)));
|
|
}
|
|
}
|
|
// load working patches
|
|
INDEX iWorkingPatchesCt = theApp.GetProfileInt( L"Modeler prefs",
|
|
L"Modeler working patches count", -1);
|
|
char strWPName[ 128];
|
|
for( INDEX i=0; i<iWorkingPatchesCt; i++) {
|
|
sprintf( strWPName, "Working patch %02d", i);
|
|
INI_READ( strWPName, "Error in INI .file!");
|
|
AddModelerWorkingPatch( CTString(CStringA(strIni)));
|
|
}
|
|
pMainFrame->m_StainsComboBox.Refresh();
|
|
|
|
// don't start new document automatically
|
|
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
|
|
|
|
// create temporary directory to contain copy/paste mapping all
|
|
CreateDirectoryA( _fnmApplicationPath + "Temp\\", NULL);
|
|
|
|
// try to
|
|
try
|
|
{ // load lamp model
|
|
DECLARE_CTFILENAME( fnLampName, "Models\\Editor\\Lamp.mdl");
|
|
m_pLampModelData = _pModelStock->Obtain_t( fnLampName);
|
|
m_LampModelObject = new CModelObject;
|
|
m_LampModelObject->SetData(m_pLampModelData);
|
|
m_LampModelObject->SetAnim( 0);
|
|
// load lamp's texture
|
|
DECLARE_CTFILENAME( fnLampTex, "Models\\Editor\\SpotLight.tex");
|
|
m_ptdLamp = _pTextureStock->Obtain_t( fnLampTex);
|
|
m_LampModelObject->mo_toTexture.SetData( m_ptdLamp);
|
|
|
|
// load collision box model
|
|
DECLARE_CTFILENAME( fnCollisionBox, "Models\\Editor\\CollisionBox.mdl");
|
|
m_pCollisionBoxModelData = _pModelStock->Obtain_t( fnCollisionBox);
|
|
m_pCollisionBoxModelObject = new CModelObject;
|
|
m_pCollisionBoxModelObject->SetData(m_pCollisionBoxModelData);
|
|
m_pCollisionBoxModelObject->SetAnim( 0);
|
|
// load collision box's texture
|
|
DECLARE_CTFILENAME( fnCollisionBoxTex, "Models\\Editor\\CollisionBox.tex");
|
|
m_ptdCollisionBoxTexture = _pTextureStock->Obtain_t( fnCollisionBoxTex);
|
|
m_pCollisionBoxModelObject->mo_toTexture.SetData( m_ptdCollisionBoxTexture);
|
|
|
|
// load floor model
|
|
DECLARE_CTFILENAME( fnFloor, "Models\\Editor\\Floor.mdl");
|
|
m_pFloorModelData = _pModelStock->Obtain_t( fnFloor);
|
|
m_pFloorModelObject = new CModelObject;
|
|
m_pFloorModelObject->SetData(m_pFloorModelData);
|
|
m_pFloorModelObject->SetAnim( 0);
|
|
// load collision box's texture
|
|
DECLARE_CTFILENAME( fnFloorTex, "Models\\Editor\\Floor.tex");
|
|
m_ptdFloorTexture = _pTextureStock->Obtain_t( fnFloorTex);
|
|
m_pFloorModelObject->mo_toTexture.SetData( m_ptdFloorTexture);
|
|
|
|
DECLARE_CTFILENAME( fnShadowTex, "Textures\\Effects\\Shadow\\SimpleModelShadow.tex");
|
|
// setup simple model shadow texture
|
|
_toSimpleModelShadow.SetData_t( fnShadowTex);
|
|
}
|
|
catch( char *err_str)
|
|
{ // report error and continue without models
|
|
AfxMessageBox( CString(err_str));
|
|
|
|
// if we allocated model object for collision box
|
|
if( m_pCollisionBoxModelObject != NULL) {
|
|
// delete it
|
|
delete m_pCollisionBoxModelObject;
|
|
m_pCollisionBoxModelObject = NULL;
|
|
}
|
|
// if we loaded collision box's texture
|
|
if( m_ptdCollisionBoxTexture != NULL) {
|
|
// release it and
|
|
_pTextureStock->Release( m_ptdCollisionBoxTexture);
|
|
m_ptdCollisionBoxTexture = NULL;
|
|
}
|
|
|
|
// if we loaded lamp's texture
|
|
if( m_ptdLamp != NULL) {
|
|
// release it and
|
|
_pTextureStock->Release( m_ptdLamp);
|
|
m_ptdLamp = NULL;
|
|
}
|
|
|
|
// if we allocated model object for floor
|
|
if( m_pFloorModelObject != NULL) {
|
|
// delete it
|
|
delete m_pFloorModelObject;
|
|
m_pFloorModelObject = NULL;
|
|
}
|
|
// if we loaded floor's texture
|
|
if( m_ptdFloorTexture != NULL) {
|
|
// release it and
|
|
_pTextureStock->Release( m_ptdFloorTexture);
|
|
m_ptdFloorTexture = NULL;
|
|
}
|
|
}
|
|
|
|
// assign system font
|
|
m_pfntFont = _pfdDisplayFont;
|
|
|
|
// Dispatch commands specified on the command line
|
|
if( !ProcessShellCommand(cmdInfo)) return FALSE;
|
|
|
|
// The main window has been initialized, so show and update it.
|
|
m_nCmdShow = SW_SHOWMAXIMIZED; // maximize main frame !!!
|
|
pMainFrame->ShowWindow(m_nCmdShow);
|
|
pMainFrame->UpdateWindow();
|
|
|
|
// if stating modeler for the first time
|
|
if( m_bFirstTimeStarted) {
|
|
// call preferences
|
|
OnFilePreferences();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAboutDlg dialog used for App About
|
|
|
|
class CAboutDlg : public CDialog
|
|
{
|
|
public:
|
|
CAboutDlg();
|
|
|
|
// Dialog Data
|
|
//{{AFX_DATA(CAboutDlg)
|
|
enum { IDD = IDD_ABOUTBOX };
|
|
//}}AFX_DATA
|
|
|
|
// ClassWizard generated virtual function overrides
|
|
//{{AFX_VIRTUAL(CAboutDlg)
|
|
protected:
|
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
|
//}}AFX_VIRTUAL
|
|
|
|
// Implementation
|
|
protected:
|
|
//{{AFX_MSG(CAboutDlg)
|
|
// No message handlers
|
|
//}}AFX_MSG
|
|
DECLARE_MESSAGE_MAP()
|
|
};
|
|
|
|
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
|
{
|
|
//{{AFX_DATA_INIT(CAboutDlg)
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CAboutDlg)
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CAboutDlg)
|
|
// No message handlers
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
// App command to run the dialog
|
|
void CModelerApp::OnAppAbout()
|
|
{
|
|
CAboutDlg aboutDlg;
|
|
aboutDlg.DoModal();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CModelerApp commands
|
|
|
|
static TIME timeLastTick=TIME(0);
|
|
BOOL CModelerApp::OnIdle(LONG lCount)
|
|
{
|
|
if( _pTimer != NULL)
|
|
{
|
|
TIME timeCurrentTick = _pTimer->GetRealTimeTick();
|
|
if( (timeCurrentTick > timeLastTick) && !m_OnIdlePaused)
|
|
{
|
|
_pTimer->SetCurrentTick( timeCurrentTick);
|
|
timeLastTick = timeCurrentTick;
|
|
POSITION pos = m_pdtModelDocTemplate->GetFirstDocPosition();
|
|
|
|
while (pos!=NULL) {
|
|
CModelerDoc *pmdCurrent = (CModelerDoc *)m_pdtModelDocTemplate->GetNextDoc(pos);
|
|
pmdCurrent->OnIdle();
|
|
}
|
|
|
|
((CMainFrame *)m_pMainWnd)->OnIdle( lCount);
|
|
}
|
|
}
|
|
|
|
// if application is active
|
|
extern BOOL _bApplicationActive;
|
|
if (_bApplicationActive) {
|
|
// never release idle
|
|
return CWinApp::OnIdle(lCount) || TRUE;
|
|
// if application is inactive
|
|
} else {
|
|
// release idle when not needed
|
|
return CWinApp::OnIdle(lCount);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CModelerApp::CreateNewDocument( CTFileName fnRequestedFile)
|
|
{
|
|
CTFileName fnMdlFile = fnRequestedFile.FileDir() + fnRequestedFile.FileName() + ".mdl";
|
|
CTFileName fnScriptFile = fnRequestedFile.FileDir() + fnRequestedFile.FileName() + ".scr";
|
|
|
|
if( fnRequestedFile.FileExt() != ".scr")
|
|
{
|
|
if( GetFileAttributesA( _fnmApplicationPath + fnScriptFile) != -1)
|
|
{
|
|
if( MessageBoxA( m_pMainWnd->m_hWnd, "Script file allready exists, "
|
|
"do you want to overwrite it?",
|
|
"Warning !", MB_YESNO | MB_ICONWARNING |
|
|
MB_DEFBUTTON1| MB_SYSTEMMODAL | MB_TOPMOST) == IDYES)
|
|
{
|
|
DeleteFileA( _fnmApplicationPath + fnScriptFile);
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
CEditModel em;
|
|
|
|
try
|
|
{
|
|
em.CreateScriptFile_t( fnRequestedFile);
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
AfxMessageBox( CString(err_str));
|
|
return;
|
|
}
|
|
}
|
|
else if( GetFileAttributesA( _fnmApplicationPath + fnMdlFile) != -1)
|
|
{
|
|
if( MessageBoxA( m_pMainWnd->m_hWnd, "Model file allready exists, do you want to "
|
|
"overwrite it and loose all possible data describing mapping, "
|
|
"colored polygons, patch positions, ... ?",
|
|
"Warning !", MB_YESNO | MB_ICONWARNING |
|
|
MB_DEFBUTTON1| MB_SYSTEMMODAL | MB_TOPMOST) != IDYES)
|
|
return;
|
|
}
|
|
|
|
// Now we create document instance of type CModelerDoc
|
|
CDocument* pDocument = m_pdtModelDocTemplate->CreateNewDocument();
|
|
if (pDocument == NULL)
|
|
{
|
|
TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n");
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
return;
|
|
}
|
|
ASSERT_VALID(pDocument);
|
|
|
|
BOOL bAutoDelete = pDocument->m_bAutoDelete;
|
|
pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong
|
|
CFrameWnd* pFrame = m_pdtModelDocTemplate->CreateNewFrame(pDocument, NULL);
|
|
pDocument->m_bAutoDelete = bAutoDelete;
|
|
if (pFrame == NULL)
|
|
{
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
delete pDocument; // explicit delete on error
|
|
return;
|
|
}
|
|
ASSERT_VALID(pFrame);
|
|
|
|
pDocument->SetModifiedFlag();
|
|
pDocument->SetPathName( CString(_fnmApplicationPath + fnMdlFile), FALSE);
|
|
pDocument->SetTitle( CString(fnMdlFile.FileName() + ".mdl"));
|
|
|
|
char strError[ 256];
|
|
if( !((CModelerDoc *)pDocument)->CreateModelFromScriptFile( fnScriptFile, strError))
|
|
{
|
|
pDocument->OnCloseDocument(); // explicit delete on error
|
|
AfxMessageBox( CString(strError));
|
|
return;
|
|
}
|
|
m_pdtModelDocTemplate->InitialUpdateFrame(pFrame, pDocument, TRUE);
|
|
}
|
|
|
|
void CModelerApp::OnFileNew()
|
|
{
|
|
// call file requester for opening documents
|
|
CDynamicArray<CTFileName> afnCreateModel;
|
|
_EngineGUI.FileRequester( "Create new model from 3D or script file",
|
|
"3D objects and scripts\0*.lwo;*.obj;*.3ds;*.scr\0"
|
|
FILTER_3DOBJ FILTER_LWO FILTER_OBJ FILTER_3DS FILTER_SCR FILTER_ALL FILTER_END,
|
|
"Create model directory", "Models\\", "", &afnCreateModel);
|
|
// create new models
|
|
FOREACHINDYNAMICARRAY( afnCreateModel, CTFileName, itModel)
|
|
{
|
|
// create new models
|
|
CreateNewDocument( itModel.Current());
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CModelerApp::OnFileOpen()
|
|
{
|
|
// call file requester for opening documents
|
|
CDynamicArray<CTFileName> afnOpenModel;
|
|
_EngineGUI.FileRequester( "Open model or script file",
|
|
"Model files (*.mdl)\0*.mdl\0"
|
|
"Script files (*.scr)\0*.scr\0"
|
|
"Model or script files (*.mdl; *.scr)\0*.mdl;*.scr\0"
|
|
"All files (*.*)\0*.*\0\0",
|
|
"Open model directory", "Models\\", "", &afnOpenModel);
|
|
|
|
// create new models
|
|
FOREACHINDYNAMICARRAY( afnOpenModel, CTFileName, itModel)
|
|
{
|
|
// we will use full file name to call OnOpenDocument()
|
|
CTFileName fnFullRequestedFile = _fnmApplicationPath + itModel.Current();
|
|
// choose right document template using file's extension
|
|
CDocTemplate *pDocTemplate = m_pdtModelDocTemplate;
|
|
BOOL bScriptDocument = FALSE;
|
|
if( fnFullRequestedFile.FileExt() == ".scr")
|
|
{
|
|
pDocTemplate = m_pdtScriptTemplate;
|
|
bScriptDocument = TRUE;
|
|
}
|
|
|
|
// Now we create document instance
|
|
CDocument* pDocument = pDocTemplate->CreateNewDocument();
|
|
if (pDocument == NULL)
|
|
{
|
|
TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n");
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
return;
|
|
}
|
|
ASSERT_VALID(pDocument);
|
|
|
|
// Model documents must be opened before view creation
|
|
if( !bScriptDocument)
|
|
{
|
|
if( !pDocument->OnOpenDocument( CString(fnFullRequestedFile)))
|
|
{
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
//delete pDocument; // explicit delete on error
|
|
return;
|
|
}
|
|
}
|
|
|
|
// View creation
|
|
BOOL bAutoDelete = pDocument->m_bAutoDelete;
|
|
pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong
|
|
CFrameWnd* pFrame = pDocTemplate->CreateNewFrame(pDocument, NULL);
|
|
pDocument->m_bAutoDelete = bAutoDelete;
|
|
if (pFrame == NULL)
|
|
{
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
delete pDocument; // explicit delete on error
|
|
return;
|
|
}
|
|
ASSERT_VALID(pFrame);
|
|
|
|
// Script documents must be opened after view creation
|
|
if( bScriptDocument)
|
|
{
|
|
if( !pDocument->OnOpenDocument( CString(fnFullRequestedFile)))
|
|
{
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
|
|
delete pDocument; // explicit delete on error
|
|
return;
|
|
}
|
|
}
|
|
|
|
pDocument->SetModifiedFlag( FALSE);
|
|
pDocument->SetPathName( CString(fnFullRequestedFile), TRUE);
|
|
pDocument->SetTitle( CString(fnFullRequestedFile.FileName() + fnFullRequestedFile.FileExt()));
|
|
pDocTemplate->InitialUpdateFrame(pFrame, pDocument, TRUE);
|
|
}
|
|
}
|
|
|
|
void CModelerApp::OnFilePreferences()
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CDlgPreferences dlg;
|
|
if( dlg.DoModal() == IDOK)
|
|
{
|
|
m_Preferences = dlg.m_Prefs;
|
|
// change wiew's background texture
|
|
CModelerView *pModelerView = CModelerView::GetActiveView();
|
|
if( pModelerView != NULL) {
|
|
pModelerView->m_fnBcgTexture = dlg.m_Prefs.ap_DefaultWinBcgTexture;
|
|
}
|
|
pModelerView = CModelerView::GetActiveMappingNormalView();
|
|
if( pModelerView != NULL) {
|
|
CModelerDoc *pDoc = pModelerView->GetDocument();
|
|
pDoc->UpdateAllViews( NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
int CModelerApp::ExitInstance()
|
|
{
|
|
m_Preferences.WriteToIniFile();
|
|
WriteProfileInt(L"Display modes", L"SED Gfx API", m_iApi);
|
|
return CWinApp::ExitInstance();
|
|
}
|
|
|
|
BOOL CModelerApp::AddModelerWorkingTexture( CTFileName fnTexName)
|
|
{
|
|
CBcgTexture *pNewWT = new CBcgTexture;
|
|
|
|
pNewWT->wt_FileName = fnTexName;
|
|
try
|
|
{
|
|
pNewWT->wt_TextureData = _pTextureStock->Obtain_t( fnTexName);
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
MessageBoxA( m_pMainWnd->m_hWnd, err_str, "Warning!", MB_OK|MB_ICONHAND|MB_SYSTEMMODAL);
|
|
if( pNewWT != NULL) delete pNewWT;
|
|
return FALSE;
|
|
}
|
|
pNewWT->wt_toTexture.SetData( pNewWT->wt_TextureData);
|
|
|
|
m_WorkingTextures.AddTail( pNewWT->wt_ListNode);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CModelerApp::AddModelerWorkingPatch( CTFileName fnPatchName)
|
|
{
|
|
FOREACHINLIST( CWorkingPatch, wp_ListNode, m_WorkingPatches, itPatch)
|
|
{
|
|
if( itPatch->wp_FileName == fnPatchName)
|
|
{
|
|
char achrMessage[ 256];
|
|
sprintf( achrMessage, "Working patch \"%s\" already exists.", (CTString&)fnPatchName);
|
|
AfxMessageBox( CString(achrMessage));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
CWorkingPatch *pNewWP = new CWorkingPatch;
|
|
pNewWP->wp_FileName = fnPatchName;
|
|
try
|
|
{
|
|
pNewWP->wp_TextureData = _pTextureStock->Obtain_t( pNewWP->wp_FileName);
|
|
}
|
|
catch( char *err_str)
|
|
{
|
|
MessageBoxA( m_pMainWnd->m_hWnd, err_str, "Warning!", MB_OK|MB_ICONHAND|MB_SYSTEMMODAL);
|
|
delete pNewWP;
|
|
return FALSE;
|
|
}
|
|
m_WorkingPatches.AddTail( pNewWP->wp_ListNode);
|
|
return TRUE;
|
|
}
|
|
|
|
const CTextureObject *CModelerApp::GetValidBcgTexture( CTFileName fnTexName)
|
|
{
|
|
const CTextureObject *ptoResult = NULL;
|
|
FOREACHINLIST( CBcgTexture, wt_ListNode, m_WorkingTextures, it_wt)
|
|
{
|
|
if( it_wt->wt_FileName == fnTexName)
|
|
{
|
|
return &it_wt->wt_toTexture;
|
|
}
|
|
}
|
|
if( !m_WorkingTextures.IsEmpty())
|
|
{
|
|
ptoResult = &(LIST_HEAD( m_WorkingTextures, CBcgTexture, wt_ListNode)->wt_toTexture);
|
|
}
|
|
return ptoResult;
|
|
}
|
|
|
|
const CTFileName CModelerApp::NextPrevBcgTexture( CTFileName fnTexName, INDEX iNextPrev)
|
|
{
|
|
INDEX ctTextures = m_WorkingTextures.Count();
|
|
ASSERT( ctTextures > 1);
|
|
|
|
CStaticArray<CTFileName> afnTemp;
|
|
afnTemp.New( ctTextures);
|
|
|
|
INDEX iCurrent = -1;
|
|
INDEX iIter = 0;
|
|
// add textures to static array and remember current texture's index by name
|
|
FOREACHINLIST( CBcgTexture, wt_ListNode, m_WorkingTextures, it_wt)
|
|
{
|
|
afnTemp[iIter] = it_wt->wt_FileName;
|
|
if( it_wt->wt_FileName == fnTexName)
|
|
{
|
|
iCurrent = iIter;
|
|
}
|
|
iIter++;
|
|
}
|
|
// texture must be found
|
|
ASSERT( iCurrent != -1);
|
|
// return
|
|
return( afnTemp[(iCurrent+ctTextures+iNextPrev) % ctTextures]);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAppPrefs routines
|
|
|
|
CAppPrefs::~CAppPrefs()
|
|
{
|
|
}
|
|
|
|
// Modeler ini read function for preferences
|
|
void CAppPrefs::ReadFromIniFile()
|
|
{
|
|
wchar_t strIni[ 128];
|
|
|
|
INI_READ( "Copy existing window preferences", "NO");
|
|
GET_FLAG( ap_CopyExistingWindowPrefs);
|
|
INI_READ( "Floor is visible by default", "YES");
|
|
GET_FLAG( ap_bIsFloorVisibleByDefault);
|
|
INI_READ( "Bcg is visible by default", "YES");
|
|
GET_FLAG( ap_bIsBcgVisibleByDefault);
|
|
INI_READ( "Set default colors", "YES");
|
|
GET_FLAG( ap_SetDefaultColors);
|
|
INI_READ( "Auto maximize window", "YES");
|
|
GET_FLAG( ap_AutoMaximizeWindow);
|
|
INI_READ( "Auto window fit", "YES");
|
|
GET_FLAG( ap_AutoWindowFit);
|
|
INI_READ( "Allways see lamp", "NO");
|
|
GET_FLAG( ap_AllwaysSeeLamp);
|
|
INI_READ( "Allow sound lock", "NO");
|
|
GET_FLAG( ap_bAllowSoundLock);
|
|
|
|
INI_READ( "Default ambient color", "0X3F3F3FFF");
|
|
GET_COLOR( ap_colDefaultAmbientColor);
|
|
|
|
INI_READ( "Default model heading", "180.0");
|
|
GET_FLOAT( ap_fDefaultHeading);
|
|
INI_READ( "Default model pitch", "0.0");
|
|
GET_FLOAT( ap_fDefaultHeading);
|
|
INI_READ( "Default model banking", "0.0");
|
|
GET_FLOAT( ap_fDefaultBanking);
|
|
INI_READ( "Default FOW", "90.0");
|
|
GET_FLOAT( ap_fDefaultFOW);
|
|
|
|
INI_READ( "Normal view ink color", "0X00000000");
|
|
GET_COLOR( ap_DefaultInkColor);
|
|
INI_READ( "Normal view paper color", "0XAAAAAAAA");
|
|
GET_COLOR( ap_DefaultPaperColor);
|
|
INI_READ( "Mapping view active surface color", "0X00000000");
|
|
GET_COLOR( ap_MappingActiveSurfaceColor);
|
|
INI_READ( "Mapping view inactive surface color", "0X80808000");
|
|
GET_COLOR( ap_MappingInactiveSurfaceColor);
|
|
INI_READ( "Mapping view paper color", "0XFFFFFFFF");
|
|
GET_COLOR( ap_MappingPaperColor);
|
|
INI_READ( "Mapping view win bcg color", "0XAAAAAAAA");
|
|
GET_COLOR( ap_MappingWinBcgColor);
|
|
|
|
INI_READ( "Default background texture", "");
|
|
ap_DefaultWinBcgTexture = CTString(CStringA(strIni));
|
|
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
}
|
|
|
|
// Modeler ini write function for preferences
|
|
void CAppPrefs::WriteToIniFile()
|
|
{
|
|
wchar_t strIni[ 128];
|
|
|
|
SET_FLAG( ap_CopyExistingWindowPrefs);
|
|
INI_WRITE( "Copy existing window preferences");
|
|
SET_FLAG( ap_bIsFloorVisibleByDefault);
|
|
INI_WRITE( "Floor is visible by default");
|
|
SET_FLAG( ap_bIsBcgVisibleByDefault);
|
|
INI_WRITE( "Bcg is visible by default");
|
|
SET_FLAG( ap_SetDefaultColors);
|
|
INI_WRITE( "Set default colors");
|
|
SET_FLAG( ap_AutoMaximizeWindow);
|
|
INI_WRITE( "Auto maximize window");
|
|
SET_FLAG( ap_AutoWindowFit);
|
|
INI_WRITE( "Auto window fit");
|
|
SET_FLAG( ap_AllwaysSeeLamp);
|
|
INI_WRITE( "Allways see lamp");
|
|
SET_FLAG( ap_bAllowSoundLock);
|
|
INI_WRITE( "Allow sound lock");
|
|
|
|
SET_COLOR( ap_colDefaultAmbientColor);
|
|
INI_WRITE( "Default ambient color");
|
|
|
|
SET_FLOAT( ap_fDefaultHeading);
|
|
INI_WRITE( "Default model heading");
|
|
SET_FLOAT( ap_fDefaultHeading);
|
|
INI_WRITE( "Default model pitch");
|
|
SET_FLOAT( ap_fDefaultBanking);
|
|
INI_WRITE( "Default model banking");
|
|
SET_FLOAT( ap_fDefaultFOW);
|
|
INI_WRITE( "Default FOW");
|
|
|
|
SET_COLOR( ap_DefaultInkColor);
|
|
INI_WRITE( "Normal view ink color");
|
|
SET_COLOR( ap_DefaultPaperColor);
|
|
INI_WRITE( "Normal view paper color");
|
|
SET_COLOR( ap_MappingActiveSurfaceColor);
|
|
INI_WRITE( "Mapping view active surface color");
|
|
SET_COLOR( ap_MappingInactiveSurfaceColor);
|
|
INI_WRITE( "Mapping view inactive surface color");
|
|
SET_COLOR( ap_MappingPaperColor);
|
|
INI_WRITE( "Mapping view paper color");
|
|
SET_COLOR( ap_MappingWinBcgColor);
|
|
INI_WRITE( "Mapping view win bcg color");
|
|
|
|
wcscpy( strIni, CString(ap_DefaultWinBcgTexture));
|
|
INI_WRITE( "Default background texture");
|
|
|
|
// Now for working textures
|
|
INDEX iWorkingTexturesCt = theApp.m_WorkingTextures.Count();
|
|
theApp.WriteProfileInt( L"Modeler prefs", L"Modeler working textures count",
|
|
iWorkingTexturesCt);
|
|
INDEX iWTCt = 0;
|
|
FOREACHINLIST( CBcgTexture, wt_ListNode, theApp.m_WorkingTextures, it_wt)
|
|
{
|
|
char strWTName[ 128];
|
|
sprintf( strWTName, "Working texture %02d", iWTCt);
|
|
theApp.WriteProfileString( L"Modeler prefs", CString(strWTName), CString(it_wt->wt_FileName));
|
|
iWTCt++;
|
|
}
|
|
|
|
// And now for patches....
|
|
INDEX iWorkingPatchesCt = theApp.m_WorkingPatches.Count();
|
|
theApp.WriteProfileInt( L"Modeler prefs", L"Modeler working patches count",
|
|
iWorkingPatchesCt);
|
|
INDEX iWPCt = 0;
|
|
FOREACHINLIST( CWorkingPatch, wp_ListNode, theApp.m_WorkingPatches, it_wp)
|
|
{
|
|
char strWPName[ 128];
|
|
sprintf( strWPName, "Working patch %02d", iWPCt);
|
|
theApp.WriteProfileString( L"Modeler prefs", CString(strWPName), CString(it_wp->wp_FileName));
|
|
iWPCt++;
|
|
}
|
|
}
|
|
|
|
int CModelerApp::Run()
|
|
{
|
|
int iResult;
|
|
CTSTREAM_BEGIN {
|
|
iResult=CWinApp::Run();
|
|
} CTSTREAM_END;
|
|
return CWinApp::Run();
|
|
}
|
|
|
|
CModelerView* CModelerApp::GetActiveView(void)
|
|
{
|
|
CModelerView *res;
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
res = DYNAMIC_DOWNCAST(CModelerView, pMainFrame->GetActiveFrame()->GetActiveView());
|
|
return res;
|
|
}
|
|
|
|
CModelerDoc *CModelerApp::GetDocument()
|
|
{
|
|
// obtain current view ptr
|
|
CModelerView *pModelerView = GetActiveView();
|
|
// if view does not exist, return
|
|
if( pModelerView == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
// obtain document ptr
|
|
CModelerDoc *pDoc = pModelerView->GetDocument();
|
|
// return it
|
|
return pDoc;
|
|
}
|
|
|