/* 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 #include #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; im_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 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 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 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; }